Securing Our REST API with JWT & OAuth

Securing Our REST API with JWT & OAuth

When building a secure backend for a REST API, two key terms often come up: JWT (JSON Web Tokens) and OAuth. You might be wondering, what exactly are they, and why is everyone using them?

Let’s dive in, because as they say, ‘Don’t underestimate the power of OAuth and JWT. They’re the silent superheroes of security. Mind it!’😅

Quick Overview

JWT: Used for both authentication and authorization(i.e., it checks who you are and what you're allowed to do).

OAuth: Primarily used for authorization(it checks what you're allowed to do, but not necessarily who you are).

Now, let's dive deeper into these two technologies.


🛡️ JWT

What is JWT?

JWT was introduced by IETF (Internet Engineering Task Force), and it's a token-based authentication mechanism.

JWT (JSON Web Token) is a compact, URL-safe token format used for securely transmitting information between two parties.

It consists of three parts: the header (which specifies the signing algorithm), the payload (which contains the claims or user data), and the signature (used to verify the token's authenticity).

The cool thing about JWT is that it helps your app verify a user's identity without needing to store session data on the server. It's like a magic pass that says, "Yep, this person is who they say they are!”.

JWT in Real Life: Like a Concert Ticket!

Let’s break down how JWT works using a fun analogy:

Imagine you’re going to a concert. You buy a ticket (that's your JWT), and the ticket has three parts:

  • Header: Tells the venue how the ticket is signed.

  • Payload: Contains your info (like your name and seat number).

  • Signature: This is like a special stamp that proves the ticket is real.

  • When you enter the concert, you show your ticket at the gate (like a user making a request to a server with their JWT). The security (the server) checks the ticket’s signature to ensure it’s valid. If the signature matches, you're allowed in; otherwise, you’re turned away.

  • Just like a concert ticket, a JWT has an expiration. Once the concert is over (the JWT expires), you’ll need a new ticket (or JWT) to attend another concert (or make further requests). This ensures that only valid, unaltered tickets are accepted, keeping the concert secure and exclusive to those with proper access.

JWT Authentication Flow in Action:

  1. User Login (username, password):

    • The user submits their username and password to the Authentication Service (Auth Service) to log in.
  2. Validate Username and Password:

    • The Auth Service validates the username and password against its database. If the credentials are correct, the server proceeds to the next step.
  3. Generate JWT (Authentication Success):

    • After validating the credentials, the Auth Service creates a JWT containing user information (e.g., userId: "12345"). This token is signed using the Private Key to ensure its authenticity and integrity.
  4. Store JWT:

    • The Auth Service sends the JWT back to the Client (e.g., the user's browser or mobile app). This JWT can be stored locally (commonly in localStorage or cookies on the client-side).
  5. Send JWT with Requests:

    • For any subsequent requests, the Client includes the JWT in the HTTP request (typically in the Authorization header using the Bearer scheme):

      • Example: Authorization: Bearer <JWT>
  6. Verify JWT in Backend (Service 1):

    • The Service 1 (e.g., another backend service) receives the JWT with the request.

    • The service verifies the JWT's validity using the Public Key that corresponds to the Private Key used for signing the token.

    • It checks if the token is valid (e.g., correct signature, not expired, etc.).

  7. JWT Verification (using jwt.verify()):

    • The Service 1 uses a library like jwt.verify() (available in various languages, e.g., Node.js) to check the JWT.

    • The method verifies:

      • Whether the signature matches the public key (authenticity).

      • If the token is expired or revoked (validity).

      • Whether the claims in the token are as expected (like userId or roles).

  8. Access Authorized / Perform Operation:

    • Once the JWT is verified, Service 1 can trust the JWT as valid.

    • The service performs the requested operation, such as fetching or modifying user data.

    • The service may also check specific claims in the token (e.g., roles, permissions) to decide if the user is authorized to perform the requested operation.

  9. Example of JWT in Action

Let’s say you’re building an app where users log in. Here’s a simple flow:

Login Request:

POST /login
{
  "username": "johnDoe",
  "password": "securePassword123"
}

Server Response (JWT token):

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCIfds6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjM0NTY3ODkwLCJ1c2VybmFtZSI6InJvaG5kb2UiLCJpYXQiOjE2MzY4NTQ1ODl9.cTgRnm5T78YH3f1gqPlwv01oh4b7nk9ihgMRbQ1MR5o"
}

Subsequent Request (with the token):

GET /profile
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCIfds6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjM0NTY3ODkwLCJ1c2VybmFtZSI6InJvaG5kb2UiLCJpYXQiOjE2MzY4NTQ1ODl9.cTgRnm5T78YH3f1gqPlwv01oh4b7nk9ihgMRbQ1MR5o

Why JWT Rocks:

  • No Server-Side Storage: Since the token contains all the info needed, no session storage is required on the server.

  • Easy to Scale: It’s great for apps that need to scale because there’s no need to keep track of sessions.

  • Secure & Flexible: It’s both a lightweight and secure way to handle authentication. You can even encrypt the data inside the JWT!


🔑 OAuth

JWT may have been the go-to solution for authentication in the past, but today, OAuth is the preferred choice for secure authorization. As web apps become more interconnected and users expect seamless, safe experiences, OAuth has risen to the top. Unlike JWT, which focuses on confirming who you are and managing sessions, OAuth makes it easy and secure for third-party apps to access your data without ever needing your password. It powers features like Google, Facebook, and GitHub logins…. STOP, I won’t spoil all the fun just yet 😄😅

Let’s dive in and see why OAuth is the new standard for modern web security!

What is OAuth?

OAuth is a protocol for authorization — not authentication. It's like a bouncer at a club who only lets in people who have the right credentials but doesn’t check who those people are.

OAuth (Open Authorization) is an open standard for authorization that allows third-party applications to securely access a user’s resources without sharing their credentials.

OAuth is commonly used for social logins and other scenarios where an app needs to access resources on behalf of a user, ensuring security and privacy by not exposing passwords.

OAuth allows third-party apps to access your user’s data (like their Google Calendar or Facebook photos) without giving them your password.

Think of it like this:

  • You let a third-party app access your Google Drive, but instead of giving them your Google password, you give them a special "key" (the OAuth token).

  • That app can then use this key to access your Google Drive, but it can’t do anything outside the scope you’ve authorized (like accessing your Gmail).

OAuth Flow elements

  • User: The person granting permission to the app to access their data.

  • Application Client: The app or service requesting access (e.g., a mobile app or website).

  • Authorization Server: The server that authenticates the user and issues the authorization code and access token.

  • Authorization Page: The user interface where the user is asked to grant or deny permission.

  • Application Server: The backend of the app that exchanges the authorization code for an access token and makes API calls.

  • Resource (Source) Server: The server hosting the user's data (e.g., Google API, Facebook API).

OAuth 2.0 Authorization Code Flow

  1. User → Application Client:

    • The user opens the Application Client (e.g., a mobile app or web app) and initiates the action that requires access to a protected resource (e.g., user data from Google, Facebook, etc.).
  2. Application Client → Authorization Page:

    • The Application Client redirects the user to the Authorization Page (hosted by the Authorization Server). The URL typically includes the following:

      • client_id (the identifier of the application)

      • redirect_uri (where the user will be sent after granting permission)

      • scope (the permissions the app is requesting)

      • response_type=code (indicating the Authorization Code flow)

  3. User → Give Access by Clicking Allow → Authorization Page:

    • The Authorization Page presents the user with a login screen (if the user isn't logged in already) and asks them to grant access by clicking "Allow" or "Authorize" to give the Application Client permission to access their data.
  4. Authorization Page → Authorization Server:

    • After the user grants permission, the Authorization Page sends an authorization code to the Authorization Server. This step involves redirecting the user back to the Authorization Server with a code that confirms the user’s authorization.
  5. Authorization Server → Authorization Page:

    • The Authorization Server processes the request and, assuming the user has granted access, issues an authorization code that is sent back to the Authorization Page as part of the URL (e.g., https://client.com/callback?code=AUTHORIZATION_CODE).
  6. Authorization Page → Application Client:

    • The Authorization Page redirects the user back to the Application Client, passing the authorization code to the specified redirect_uri (e.g., https://client.com/callback?code=AUTHORIZATION_CODE).
  7. Application Client → Application Server:

    • The Application Client sends the authorization code it received from the Authorization Page to its Application Server to request an access token.
  8. Application Server → Authorization Server:

    • The Application Server sends a request to the Authorization Server's token endpoint, including:

      • The authorization code (received from the Authorization Page)

      • The client secret (to authenticate the app)

      • The redirect URI (for validation purposes)

  9. Authorization Server → Application Server:

    • The Authorization Server validates the request, ensuring the authorization code, client ID, and client secret are correct. If valid, it responds with an access token (and optionally a refresh token), which the Application Server can use to authenticate API requests.
  10. Application Server → Resource (Source) Server:

  • The Application Server now uses the access token to make authenticated requests to the Resource Server (e.g., Google API, Facebook API) to access the user's protected resources (like profile data, files, etc.).

Example of OAuth in Action

  1. User is redirected to Google for authentication:
GET https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&scope=email
  1. App exchanges authorization code for an access token:
POST https://oauth2.googleapis.com/token
Content-Type: application/x-www-form-urlencoded
{
  "code": "authorization_code",
  "client_id": "YOUR_CLIENT_ID",
  "client_secret": "YOUR_CLIENT_SECRET",
  "redirect_uri": "YOUR_REDIRECT_URI",
  "grant_type": "authorization_code"
}
  1. App makes a request to Google API using the access token:
GET /user/profile
Authorization: Bearer access_token

Implementing Google OAuth in Your MERN Stack

If you’re looking to integrate Google OAuth into your MERN stack application seamlessly, I’ve got you covered! By utilizing OAuth, you can enhance both the ease and security of user authentication in your app.

To make things easier for you, I’ve created a repository called OAuth-App on GitHub. This repository includes a step-by-step implementation of Google OAuth that you can directly use or adapt for your project.

With this, you’ll learn how to:

  • Configure Google APIs for OAuth 2.0.

  • Set up secure routes for login.

  • Retrieve user details with tokens to personalize the experience.

Visit the OAuth-App repository now and elevate the authentication mechanism of your MERN stack project with ease!
Don’t forget to cheer me up by giving Star to this repository.😊

Why OAuth is Awesome:

  • No Password Sharing: Users don’t need to share their username and password with third-party apps. Instead, they just grant specific permissions.

  • Granular Permissions: OAuth allows users to control exactly what an app can access (e.g., only Google Calendar, not Gmail).

  • Widely Supported: OAuth is supported by many identity providers like Google, Facebook, and GitHub, making it easy to integrate social logins.


🎯 JWT vs OAuth

FeatureJWTOAuth
PurposeAuthentication + AuthorizationAuthorization only
Who it’s forUser authentication (verifying identity)Giving apps access to user data without sharing passwords
Token TypeSelf-contained (stateless) tokenAccess token (issued by authorization server)
Use CaseVerifying the user (login)Allowing access to third-party apps (like Google Login)
ExampleJWT used for loginOAuth used for Google/Facebook login

By understanding how each works, you'll be able to choose the right tool for securing your app and protecting your users. Happy coding!

Feel free to drop any questions or thoughts in the comments below — I'd love to hear how you're using JWT and OAuth in your projects! 😊👨‍💻👩‍💻

Check out my Portfolio website for connecting with me or just to say Hi !!.

Did you find this article valuable?

Support Anurag's blog by becoming a sponsor. Any amount is appreciated!