Let's authenticate everything with JSON Web Tokens 🙌🙌🙌

I've been thinking about JSON Web Tokens (JWTs) a lot lately and maybe not everything, but with a little creativity, every reason for authenticating stuff I can think of can be done with JWTs.

Together, we'll look at how we can apply JSON Web Token validation to authenticate for multiple schemes such as Two-factor authentication using Passwordless Email and SMS Authentication, Access and Refresh Tokens without making major changes to your architecture.

Also, we'll focus on Pseudo-code rather than code ....

Cool?

Trust me, it doesn't get any cooler than this

Meow?

First, what are JSON Web Tokens?

JSON Web Tokens are encrypted strings that contain information that describe a user of a system, and the user's claims to that system.

Claims

For example, my NerdHands account JWT could contain claims such as my NerdHands Author ID, the Date the JWT was created, and its Expiry Date.

The browser can then pass the JWT to the NerdHands server to grant me access to my editor.

This article -> here -> does an awesome job of introducing you to JWTs if you still have questions.

So, shall we begin with Access Tokens?

This is perhaps the most popular application of JSON Web Tokens.

It basically goes like this:

  • A user performs basic authentication with username and password (or some variant of this).
  • If successful, a JSON Web Token is generated containing the UserId and maybe a role like standard-user or administrator.
  • This JWT string will be supplied for subsequent requests to the server.
  • When validating the JWT, the server will confirm that it is still valid, by checking its expiry date.
  • If valid, the server proceeds with the request, else it bounces the user with an appropriate response.

If a JWT is marked as invalid because it has expired, a new JWT has to be created by re-authenticating the user. This could mean the user needs to sign in again.

But does it have to?

Couldn't we somehow extend the authentication time while still maintaining authentication integrity?

This brings us to:

Refresh Tokens

Access Tokens expire for various reasons, and when they do, we need to bring them to life.

This is done with Refresh Tokens, which are token strings we can pass to an authentication server to retrieve a brand new access token.

Refresh Tokens can also be JWTs with the plot twist (yea) that its role attribute will be something like "refresh-token" so the server does not confuse it with an Access Token.

So when an Access Token is about to expire, pass the refresh token to an endpoint which:

  • Checks that the access-token and refresh-token are still valid
  • Checks that the access-token and refresh-token have the same user id claims
  • Creates and returns a new access-token JWT

Passwordless Email Authentication

When you want to get into a slack team, you have the option of authenticating via a magic link sent to your Email.

Pretty sweet feature!

So, how can we use JWTs for this too?

The magic link should contain a ... (say it along with me) ... JWT!!!

  • So we create a JWT containing the user's ID, and a role marked as "mail-token" or some other identifier that shows that the JWT is only to be used for Email Validation.
  • The JWT is placed in the query-string of a callback URL and embedded in the sign-in email sent to the user.
  • The user clicks on the URL, before rendering the page, the server confirms that the JWT is a "mail-token", is valid and contains the ID of a valid user.
  • If validation is successful, the server creates a new Access Token JWT for the user.

Take a moment to think about the implications of the ease of embedding this feature in your applications.

Passwordless SMS Authentication

This is popular in applications that perform user financial transactions like banking applications and third party apps like QuickTeller and Thrive-send (did I get that spelling right?).

A token made of digits is sent to the user's phone via SMS, and a form appears on the browser for the user to enter the digits sent to their phone within some allotted time (say 5 minutes?).

So how can we use JWTs for this?

The digits in the SMS code can be generated randomly, of course. I'll leave you to the details of that.

Now, encode that SMS code in a JWT also containing a UserId claim.

Be sure to encode the expiry date for the JWT with the future date when the SMS code becomes invalid.

Send the SMS Code to the user's phone, and place the JWT in the web page that is sent to the user. I'd suggest placing it in a web form hidden field that can be retrieved when submitted, but you could use cookies or session storage, whichever suits your architecture.

When the user enters the potential SMS code sent to his/her phone, the server can compare it when the SMS code placed in the JWT you created before and validate it.

Hey, guys ... We're in

Conclusion

JWTs carry information about the user's claims, so it's not necessary to maintain such state elsewhere.

This means if you're not currently using JWTs and you want to add them to your site, you don't need to make any changes to your DB structure.

This makes them perfect for stateless systems like REST APIs, and also easy to integrate with systems that keep state like MVC and other traditional session-based web architectures.

Show Comments