How to get originally granted scopes when renewing token in Auth0 Rules?

We have a rule configured that grants users custom scopes when they request an access token or renew a token. The rule basically reads the scopes in the request and then adds a list of our custom scopes based on the user metadata.

As an example, we do something like this:

const customScopes = ['foo:bar'];
const req = context.request;
// Retrieve scopes either from the parameters or body
const requestedScopeString = (req.query && req.query.scope) || (req.body && req.body.scope);
const grantedScopes = requestedScopeString ? requestedScopeString.split(' ') : [];
grantedScopes.push(...customScopes);

This method works perfectly fine for the initial request for a token: the user is granted their requested scopes as well as our custom scopes. However, this is not working correctly for renewing tokens. When there is a token renewal, we should be able to return the scopes granted in the initial request. But, the original scopes do not appear anywhere in the context or user objects. So what we end up doing is adding just our custom scopes, and the initially granted scopes are lost.

Is it possible to get the originally granted scopes when processing a token renewal? And if so, how do we get these scopes?

Hi @tommy1,

According to the refresh token doc:

Rules will run for the Refresh Token Exchange. To execute special logic, you can look at the context.protocol property in your rule. If the value is oauth2-refresh-token, then this is the indication that the rule is running during the Refresh Token Exchange.

Can you try checking if the there is anything related to that variable that is not getting run because it is a refresh exchange?

If you have a lot of permissions it may be worth looking into RBAC, but it is hard to say without knowing your exact use-case.

Thanks,
Dan

Hi Dan. We have no special logic based on the context.protocol property. I’ve logged the full context and user objects to look for the initially granted scopes and there is nothing there.

@tommy1,

Could you post the whole rule with any sensitive data scrubbed?

Thanks,
Dan

Here is the full rule with sensitive data scrubbed and certain fields renamed

function addApiScopeToAuthTokens(user, context, callback) {
    const CLAIM_KEY = '' // REMOVED

    const customScopesFilters = [
        // REMOVED
    ]

    // scopes granted to users by email
    const scopesByEmail = {
        // REMOVED
    }

    // Custom scopes granted to all valid users
    const defaultCustomScopes = [
        // REMOVED
    ]

    const extraCustomScopes = [
        // REMOVED
    ]

    const req = context.request
    // Retrieve scopes either from the parameters or body
    const requestedScopeString = (req.query && req.query.scope) || (req.body && req.body.scope)
    const requestedScopes = requestedScopeString ? requestedScopeString.split(' ') : []

    // Start with any non-custom scopes from the request, everyone gets these.
    const grantedScopes = requestedScopes.filter(scope => !customScopesFilters.some(filter => filter.test(scope)))

    if (context.clientMetadata && context.clientMetadata.some_metadata_field) {
        context.accessToken[CLAIM_KEY] = context.clientMetadata.some_metadata_field

        grantedScopes.push(...defaultCustomScopes)
    } else {
        if (user.app_metadata && user.app_metadata.some_metadata_field) {
            context.accessToken[CLAIM_KEY] = user.app_metadata.some_metadata_field
        }

        if (user.email_verified) {
            const emailBasedScopes = Object.keys(scopesByEmail).filter(scope => scopesByEmail[scope].test(user.email))
            grantedScopes.push(...defaultCustomScopes, ...extraCustomScopes, ...emailBasedScopes)
        }
    }

    context.accessToken.scope = [...new Set(grantedScopes)]
    callback(null, user, context)
}

Hi @tommy1,

I apologize for the delay in response on this. It must have slipped through the cracks.

Were you able to find a solution to this?

Thanks,
Dan

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