9

The JWT specification describes only the payload and how it is sent, but leaves authentication protocol open, which allows the flexibility, but quite unfortunately, flexibility can lead to antipatterns and misdesign.

I'm looking for some well thought and tested enterprise patter for JWT authentication, which I could use or adapt, but I've failed to find something complete.

What I was thinking of is:

  • when no Authorization header is met, or the JWT token is invalid, or expired, send HTTP 401
  • in order to authenticate, use /login REST channel, send username and password as JSON object
  • in order to keep token alive, use /keepalive REST channel, call it every N (5) minutes, receive new JWT token and replace the existing one after each call (the token expires after M (15) minutes)

However, what disturbs me, is the necessity of that /keepalive channel. On the other hand, it forces me to prevent the authentication to expire, even if the user is away (the decision, if we would want keepalive is not yet met) and of course, those are extra calls and extra complication to protocol. What would be interesting, is that server automatically prolongs the token. In session-based environment it happens by resetting the timestamp, here, however, the server would have to sent new token, maybe not each time, but once the token is going to expire in R (say, 10) minutes. But placing it in response body would mean to modify the JSON response protocol (therefore, the solution is invasive and not transparent), and putting an extra HTTP header that client could process could not necessarily be a good pattern. I'd think about just placing Authentication Bearer xxxTOKENxxx header in Response if I'd have to choose...

Are there any ready enterprise patterns which answers my open points? Is my protocol draft a reliable idea? I'd prefer to use something ready than design from scratch.

1
  • 1
    Yes. JWT has led lots of people to implement homegrown 'protocols' and throw aside proven framework code. To get the right solution it's going to be important to be clear on requirements. Sounds like 'session' expiration is a requirement. Is forced log-out a requirement? i.e. where someone on the server side can say, log this user out, or a user can say log out all my sessions.
    – joshp
    CommentedNov 15, 2016 at 20:48

2 Answers 2

4

JWT (Intro to JSON Web Token) is just a token format, authentication it's something completely out of scope for that specification. It is indeed commonly used within authentication systems, but you could also use it for completely different scenarios so it makes sense to not include authentication specific constraints within that specification.

If you're looking for guidance on authentication you should refer to the OpenID Connect family of specifications. Additionally, if your system is comprised of HTTP API's and you're interested in providing delegated access to those API to your own or to third-party client application then you should refer to the OAuth 2.0 specification.

There are additional authentication related protocols like SAML and WS-Federation that are still widely used in enterprise scenarios, but they are significantly more complex to implement.

About your specific open points:

  • The bearer token authentication scheme is defined in RFC 6750 which contains instructions on how to perform requests and the possible error codes.
  • OAuth2 and OpenID Connect both contemplate the possibility and define the way to exchange a username/password with a token.
  • The problem of extending a self-contained/by-value token (JWT) lifetime is addressed within OpenID Connect and OAuth2 through the means of refresh tokens.

Even though OAuth2 and OpenID Connect can be seen as easier to implement than some of its predecessors, they are still complex enough to warrant some caution and only implement them yourself if you're willing to spend a considerable amount of time and resources. It's generally a better option to use third-party libraries or services that do that heavy-lifting for you.

Finally, these protocols cover a lot of scenarios so they may be overkill in some situations.

1
  • 2
    +1 for warranting caution & a complete answer to the implied question rather than the written one.
    – Paul
    CommentedNov 16, 2016 at 14:05
3

I don't think you need a keepalive channel. Your payload can (and is recommended to) contain expiry information provided by the server (in the exp key, per the standard) when the token is generated on login. If an expired token is used (which, obviously, is determined by the server, which only trusts what's in the token if the signature validates), the server simply rejects it with HTTP 401, prompting the client to re-authenticate.

Clients, meanwhile, can be proactive. The payload section is not encrypted, and since the client can read it the client can ascertain when a request will be sent with an expired token, and therefore call /login again if the token is expired.

Alternatively, REST allows for hypermedia information to be sent as 'an engine of state', and so if you want you could actually make your JWT's one-use only, and with an expiry as well. Every request, then, would generate a new JWT which is returned in the response to the client, either in the content or more likely in a response header, as hapi-auth-jwt2 does.