DEV Community

Brent Dalling
Brent Dalling

Posted on • Updated on • Originally published at brentdalling.com

JWT's for authentication

Hi there! I'm Brent. I'm a senior software developer with 8 years of professional experience. I've written software professionally in Java, JS/TS, PHP, C#, Python, Swift, Obj_C, Vue, React, Laravel, CodeIgniter, Ionic, SwiftUI, and many more languages or frameworks. I'm learning more every day. Just like you! My articles explain my thought process, opinions, and outlook. They're not the views of my employer. Just my own.

JWT's for authentication

It's a relatively common question. But, let's back up for a moment. Since the early days of computing we've needed some sort of user authentication and role/permission management. Early forms of this used local storage on hard-disks.

State-ful Sessions

As networking evolved, and peer-to-peer networking emerged, we started needing access to resources not stored on our local hard disk. These resources also needed some sort of authentication. Thus, the concept of remote authentication and user sessions was born.

Remote authentication needed to make sure that user sessions were secure, revocable, and relatively friction-less. For years, frameworks like .NET, Laravel, CodeIgniter, and basic language built features like the PHP Session used local storage to place a session file. This file would be used to verify a session cookie claim and find session information related to the user. (see sources - Advanced PHP Sessions) These sessions would send a cookie with the sessionId name and the client-side would send this sessionId cookie back to the server with every request.

When a request was made to the server the sessionId would be looked up and verified. This process slows down server responses potentially as it has to look linearly through the file system until it find a file with the sessionId as the name. Once it found the file it would perform some sort of validation. Additionally, once the session was verified, the session would be loaded into a variable with access to all session attributes. This is how the PHP session works. This isn't necessarily how all sessions work across all languages and frameworks.

Enter JWT and state-less sessions

JWT's are very similar to the traditional session method. Except, instead of keeping a copy of the JWT on the server, the server would send the JWT to the front-end and require that the front-end passes the JWT to the server for each request. (this is much like the session cookie with PHP type sessions). The server then verifies the signature (part of the JWT structure. We will discuss this later.) and guarantees that the contents are valid. This can potentially reduce server load. Admittedly, not by much as the hashing can be performance intensive.

The JWT's are a signed state-less token that have three parts to them. The header, the payload, and the signature. The header contains information about how the token was hashed. The body contains encoded claims. The signature is the signed claims and header. Because the JWT is signed and is capable of being verified on the server it is capable of being a form of state-less session. This simply means that the server doesn't maintain this information between requests. Instead, the server decodes the JWT for every request and assigns/permits operations based on the contained claims.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJ1c2VyIjp7ImZpcnN0X25hbWUiOiJCcmVudCIsImxhc3RfbmFtZSI6I
kRhbGxpbmciLCJwcm9maWxlIjp7ImF2YXRhciI6Imh0dHBzOi8vLi4uLiIs
ImdpdGh1YiI6Imh0dHBzOi8vLi4uLiJ9LCJyb2xlIjoiYWRtaW4iLCJwZXJ
taXNzaW9ucyI6eyJjYW4tcmVhZC11c2VycyI6dHJ1ZSwiY2FuLXVwZGF0ZS1
1c2VycyI6ZmFsc2UsImNhbi1kZWxldGUtdXNlcnMiOmZhbHNlLCJjYW4tY3
JlYXRlLXVzZXJzIjpmYWxzZSwiY2FuLXNlbmQtbWVzc2FnZXMiOnRydWV9fX0
.1npfC1UPIIQRHj8aj_flqRU9IchB30Sc8WpGiRnoCms
Enter fullscreen mode Exit fullscreen mode

Line breaks added for readability

The JWT above contains all three sections. The header, body, and signature. The header contains information on the hashing algorithm. The body is the long middle section spanning several lines. The signature is the last section.

JWt's have public and private claims inside the body. Public claims correspond to the reserved keys. We'll not be talking about these as most developers won't be using them. (The sources for this article will contain the "JWT Handbook" which talks about this more in-depth.) Private claims are any claim that you add in a ad-hoc basis. These claims usually contain information about the service, user, and anything else you need your client-side to know about. You can usually find private claims like below contained in the body.

{
  "user": {
    "first_name": "Brent",
    "last_name": "Dalling",
    "profile": {
      "avatar": "https://....",
      "github": "https://...."
    },
    "role": "admin",
    "permissions": {
      "can-read-users": true,
      "can-update-users": false,
      "can-delete-users": false,
      "can-create-users": false,
      "can-send-messages": true
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Note that the above example contains absolutely no sensitive information. This is because the JWT itself can be considered insecure and the contents transparent. This is because of the JWT header. Remember, this is because the JWT header contains information on the hashing. This is a JWT requirement so that the token consumers can decode it and view the contents. This means that anyone can intercept or scrape these tokens and view the contents of them.

For this reason, JWT's should absolutely never contain sensitive information. Credit cards, social security numbers, drivers licenses, etc should never be exposed to the JWT. To do so would be to create massive Availability-based security issue. (Please see both the JWT Handbook and the CIA-Triad)

The JWT itself is secure. This is because the token is signed by a hashing algorithm using a private key on the server. This signed value is then stored as the signature. The last piece of the 3-part JWT. Only the server knows the key. And, therefore, the server is the only machine that can validate it. This isn't to say there are not ways around this. Of course there are. (please see JWT-Attacks for additional reading into advanced security issues with JWT's) But, from a developer and researcher point of view they are considered secure enough. They are secure enough that they are now baked into many frameworks, API's, and services. A JWT properly implemented has a low security risk.

JWT's properly implemented have one major security vulnerability. The developer implementing the standard or packages. If the developer places sensitive information, and exposes any of the CIA_Triad, then the developer has introduced a major privacy vulnerability. For this reason, I recommend that junior developers have their implementation reviewed.

In conclusion, JWT's are secure by nature. They provide a great state-less session standard. And, they're highly versatile and dependable. There's a reason the JWT has become a de-facto standard in client to server-side communications. It accomplishes the exact same goals as the old PHP session standards. But, it accomplishes this while removing the verification/lookup load from the server. I can recommend them when properly implemented. Happy coding!

Bibliography

Advanced PHP Sessions: https://canvas.seattlecentral.edu/courses/937693/pages/10-advanced-php-sessions
JWT Handbook: https://auth0.com/resources/ebooks/jwt-handbook/
CIA-Triad: https://www.techtarget.com/whatis/definition/Confidentiality-integrity-and-availability-CIA
JWT-Attacks: https://portswigger.net/web-security/jwt

Top comments (0)