Are request_scopes not set in Post Login action for Resource Owner Password Flow?

Summary

The issue I’m encountering is the Resource Owner password flow login does not cause the requested_scopes array to be initialized (from event.transaction.requested_scopes) for the Post Login actions.

Does anyone know if this is a bug or if the requested scopes are available in another object for the Post Login action for the Resource Owner code flow?

Details

I’m trying to perform the Resource Owner password flow login (per docs Call Your API Using Resource Owner Password Flow). I also have a Post Login Action that adds a custom claim to the id_token if a specific scope value is included in the login request. Specifically, requested scope values are provided to the action via the action event object in event.transaction.requested_scopes (per docs Actions Triggers: post-login - Event Object). The ultimate goal is to have this claim returned by the GET /userinfo API (per docs Authentication API Explorer).

However, the Resource Owner password flow appears to prevent this requested_scopes array from being provided to the action (when comparing it another flow like Authorization code flow).

Examples

An example of my request is as follows, with secret values obfuscated like {secretValueName}:

curl --location 'https://{myDomain}/oauth/token' \
--header 'content-type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'username={username}' \
--data-urlencode 'password={password}' \
--data-urlencode 'audience={apiAudience}' \
--data-urlencode 'scope=openid email' \
--data-urlencode 'client_id={myClientId}' \
--data-urlencode 'client_secret={myClientSecret}'

The JSON response to this cURL request looks like the following (with the JWTs obfuscated):

{
   "access_token": "{obfuscated JWT}",
   "id_token": "{obfuscated JWT}",
   "scope": "openid email",
   "expires_in": 43200,
   "token_type": "Bearer"
}

Here is a minimum viable example of my Post Login Action:

exports.onExecutePostLogin = async (event, api) => {

  const standardOpenIdScope = "openid";

  if (event.authorization
        && event.transaction
        && event.transaction.requested_scopes
        && event.transaction.requested_scopes.includes(standardOpenIdScope)) {

    const additionalMetadata = {
      "testMetadata": "testMetadataValue"
    };
    api.idToken.setCustomClaim("user_metadata", additionalMetadata);
  }
};

When I perform the GET /userinfo request using the access_token granted for the Resource Owner login flow, I get the following response. It is missing the user_metadata property that should’ve been set by the Action:

{
    "sub": "{obfuscated Auth0 Id}",
    "email": "{obfuscated Email}",
    "email_verified": true
}

As a counter example, here is the GET /userinfo response using an access_token granted from a normal Authorization Code flow login (per docs Authorization Code Flow); note the successful inclusion of the user_metadata property:

{
    "sub": "{obfuscated Auth0 Id}",
    "email": "{obfuscated Email}",
    "email_verified": true,
    "user_metadata": {
        "testMetadata": "testMetadataValue"
    }
}
1 Like

Hi @djfy,

I reviewed your Post Login action script and noticed that you used a non-namespaced custom claim ( user_metadata), which is not allowed when generating access tokens with an Auth0 API audience.

To avoid this conflict, you should use collision resistant namespaced custom claims.

Please refer to our Adding custom claims to tokens knowledge solution for an example.

Cheers,
Rueben

Hello Rueben,

Thank you for reviewing my post, but the issue with the Resource Owner login flow persists even with the incorporation of your suggestion to namespace the custom claim (see new Action script below); the Post Login action event object is not given the requested scope values (i.e., event.transaction.requested_scopes is not initialized) during Resource Owner login flows, preventing the namespaced custom claim from being added.

Is there something special that must be done for the Resource Owner login flow or is there another object accessible in the Post Login action that provides the scopes for the Resource Owner login flow?

New minimum viable Post-Login script and response examples

Note, the following snippet uses https://myapp.example.com as the namespace.
In my deployed Action, it is actually my API audience URL.

exports.onExecutePostLogin = async (event, api) => {

  const standardOpenIdScope = "openid";

  // Note - the follow namespace string is an example in this snippet.
  // In my deployed Action, it is actually my API audience URL.
  const namespace = 'https://myapp.example.com';

  if (event.authorization
        && event.transaction
        && event.transaction.requested_scopes
        && event.transaction.requested_scopes.includes(standardOpenIdScope)) {

    const additionalMetadata = {
      "testMetadata": "testMetadataValue"
    };
    api.idToken.setCustomClaim(`${namespace}/user_metadata`, additionalMetadata);
  }
};

GET /userinfo response examples

Using access_token from Resource Owner login flow

Even with namespacing the custom claim, the issue with the Resource Owner login flow persists since the Post Login action is not provided the request scopes via the event.transaction.requested_scopes object:

{
    "sub": "{obfuscated Auth0 Id}",
    "email": "{obfuscated Email}",
    "email_verified": true
}

Using access_token from Authorization Code flow

As before, a “typical” login flow results in the custom claim being added appropriately, indicating the event.transaction.requested_scopes object in the Post Login action is initialized for this login type.
Note, again, the namespace in this snippet is https://myapp.example.com. Again, it is actually my Audience URL in my deployed Post Login action:

{
    "sub": "{obfuscated Auth0 Id}",
    "email": "{obfuscated Email}",
    "email_verified": true,
    "https://myapp.example.com/user_metadata": {
        "testMetadata": "testMetadataValue"
    }
}
1 Like

Hi @djfy,

Thanks for your response.

It seems that the event.transaction.requested_scopes will not work for Client Credentials, Refresh Token, and Resource Owner Password Grant flows.

Instead, you can access the scopes by calling event.request.body.scope.

This is mentioned in this knowledge solution.

Let me know if you have any additional questions!

Thanks,
Rueben

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.