Authentication is one of the core functions of applications on the internet today, one that many developers are familiar with. Yet, actually implementing authentication correctly requires understanding several standards and protocols.
Two of the most important of these authentication standards are OAuth and JWT (JSON Web Tokens).
Looking to make sense of OAuth and JWT? You’re in the right place. In this article we will cover:
- What OAuth is and the Pros and Cons of using it
- What JWT (JSON Web Tokens) is and the Pros and Cons
- How to use OAuth and JWT together effectively
Let’s dive in!
OAuth (Open Authorization) - often written as the latest version OAuth 2.0 - is a protocol that is used to authenticate a user via an authentication server.
One of the useful things about OAuth is that it enables you to delegate account access in a secure way without sharing credentials. Instead of credentials, OAuth relies on access tokens.
Using access tokens, a client application can verify the identity of the user that authenticated themselves.
Visually, the process looks like this:
When you implement “Sign in with Google” or “Sign in with Github”, you are using the OAuth 2.0 protocol!
Working with OAuth has some great benefits, including:
- It’s the accepted industry standard. This means that most authentication services will understand and use OAuth 2.0.
- There’s many plug-and-play OAuth options. Including services like “Sign in with Google” and “Sign in with Facebook” that are already set up to be consumed within your application.
- OAuth has well tested client libraries in almost all languages and web frameworks. This means that your language of choice can be used with OAuth
- It allows for decoupling of code. Your client application code is not affected by the authentication code.
- OAuth is very secure and battle tested. Due to its widespread nature, you can be rest assured that all security edge cases have been thought about by industry experts.
While OAuth is a great standard, there’s a handful of things to be mindful of when using it:
- OAuth can be complicated to understand if you are unfamiliar. There are several different OAuth flows and deciding which is right for you can be a challenge. Sometimes, you may even need to use multiple flows.
- It has lower end user privacy. The auth server knows all the sites that the end user has logged in into. For example, when a site uses Sign in with Google, Google would be able to keep track of when that site’s users are signing in or are active.
- It’s overkill in certain situations. If you are building a simple webapp that has one frontend and backend, then you don’t need the OAuth protocol. However, a lot of online tutorials and ready made auth solutions force you to implement this.
- No session management solution. Once the user is authenticated, the auth server simply returns a JWT which can be consumed by your application (as well will see later). However, after that step, the OAuth protocol doesn’t provide any support for specifying how to maintain the authenticated session between your app’s frontend and backend - this is totally up to the developer.
A JWT is a token that is generated by the authentication server and contains the end-user’s information (like their userID, email etc.). The information is in JSON format and can be efficiently verified by the client application using cryptography.
JWT is best used whenever you want to transmit some information to an untrusted client, in such a way that that client can verify the information contained in the payload themselves.
From the context of an auth server, an untrusted client is the application that the user is trying to use. From the context of the application’s backend, an untrusted client is the frontend code.
There’s some good reasons JWT is such a popular standard:
- They are self-contained. The JWT can contain the user’s details. So you don’t need to query a database / auth server for that information on each request.
- They offer strong security guarantees. JWTs are digitally signed which safeguards them from being modified by the client or an attacker.
- JWTs are stored only on the client. You generate JWTs on the server and send them to the client. The client then submits the JWT with every request. This saves database space.
- They are efficient and quick to verify. This is because JWTs don’t require a database lookup.
While JWTs are incredibly useful - it’s helpful to keep the following things in mind:
- You can’t revoke them without putting in a lot of extra engineering effort. This is because there is no db call when verifying them. In order to implement immediate revocation, you would need to implement JWT blacklisting which can be time consuming.
- It’s easy to create security bottlenecks while keeping one secret safe. If the signing key is compromised, the attacker can use that to create their own valid JWTs. This would allow them to spoof the identity of any user an application.
We’ve learned that OAuth and JWT are powerful standards for building authentication flows in applications. As it turns out - OAuth vs JWT doesn’t have to be either or - they can be used together!
When the authentication server successfully verifies a user’s credentials (via OAuth) it also needs to transmit the user details to the client application. In order for the client application to verify the details, JWTs can be used to ensure an efficient process.
This works by the OAuth server sending a JWT to the client (after the OAuth flow is complete) containing the end user’s information.
A typical JSON payload in the JWT sent by the OAuth server looks like the below (example from sign in with Google):
What do all these fields mean? Below is a quick summary using this particular example:
- iss: The issuer of the token (in this case Google)
- azp and aud: Client IDs issued by Google for your application. This way, Google knows which website is trying to use its sign in service, and the website knows that the JWT was issued specifically for them.
- sub: The end user’s Google user ID
- at_hash: The hash of the access token. The OAuth access token is different from the JWT in the sense that it’s an opaque token. The access token’s purpose is so that the client application can query Google to ask for more information about the signed in user.
- email: The end user’s email ID
- email_verified: Whether or not the user has verified their email.
- iat: The time (in milliseconds since epoch) the JWT was created
- exp: The time (in milliseconds since epoch) the JWT was created
- nonce: Can be used by the client application to prevent replay attacks.
- hd: The hosted G Suite domain of the user
As you can see, there is a lot of information transmitted from the OAuth server (Google in this case), to the client application! It’s worth mentioning that some of the fields in the above JSON payload are specific to Google (like hd). Other providers may have similar and have different content.
Since this is all in a JWT, the client application can verify the contents of this JSON and know that no one has manipulated this content.
Oftentimes we see developers asking whether to use “OAuth or JWT” for their authentication setup. In reality, OAuth and JWT are two different standards, with different uses, which can be used together with great effect. In fact, JWT is often used as part of the OAuth protocol.
At SuperTokens, we provide an auth solution that mitigates most of the cons of using OAuth and a JWT, including: