Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What is a JWT #23

Open
36 tasks
rishabhpoddar opened this issue Mar 5, 2022 · 3 comments
Open
36 tasks

What is a JWT #23

rishabhpoddar opened this issue Mar 5, 2022 · 3 comments
Assignees

Comments

@rishabhpoddar
Copy link
Member

rishabhpoddar commented Mar 5, 2022

Checklist

  • Define the outcome (value) that the post will have for the reader (i.e. what will they learn or gain)

  • Who is it for? (i.e. someone building auth - junior / senior, previous knowledge required etc, specific tech stacks)

  • Level of depth on the topic

  • Define real world application / relevance. Why is this topic important?

  • Writing the post

  • Define article title

  • Define meta title, meta description, meta image tags (for social)

  • Define meta title, meta description, meta image tags (for SEO)

  • Proof read

  • Adding title meta

  • Adding description meta

  • Adding OG meta

  • Added analytics for the following events to main-website

    • page_blog_article
    • page_blog_lastsection_markasdone
    • page_blog_discord_article
  • Adding to sitemap.xml

  • Release on test

    • Check landscape and portrait view of blog
  • Check for SEO (via SEO agent)

  • Release to prod

  • Clone the blog on

    • Medium
    • Hackernoon
    • Codementor
    • Dev.to
    • Dzone
    • Hashnode
    • lobste.rs
    • For each of these platforms, remember to put in the seo title, meta description, OG image and adding canonical tags.
  • Distribute on

    • Reddit
    • LinkedIn
    • HN
    • Slack (YC channel)
    • Medium
@rishabhpoddar
Copy link
Member Author

rishabhpoddar commented Mar 5, 2022

From SEO point of view, be sure to write about:

  • jwt rejected: user authentication failed (1k people searching this monthly) and it's insanely easy to rank for (0/100 - easiest score possible)
  • this jwt token doesn t support required scopes (1.1k people searching)
  • JWT decode (a whopping 42k people searching this and 8.6k for "JWT token decoder")

I think one good way to do this would be to add a section on "common problems with JWT" or something similar, and then list these as h2 or h3s

Overall outline: https://docs.google.com/document/d/1vE3x1myMvBY1GyYXg2TD0RB3ZM1LnyiqoOL29YsOhcQ/edit#

@rishabhpoddar rishabhpoddar mentioned this issue Mar 5, 2022
6 tasks
@rishabhpoddar rishabhpoddar self-assigned this Mar 8, 2022
@rishabhpoddar
Copy link
Member Author

Example of a JWT's creation, signing and verification process

1) Create a JSON

Let's take the following JSON:

{
    "userId": "abcd123",
    "expiry": 1646635611301
}

Notice that we have also added an expiry field (in milliseconds since epoch). We will see how this field is used during the verification process.

2) Create a JWT signing key and decide the signing algorithm

First, we need a signing key and an algorithm to use. We can generate a signing key using any secure random source. For the purpose of this post, let's use:

  • Signing key[^1]: NTNv7j0TuYARvmNMmWXo6fKvM4o6nv/aUi9ryX38ZH+L1bkrnD1ObOQ8JAUmHCBq7Iy7otZcyAagBLHVKvvYaIpmMuxmARQ97jUVG16Jkpkp1wXOPsrF9zwew6TpczyHkHgX5EuLg2MeBuiT/qJACs1J0apruOOJCg/gOtkjB4c=
  • Signing algorithm: "HMAC + SHA256" or HS256.

3) Creating the "Header"

This contains the information about which signing algorithm is used. Like the payload, this is a also a JSON and will be appended to the start of the JWT (hence the name header):

{
    "typ": "JWT",
    "alg": "HS256"
}

4) Create a signature

  • First we remove all the spaces from the payload JSON and then base64 encode it to give us eyJ1c2VySWQiOiJhYmNkMTIzIiwiZXhwaXJ5IjoxNjQ2NjM1NjExMzAxfQ. You can try pasting this string in an online base64 decoder to retrieve our JSON.
  • Similarly, we remove the spaces from the header JSON and base64 encode it to give us: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
  • We concatenate both the base 64 strings, with a . in the middle like <header>.<payload>, giving us eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJhYmNkMTIzIiwiZXhwaXJ5IjoxNjQ2NjM1NjExMzAxfQ. There is no special reason to do it this way other than to set a convention that the industry can follow.
  • Now we run the Base64 + HMACSHA256 function on the above concatenated string and the secret to give us the signature:
    Base64URLSafe(
        HMACSHA256("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJhYmNkMTIzIiwiZXhwaXJ5IjoxNjQ2NjM1NjExMzAxfQ", "NTNv7j0TuYARvmNMmWXo6fKvM4o6nv/aUi9ryX38ZH+L1bkrnD1ObOQ8JAUmHCBq7Iy7otZcyAagBLHVKvvYaIpmMuxmARQ97jUVG16Jkpkp1wXOPsrF9zwew6TpczyHkHgX5EuLg2MeBuiT/qJACs1J0apruOOJCg/gOtkjB4c=")
    )
    
    Results in:
    3Thp81rDFrKXr3WrY1MyMnNK8kKoZBX9lg-JwFznR-M
    
    We base64 encode it only as a industry convention.

5) Creating the JWT

Finally, we append the generated secret like <header>.<body>.<secret> to create our JWT:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJhYmNkMTIzIiwiZXhwaXJ5IjoxNjQ2NjM1NjExMzAxfQ.3Thp81rDFrKXr3WrY1MyMnNK8kKoZBX9lg-JwFznR-M

6) Verifying the JWT

Once the client sends the JWT back to the server, the server does the following steps:

  • Fetches the header part of the JWT (eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9).
  • Does base64 decoding on it to get the plain text JSON: {"typ":"JWT","alg":"HS256"}
  • Verifies that the typ field's value is JWT and the alg is HS256. If not, it would reject the JWT.
  • Fetches its secret key and runs the same Base64URLSafe(HMACSHA256(...)) operation as step number (4) on the header and body of the incoming JWT. Note that if the incoming JWT's body is different, this step will generate a different signature than in step (4).
  • Checks that the generated signature is the same as what signature in the incoming JWT. If it's not, then the JWT is rejected.
  • We base64 decode the body of the JWT (eyJ1c2VySWQiOiJhYmNkMTIzIiwiZXhwaXJ5IjoxNjQ2NjM1NjExMzAxfQ) to give us {"userId":"abcd123","expiry":1646635611301}.
  • We reject the JWT is the current time (in milliseconds) is greater then the JSON's expiry time (since the JWT as expired).

We can trust the incoming JWT only if it passes all of the checks above.

To summarize, a JWT is a token that is sent from the server to the client, so that the client can be identified in a secure and trusted manner when making API calls. The security and trust comes due to the signing and verification process.

@rishabhpoddar
Copy link
Member Author

@rishabhpoddar rishabhpoddar mentioned this issue Mar 23, 2022
10 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant