I'm designing a JWT authentication workflow for a RESTful API which uses two kinds of tokens:

  • Phone token, a short-lived token - issued by completing an One-Time-Password challenge. Its task is to prove "ownership" of a phone. It carries the phone number.
  • Access token, a long-lived token - issued by providing a valid phone token. Its task is to provide the identity of the phone owner. It carries the user's ID.

Authentication flow

My question is how to structure those two tokens correctly and whether I should use two distinct signing keys for them?

From my understanding the subject (sub) of the phone token should be the phone number and the subject (sub) of the access token should be the user's ID. (Edit: I'm not even sure about that, how would the controller know how to interpret the number, i.e looking up the right resource? Wouldn't it be better to use strings like 'phone' and 'identity' for the subject and provide an additional 'id' field?)

What about the issuer field (iss), should this be something like http://example.com/phone and http://example.com/identity ?

What about the audience field (aud)? The phone token has a small audience, i.e only one or two services, should I specify them explictly? Like aud: ['identity', 'xyz']?

In case of of the access token the audience is quite broad, i.e many services which consume this token, and the audience might grow so I don't want to hardcode them into the token, otherwise I would have to issue new tokens everytime I add a service. How could I circumvent this?

I'd be very glad if you could suggest a possible structure and the reasoning behind it.


Disclosure: Answer provided by an Auth0 engineer.

I would question the need for two tokens as I don't see a strict requirement for the two of them. What you presented sounds very similar to a (SMS based) passwordless authentication mechanism and the result of an authentication procedure is usual one single thing that proves the identity of a user.

See also Authenticate users with a one-time code via SMS in a SPA for some sequence diagrams that cover this passwordless authentication flow.

Having only one token as the result immediately answers most of your questions:

  • Only one signing key to worry about
  • Only one token issuer to name
  • The sub claim in the token will refer to the identity the token is associated to

Now that you have a token that proves the identity of a user, you need to make some authorization decisions. Here is where access tokens come into play, specially when REST API's are involved. Using a bearer access token to authenticate calls into a HTTP API is indeed very easy to setup, given you only need to pass the token, the API validates it and that's it.

The most complex issue is how you get issued the access tokens... you could reuse the token that proves the user identity and in simple scenarios it's possible to live with this. However, in complex scenarios with multiple API's where access to one does not imply access to other and/or there are fine-grained authorizations decisions that need to be taken this gets messier. One of the points of caution is the one you mentioned, in order to prevent possible attacks where a token issued to API A is then tried against API B, each API should verify that the token was in fact issued to them, in the case of JWT's, this is done by checking the aud claim so the correct practice it to list every intended audience of the token.

Given that omitting audience is not a good choice, I would consider not having that many audiences in the first place and find a strategy to group API's (if you really have that many) under one audience designation.

All of this is also assuming you want to use self-contained access tokens (the JWT format would probably be the best). Instead you could use opaque reference tokens which would imply you would need to store associated information elsewhere and query it each time you want to validate a token.

  • thank you very much for your detailed answer, you're absolutely right about the audience. The articles and posts on Auth0 have been a great resource for everything related to authentication. The short lived phone token only serves for critical endpoints i.e changing account details, obtaining an access token etc.. Also I kept users and phones separate entities, i.e one can exist without the other in my database, this makes invites easy and transferring accounts from one phone number to another. – sled Oct 18 '16 at 22:06

Your Answer

