okta / okta-signin-widget

HTML/CSS/JS widget that provides out-of-the-box authentication UX for your organization's apps
Other
375 stars 320 forks source link

multiOptionalFactorEnroll: true not respected when using recoveryToken #2277

Open josephbreihan opened 2 years ago

josephbreihan commented 2 years ago

I'm submitting a

Background info

With the multiOptionalFactorEnroll flag set to true, users prompted to enroll in MFA should be kicked back to the enrollment screen to enroll additional factors after successfully enrolling one factor. This works for the regular sign in flow but not when a recoveryToken is specified.

This issue was raised separately by two clients (see 01205997 and 01208760). We have HONOR_MFA_ENROLL_OPTION_AFTER_STATETOKEN_BOOTSTRAP enabled, but it doesn't have any affect on recovery tokens.

I've overloaded verifyRecoveryToken with the following to force the multiOptionalFactorEnroll flag to be sent to /authn/recovery/token :

var config = OktaUtil.getSignInWidgetConfig();
config.features.multiOptionalFactorEnroll = true;

var oktaSignIn = new OktaSignIn(config);

oktaSignIn.authClient.originalVerifyRecoveryToken = oktaSignIn.authClient.verifyRecoveryToken;
oktaSignIn.authClient.verifyRecoveryToken = function (opts) {
    opts.options = {
        "multiOptionalFactorEnroll": true
    };
    return this.originalVerifyRecoveryToken(opts);
}

oktaSignIn.renderEl({ el: '#okta-login-container' },
    OktaUtil.completeLogin,
    function(error) {
        // Logs errors that occur when configuring the widget.
        // Remove or replace this with your own custom error handler.
        console.log(error.message, error);
    }
);

I verified that this options block is accepted by the API with the following:

curl -v -X POST \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
  "recoveryToken": "dfpfN4ViT38AoVnRxoyp",
  "options": {
     "multiOptionalFactorEnroll": true
  }
}' "https://my-dev-tenant-id.okta.com/api/v1/authn/recovery/token"

which responds with:

{"stateToken":"00r5dmCKtjswENG03mBhj1SVSIUx6IF_LAzRF3QQB6","expiresAt":"2021-10-27T20:05:33.000Z","status":"RECOVERY","recoveryType":"PASSWORD","_embedded":{"user":{"id":"00u12pl9u7C2hlzjK5d7","passwordChanged":"2021-10-27T19:57:44.000Z","profile":{"login":"testguy@example.com","firstName":"Test","lastName":"Guy","locale":"en","timeZone":"America/Los_Angeles"},"recovery_question":null}},"_links":{"next":{"name":"answer","href":"https://my-dev-tenant-id.okta.com/api/v1/authn/recovery/answer","hints":{"allow":["POST"]}},"cancel":{"href":"https://my-dev-tenant-id.okta.com/api/v1/authn/cancel","hints":{"allow":["POST"]}}}}

and verified that unknown parameters are refused by the API with the following:

curl -v -X POST \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
  "recoveryToken": "dfp_yC3qxGKQ0Ugh9MN2",
  "options": {
     "invalidOption": true
  }
}' "https://my-dev-tenant-id.okta.com/api/v1/authn/recovery/token"

which responds with:

{"errorCode":"E0000003","errorSummary":"The request body was not well-formed.","errorLink":"E0000003","errorId":"oaeyuM_8jm_RLuetwI6klM8Iw","errorCauses":[]}

Expected behavior

A user that is not enrolled in MFA should be prompted to enroll. After they complete enrollment of one factor, they should be given the option to enroll in other factors or click the Finish button to redirect.

What went wrong?

Instead of prompting the user to enroll in additional factors, the Sign-In Widget ignores that multiOptionalFactorEnroll has been set to true and redirects immediately.

Steps to reproduce

Embedded screencasts:

  1. Normal login flow (multiOptionalFactorEnroll: true works as expected): a. Reset all factors b. Reset to temp password c. Login with temp password Image of normal flow working as expected

  2. Recovery flow (multiOptionalFactorEnroll: true is ignored): a. Reset all factors b. Reset with email recovery link c. Login with email recovery link Image of recovery flow not working correctly

Your environment

jaredperreault-okta commented 2 years ago

@josephbreihan Thanks for the thorough bug report! We'll look into it

Internal Ref: OKTA-441437