Forward appState to application with lock

Cześć @konrad.sopala :wave:

I did some digging around, and eventually came to the following conclusions:

  • For my company’s use case, we have a universal login page with auth0-lock for the UI
  • appState can only be accessed and modified by the application (it’s managed by TransactionManager in auth0-spa-js, which is used by auth0-react). Therefore it’s not a suitable place to store something that the user can modify during logging in, unless one is using embedded login.
  • When using authorization code flow with pkce, state is no longer used for CSRF protection when handling redirect callback. However, it’s still used when generating code challenge. That means it’s impossible to straight up replace state param when instantiating lock with our base64 encoded extra user data. (that would be a hacky solution anyway)

It turns out this can be implemented with a custom param defined in auth.params of auth0-lock options.

new Auth0Lock(clientID, auth0Domain, {
  auth: {
    params: {
      customParam: "value"
    }
  }
});

Then, we can intercept that customParam from a rule and modify user’s profile & ID token:

function addPersistenceAttribute(user, context, callback) {
  const namespace = "https://example.com/";
  
  user.user_metadata = user.user_metadata || {};
  user.user_metadata.customParam = context.request.query.customParam || user.user_metadata.customParam;
  context.idToken[namespace + "customParam"] = user.user_metadata.customParam;

  if (context.request.query.customParam !== undefined) {
    auth0.users
      .updateUserMetadata(user.user_id, user.user_metadata)
      .then(function () {
        callback(null, user, context);
      })
      .catch(function (err) {
        callback(err);
      });
  } else {
    callback(null, user, context);
  }
}

So that solves it for my case :relieved:

1 Like