|
4 | 4 | "bytes" |
5 | 5 | "context" |
6 | 6 | "encoding/json" |
| 7 | + "fmt" |
7 | 8 | "image/png" |
8 | 9 | "time" |
9 | 10 |
|
@@ -113,24 +114,38 @@ func (p *provider) Validate(ctx context.Context, passcode string, userID string) |
113 | 114 | return status, nil |
114 | 115 | } |
115 | 116 |
|
116 | | -// RecoveryCode generates a recovery code for a user's TOTP authentication, if not already verified. |
117 | | -func (p *provider) RecoveryCode(ctx context.Context, id string) (*string, error) { |
| 117 | +// ValidateRecoveryCode validates a Time-Based One-Time Password (TOTP) recovery code against the stored TOTP recovery code for a user. |
| 118 | +func (p *provider) ValidateRecoveryCode(ctx context.Context, recoveryCode, userID string) (bool, error) { |
118 | 119 | // get totp details |
119 | | - // totpModel, err := db.Provider.GetAuthenticatorDetailsByUserId(ctx, id, constants.EnvKeyTOTPAuthenticator) |
120 | | - // if err != nil { |
121 | | - // return nil, fmt.Errorf("error while getting totp details from authenticators") |
122 | | - // } |
123 | | - // //TODO *totpModel.RecoveryCode == "null" used to just verify couchbase recoveryCode value to be nil |
124 | | - // // have to find another way round |
125 | | - // if totpModel.RecoveryCode == nil || *totpModel.RecoveryCode == "null" { |
126 | | - // recoveryCode := utils.GenerateTOTPRecoveryCode() |
127 | | - // totpModel.RecoveryCode = &recoveryCode |
128 | | - |
129 | | - // _, err = db.Provider.UpdateAuthenticator(ctx, totpModel) |
130 | | - // if err != nil { |
131 | | - // return nil, fmt.Errorf("error while updaing authenticator table for totp") |
132 | | - // } |
133 | | - // return &recoveryCode, nil |
134 | | - // } |
135 | | - return nil, nil |
| 120 | + totpModel, err := db.Provider.GetAuthenticatorDetailsByUserId(ctx, userID, constants.EnvKeyTOTPAuthenticator) |
| 121 | + if err != nil { |
| 122 | + return false, err |
| 123 | + } |
| 124 | + // convert recoveryCodes to map |
| 125 | + recoveryCodesMap := map[string]bool{} |
| 126 | + err = json.Unmarshal([]byte(refs.StringValue(totpModel.RecoveryCodes)), &recoveryCodesMap) |
| 127 | + if err != nil { |
| 128 | + return false, err |
| 129 | + } |
| 130 | + // check if recovery code is valid |
| 131 | + if val, ok := recoveryCodesMap[recoveryCode]; !ok { |
| 132 | + return false, fmt.Errorf("invalid recovery code") |
| 133 | + } else if val { |
| 134 | + return false, fmt.Errorf("recovery code already used") |
| 135 | + } |
| 136 | + // update recovery code map |
| 137 | + recoveryCodesMap[recoveryCode] = true |
| 138 | + // convert recoveryCodesMap to string |
| 139 | + jsonData, err := json.Marshal(recoveryCodesMap) |
| 140 | + if err != nil { |
| 141 | + return false, err |
| 142 | + } |
| 143 | + recoveryCodesString := string(jsonData) |
| 144 | + totpModel.RecoveryCodes = refs.NewStringRef(recoveryCodesString) |
| 145 | + // update recovery code map in db |
| 146 | + _, err = db.Provider.UpdateAuthenticator(ctx, totpModel) |
| 147 | + if err != nil { |
| 148 | + return false, err |
| 149 | + } |
| 150 | + return true, nil |
136 | 151 | } |
0 commit comments