I have recently implemented the Resource Owner Password Grant flow for a machine-to-machine application, where only trusted apps are using this authentication method. In addition, the API expects stateless JWTs on the server-side. The question:
I cannot find any way to include username or email address as a claim to the access_token JWT using password grant. If I include the scope “openid” to the POST /token endpoint, it will return both an access_token and id_token, however the id_token doesn’t seem to work when the audience is set to the machine to machine API application.
Is what I am trying to do possible? Any help is greatly appreciated. Thanks!
If you are using the ROPG flow, you will get an ID token if the scope is openid. If you use both scope=openid and audience={your_api} then you get both an ID token and an access token that is valid both for your API and for the /userinfo endpoint.
The access token, by default, will only have the sub claim with the user’s ID. You can include user claims in the access token by using custom claims. In a rule you would do something like this:
function (user, context, callback) {
// only add the claims for this specific API
// you could add more checks/conditions if it makes sense
if (content.request.body && context.request.body.audience === '{your_api_identifier}') {
const namespace = 'https://mydomain.com/claims/';
context.accessToken[namespace + 'email'] = user.email;
}
}
Thank you for the response! Using a rule to add the custom claim to the access token worked like a charm. I also tried adding openid and using the id_token, which already had a user email claim, but for some reason on the server side that didn’t work. The access token method with custom claim works well though, thanks for the help.
Glad it worked. I wanted to clarify how to get an ID token (using scope=openid), but the audience (the entity meant to consume the token) is different in each case:
The audience of the ID Token is the client application requesting the token.
The audience of the Access Token is the target API (the one selected with the audience parameter)
Your API is correctly rejecting the ID Token because the aud (audience) claim is different to the expected API identifier value.
Thank you for the clarification. I just ran a test, and all worked as expected with the id_token if I change the audience parameter to a client id of the application. Again thanks for the assistance!
Sorry I wasn’t clear on that. The ID Token should not be used for authorization purposes (except for very special cases). You should configure the backend to the appropriate audience to check (that of the API) and use the access token for API requests.
Understood, my use case involves many different client applications potentially sending requests to the one API, so having a static audience in checkJwt on the server-side is a necessity anyway - the access_tomen with custom claim method fits perfectly.