Skip to main content
Features and breaking changes released in versions of Triggers in the Login Flow are listed below.

v3 (GA)

Post-login

We strongly recommend upgrading and using the latest GA version (v3) of the post-login flow for the best user experience possible.

Breaking changes

  • api.redirect.canRedirect() marked as deprecated.
  • api.redirect.sendUserTo() will no longer skip redirecting when in a non-interactive flow. This means that calls to api.redirect.sendUserTo() should first check if the redirect is needed before issuing the redirect. Information like event.authentication.methods can be consulted to see if a redirect was successfully completed and recorded via api.authentication.recordMethod(). Attempting to trigger a redirect in a non-interactive flow will correctly trigger an interaction_required error.

New features

  • event.authentication.methods may now also contain custom methods completed by users within that session and recorded using api.authentication.recordMethod() from the onContinuePostLogin handler.
  • api.authentication.recordMethod() is added as a way to store a record for the completion of a custom method in the user’s session. These APIs allow you to strictly require custom factors for certain scenarios. The user (on a specific device) will be required to complete the custom factor, regardless of whether or not an interactive login is happening. If the conditions are met for requiring the custom factor and the user’s session doesn’t have a record of its completion, the interactivity of the flow shouldn’t influence whether the factor is required or not. For example, if you wanted to implement a required custom factor, you would set up the following:
    1. In onExecutePostLogin, search for a record in the event.authentication.methods array with the custom method’s identifier URL. If the method is there and has a current enough timestamp, allow the login to continue. Otherwise, trigger a redirect to the URL implementing the custom factor using api.redirect.sendUserTo(). Custom data can be encoded into a JWT and signed using api.redirect.encodeToken().
    2. When the user is redirected to /continue, the onContinuePostLogin handler will be invoked. Within that handler, validate any data coming back from the custom factor (if needed) and signal its completion by calling api.authentication.recordMethod().

v2 (GA)

Post-login

Breaking changes

Perform side effects
In the pre-GA version of the post-login trigger, side effects were performed by returning an object from an Action. In Actions GA, an api object is provided to encapsulate these changes and provide better in-editor type hints and inline documentation. Update user user_metadata Pre-GA Trigger:
async function myFunction(event, context) {
  return {
    user: {
      userMetadata: {
        myParam: "foo"
      }
    }
  };
}
GA Trigger:
async function onExecutePostLogin(event, api) {
  api.user.setUserMetadata('myParam', 'foo');
}
You should not use this method in callbacks because invoking this method won’t update metadata immediately. Instead, you can call this method several times throughout multiple Actions in the same flow (metadata set in one Action is applied to the transient object and is therefore available in subsequent Actions), and the engine will aggregate the changes and update the metadata all at once before the flow is completed.
Update user app_metadata Pre-GA Trigger:
async function myFunction(event, context) {
  return {
    user: {
      appMetadata: {
        myParam: "foo"
      }
    }
  };
}
GA Trigger:
async function onExecutePostLogin(event, api) {
  api.user.setAppMetadata('myParam', 'foo');
}
You should not use this method in callbacks because invoking this method won’t update metadata immediately. Instead, you can call this method several times throughout multiple Actions in the same flow (metadata set in one Action is applied to the transient object and is therefore available in subsequent Actions), and the engine will aggregate the changes and update the metadata all at once before the flow is completed.
Deny a login Pre-GA Trigger:
async function myFunction(event, context) {
  throw new Error("Access denied.");
}
GA Trigger:
async function onExecutePostLogin(event, api) {
  api.access.deny("Access denied.");
}
Throwing an error will also deny a login, but calling api.access.deny is the preferred approach.
Add Custom Claims to the Pre-GA Trigger:
async function myFunc(event, context) {
  return {
    accessToken: {
      customClaims: {
        'https://example.com/custom/claim': 'Custom claim value',
      }
    }
  };
}
GA Trigger:
async function myFunc(event, api) {
  api.accessToken.setCustomClaim('https://example.com/custom/claim', 'Custom claim value');
}
Add Custom Claims to the Pre-GA Trigger:
async function myFunc(event, context) {
  return {
    idToken: {
      customClaims: {
        'https://example.com/custom/claim': 'Custom claim value',
      }
    }
  };
}
GA Trigger:
async function myFunc(event, api) {
  api.idToken.setCustomClaim('https://example.com/custom/claim', 'Custom claim value');
}
Dynamically enable Pre-GA Trigger:
async function myFunction(event, context) {
  return {
    command: {
      type: "multifactor",
      provider: "any"
    }
  };
}
GA Trigger:
async function onExecutePostLogin(event, api) {
  api.multifactor.enable("duo");
}
Redirect the user Pre-GA Trigger:
async function myFunction(event, context) {
  return {
    command: {
      type: "redirect",
      url: "https://my-app.example.com"
    }
  };
}
GA Trigger:
async function onExecutePostLogin(event, api) {
  api.redirect.sendUserTo("https://my-app.example.com");
}
To ensure parameters are being sent securely and to avoid replay attacks, passing data via redirects has changed significantly in Actions GA. For more information, see Redirect with Actions.
Manipulate scopes
Although we experimented with providing direct manipulation of ID and Access Token scopes during the Actions Beta, we do not support this functionality in Actions GA.