Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Password recovery intermittently fails when the User Account Recovery API V2 is used with challenge questions #22151

Closed
deshankoswatte opened this issue Jan 3, 2025 · 0 comments · Fixed by wso2-extensions/identity-governance#902

Comments

@deshankoswatte
Copy link
Member

deshankoswatte commented Jan 3, 2025

Description

When password recovery is performed via the User Account Recovery API V2 [1] using challenge questions [2], and the fix for [3] is applied, the password recovery managers are extracted, and the recoveryInformationDTO is retrieved as follows:

for (PasswordRecoveryManager manager : passwordRecoveryManagers) {
    tempDTO = manager.initiate(userClaims, tenantDomain,
            RecoveryUtil.buildPropertiesMap(initRequest.getProperties()));
    if (!(manager instanceof PasswordRecoveryManagerImpl)) {
        // Get the challenge question-based password recovery configurations.
        LOG.debug("Considering PasswordRecoveryManager to be ChallengeQuestionPasswordRecoveryManager " +
                "and retrieving question-based recovery configurations.");
        isQuestionBasedRecoveryEnabled = tempDTO.isQuestionBasedRecoveryEnabled();
        isQuestionBasedRecoveryAllowedForUser = tempDTO.isQuestionBasedRecoveryAllowedForUser();
    } else {
        // Get the configurations for notification password recovery manager.
        recoveryInformationDTO = tempDTO;
    }
}

With the above approach, the code executes correctly when the notification-based password recovery manager is the last member of the passwordRecoveryManagers list. However, if the security question-based password recovery manager appears as the last member of the list, the existing user recovery data will be invalidated at [4], and new recovery data based on security questions will be stored through [5]. This new recovery data is not utilized in the above-mentioned source code section, leading to an invalidated recoveryCode being returned in the init request. Consequently, if this recovery code is used in the recover request, it will fail with the following error message.

POST /api/users/v2/recovery/password/recover HTTP/1.1
accept: application/json
Content-Type: application/json
Authorization: Basic <BASE64_ENCODED_ADMIN_CREDENTIALS>
User-Agent: PostmanRuntime/7.43.0
Postman-Token: 814a1203-4ad6-46bd-8cef-ed7a56726a9a
Host: localhost:9443
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 80
 
{
"recoveryCode": "08e3f980-9196-4824-b5b8-f5591903d4e5",
"channelId": "1"
}
 
HTTP/1.1 406 Not Acceptable
X-WSO2-TraceId: da924670-f435-4ff0-bbc7-2f729bd7d1f7
Date: Fri, 03 Jan 2025 09:57:59 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Keep-Alive: timeout=60
Connection: keep-alive
Server: WSO2 Carbon Server
 
{"code":"UAR-10001","message":"Not Accepted","description":"Invalid Code '08e3f980-9196-4824-b5b8-f5591903d4e5'.","traceId":"da924670-f435-4ff0-bbc7-2f729bd7d1f7"}

The above logic should be reviewed and updated to ensure that invalidated recovery codes are not returned in the response.

[1] - https://is.docs.wso2.com/en/latest/apis/user-account-recovery-v2-rest-api/#tag/Password-Recovery
[2] - https://store.wso2.com/connector/identity-challenge-questions
[3] - #21106
[4] - https://github.com/wso2-extensions/identity-governance/blob/v1.9.6/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/internal/service/impl/UserAccountRecoveryManager.java#L1070
[5] - https://github.com/wso2-extensions/identity-governance/blob/v1.9.6/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/store/JDBCRecoveryDataStore.java#L114-L153

Steps to Reproduce

  • Set up challenge questions as described in the connector documentation attached above.
  • Enable notification-based recovery through the Console.
  • Create a user with both challenge questions and an email, ensuring that both methods can be utilized for recovery.
  • Initiate the init request with the username as follows:
curl --location 'https://localhost:9443/api/users/v2/recovery/password/init' \
--header 'accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic <BASE64_ENCODED_ADMIN_CREDENTIALS>' \
--data '{
  "claims": [
    {
      "uri": "http://wso2.org/claims/username",
      "value": "<username>"
    }
  ]
}'
  • Execute the recover request using the recoveryCode received from the above request:
curl --location 'https://localhost:9443/api/users/v2/recovery/password/recover' \
--header 'accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic <BASE64_ENCODED_ADMIN_CREDENTIALS> \
--data '{
  "recoveryCode": "<RECOVERY_CODE>",
  "channelId": "1"
}'

Note: This issue occurs intermittently. To reproduce it, you may need to restart the server multiple times, which changes the order of password managers in the source code section mentioned above.

Version

wso2is-7.0.0.83

Environment Details (with versions)

  • OS: Mac OS
  • Database: H2
  • Userstore: JDBC
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants