Is there a way to update the m2m access token so that the scopes are an array rather than a string

This is related to this request which I saw was closed - Change the scope from string to array format in access token. I have the same issue and was wondering if there is a way. We have an integration partner who requires the scopes to be an array rather than a string.

To be clear scopes in the m2m access token look like this:

"scope": "scope1 scope2"

We need them to look like this

"scope": [
  "scope1",
  "scope2"
]

@tyf I saw you commented on the original issue. Is this impossible or is there a way forward?

Hey @paul10 welcome to the community!

It’s not currently possible AFAIK, but what’s the use case? I’m curious as to why you need scopes in an array. I’d just love a use case so I can bounce ideas off folks internally :slight_smile:

Let me know!

Hi @tyf thanks for responding. We have an integration partner who is leveraging the JWT bearer flow for authentication to their api. We need to generate a JWT and pass it to them and they will respond with a bearer token we can use to make subsequent calls. They have some specific requirements for the JWT, one being that the scope attribute needs to be an array rather than a string. We were hoping to use Auth0’s M2M solution rather than generating and signing our own JWTs. Would it be possible to use a client credentials hook to change the datatype of the scope attribute to an array?

No problem @paul10 happy to help where I can!

Thanks for describing the use case, very helpful - I’m curious if there is any way for the consuming service to accept a value other than scope? My thinking is that you could write an Action for the client credentials exchange that would add a custom claim with the value of event.transaction.requested_scopes of the event object which will provide you with an array of the scopes requested. You would need to request the scopes explicitly in the request to /oauth/token, and they must be granted to the m2m at the API level in Auth0.

The request might look like:

curl --request POST \
  --url https://tenant_domain.us.auth0.com/oauth/token \
  --header 'content-type: application/json' \
  --data '{"client_id":"XXX","client_secret":"XXX", "scope": "read:appointments read:prescriptions create:appointments read:msg delete:appointments","audience":"https://test-api-endpoint","grant_type":"client_credentials"}'

Action:

exports.onExecuteCredentialsExchange = async (event, api) => {
  api.accessToken.setCustomClaim("scopes_array", event.transaction.requested_scopes);  
};

Resulting JWT:

{
  "scopes_array": [
    "read:appointments",
    "read:prescriptions",
    "create:appointments",
    "read:msg",
    "delete:appointments"
  ],
  "iss": "https://tenant_domain.us.auth0.com/",
  "sub": "PpSYjwerwer34535eE9Oxvu0s69O730d@clients",
  "aud": "https://test-api-endpoint",
  "iat": 1667497853,
  "exp": 1667584253,
  "azp": "PpSYjfy2yw87678QheE9Oxvu0s69O730d",
  "scope": "read:appointments read:prescriptions create:appointments delete:appointments read:msg",
  "gty": "client-credentials"
}

Let me know what you think!