Authentication Decision Tree

When your code receives an AuthnResult from the Direct Authentication API Calls, you should use code similar to the following to decide what to show the user next:

var next_interaction;

if (!result.completed_mfa) {
    if (!result.factor_id && !result.profile_id) {
        // Request an authentication factor. The user should input
        // an email address or phone number.
        next_interaction = 'add-factor';
        // After the user interaction, your code should call:
        // /aa/(string:id)/add-factor
    } else if (result.factor_id) {
        // Ask the user to enter the code sent to them
        // for authentication.
        next_interaction = 'enter-code';
        // After the user interaction, your code should call:
        // /aa/(string:id)/auth-uid
    } else {
        // Ask the existing user to sign in using their password.
        next_interaction = 'sign-in';
        // After the user interaction, your code should call:
        // /aa/(string:id)/auth-password
    }
} else if (!result.profile_id) {
    if (result.signup && result.signup.has_password) {
        // Ask the user to accept the terms of service and privacy policy.
        next_interaction = 'agreement';
        // After the user interaction, your code should call:
        // /aa/(string:id)/signup-finish
    } else if (result.signup && result.signup.name_checked) {
        // Ask the user to set a password.
        next_interaction = 'set-password';
        // After the user interaction, your code should call:
        // /aa/(string:id)/set-signup-data
        //
        // ALTERNATIVE:
        //
        // If the app is requesting access to closed loop cash only
        // (using ``/aa/signup-closed``), the app can choose not to
        // ask the user to set a password and jump directly
        // to the agreement form.
        //
        // next_interaction = 'agreement';
        //
        // After the user interaction, your code should call:
        // /aa/(string:id)/signup-finish
    } else {
        // Request the user's name.
        next_interaction = 'set-personal-name';
        // After the user interaction, your code should call:
        // /aa/(string:id)/set-signup-data
    }
} else {
    // The authentication flow is complete.
    next_interaction = 'authenticated';
    // The access token you need for most API calls
    // is now available as ``result.token.access_token``.
    //
    // If this is a password reset flow, you should prompt
    // the user for a new password and call:
    // /aa/(string:id)/reset-password
    //
    // If the user accepted an invitation, you should call:
    // /wallet/finish-invite
}

To optimize the user experience and avoid unnecessary user interactions and server round trips, your code should avoid calling the direct authentication API calls in an unchanging sequence. Ideally, your code should contain an implementation of this decision tree. Your code should be constructed as follows:

  1. Start an authentication attempt with POST /aa/signup, POST /aa/signin, POST /aa/reset, POST /aa/accept, POST /aa/signin-closed, or POST /aa/signup-closed. Receive an AuthnResult.
  2. Based on the most recent AuthnResult you received, your implementation of the decision tree should decide which interaction to perform with the user. For example, if the next_interaction as specified by the tree is enter-code, you should show a screen or dialog that asks the user to enter a code they received by email or SMS.
  3. At the end of the user interaction, call the API specified by the decision tree comments.
  4. If the API call succeeds, you will receive an updated AuthnResult; you should then loop back to step 2. If the password was incorrect or some other error occurred, the API call will respond with an InvalidRequest. You should display the error to the user and repeat the user interaction until it succeeds.

Flowchart

The image below is a flowchart representation of the decision tree. Click the image for full size.

_images/direct-auth-client-flow.png

Examples

This documentation includes some examples of using the decision tree.