0

When logging into Auth0:

POST https://my.auth0.com/oauth/ro
{
  "client_id":   "<client-id>",
  "username":    "me@gmail.com",
  "password":    "••••••••",
  "connection":  "<auth0-connection>",
  "grant_type":  "password",
  "scope":       "openid offline_access jti email",
  "device":      "<device-id>"
}
// Response
{
  "refresh_token": "<refresh-token>",
  "id_token": "<id-token>",
  "access_token": "<access-token>",
  "token_type": "bearer"
}
// id_token JWT payload
{
  "jti": "3d4c5e97-3543-4c53-b46e-3aa965cd5a34",
  "email": "me@gmail.com",
  "email_verified": false,
  "iss": "https://my.auth0.com/",
  "sub": "auth0|<id>",
  "aud": "<aud>",
  "exp": 1481766419,
  "iat": 1481730461
}

if I specify jti in my scope, the returned id_token, which is a JWT, will contain a jti. Having jti in a JWT is recommended by Auth0. jtis uniquely identify JWTs and can be used for things like blacklisting JWTs.

For some reason though, if I try getting a new id_tokenusing a refresh token:

POST https://my.auth0.com/delegation
{
  "client_id":       "<client-id>",
  "grant_type":      "urn:ietf:params:oauth:grant-type:jwt-bearer",
  "refresh_token":   "<refresh-token>",
  "api_type":        "app",
  "scope":           "openid offline_access jti email",
  "device":          "<device-id>"
}
// Response
{
  "token_type": "Bearer",
  "expires_in": 35958,
  "id_token": "<id-token>"
}
// id_token JWT payload
{
  "email": "me@gmail.com",
  "email_verified": false,
  "iss": "https://my.auth0.com/",
  "sub": "auth0|<id>",
  "aud": "<aud>",
  "exp": 1481766678,
  "iat": 1481730720,
  "azp": "<azp>"
}

even though I specify jti in my scope, the id_token returned does not contain a jti.

Is this a bug? Please help.

enamrik
  • 2,292
  • 2
  • 27
  • 42

1 Answers1

1

The jti claim is not generated or included by default. If you're seeing that behavior the most likely explanation is that you have a custom rule that is doing the following:

function (user, context, callback) {
  user.jti = require('uuid').v4();
  callback(null, user, context);
}

This means that when you include the jti as a scope that value gets included in the resulting ID Token because it's obtained from that property. When going through delegation the jti claims seems to receive special treatment and it's ignored when you do the refresh. The use of delegation for refresh is discouraged, however, if you want to continue with that approach and just need a unique identifier within the JWT, if you use a non-reserved claim name you may be able to workaround this. For example, in a rule:

function (user, context, callback) {
  user.myjti = require('uuid').v4();
  callback(null, user, context);
}

Then on both requests include the myjti scope; a quick test showed that this works also when using delegation.

João Angelo
  • 56,552
  • 12
  • 145
  • 147
  • thanks! You were right, there was a rule setting jti. What endpoint should I use to get a new id_token using my refresh_token? I tried https://dev-innit.auth0.com/oauth/token with {grant_type:"refresh_token",refresh_token:} and I get unsupported_grant_type. I'd rather use the correct endpoint than create my own JWT ID property. – enamrik Dec 15 '16 at 20:26
  • In order to use `/oauth/token` with a grant type of `refresh_token` you would need to enable the *OAuth 2.0 API Authorization* in the advanced account settings and then also possible enable the *OIDC Conformant* flag at the client application level. However, despite doing that I don't believe rules are currently supported when refreshing through the token endpoint so you would not be able to add the claim to the value. For now, the custom claim name and the use of delegation endpoint is what's available. – João Angelo Dec 16 '16 at 16:08
  • Thanks, that was really clear and straight forward. I'll go with the `/delegation` endpoint then until `/oauth/token` supports custom claims. – enamrik Dec 16 '16 at 21:15