JWT + OAuth2 + OIDC + PKCE Complete small Guide

작성자

카테고리:

← 피드로
DEV Community · Bhargav Patel · 2026-07-28 개발(SW)

The flow will be:

  1. Authentication foundation
  2. Session vs JWT
  3. JWT deep dive
  4. JWT security
  5. Access/Refresh tokens
  6. OAuth2 relationship with JWT
  7. End-to-end production flow
  8. PKCE
  9. Storage strategies
  10. summary

1. Authentication Fundamentals

Every secure application needs answers to two questions:

Authentication

“Who are you?”

Example:

User enters:

username
password
MFA

Enter fullscreen mode Exit fullscreen mode

System verifies identity.

Result:

User is Bhargav

Enter fullscreen mode Exit fullscreen mode

Authorization

“What are you allowed to do?”

Example:

User:
Bhargav

Permissions:

READ_ORDERS
CREATE_ORDER
DELETE_ORDER

Enter fullscreen mode Exit fullscreen mode

Authentication happens first.

Authorization happens after.

Authentication
      |
      v
Authorization

Enter fullscreen mode Exit fullscreen mode

2. Traditional Session-Based Authentication (Stateful)

Before JWT, applications commonly used sessions.

Flow

User logs in:

Browser
   |
   | username/password
   |
   v
Server

Enter fullscreen mode Exit fullscreen mode

Server creates:

Session ID = abc123

Enter fullscreen mode Exit fullscreen mode

Stores:

Database / Memory

abc123
 |
 |
User:
Bhargav
Role:
ADMIN

Enter fullscreen mode Exit fullscreen mode

Browser receives:

Cookie:

SESSION_ID=abc123

Enter fullscreen mode Exit fullscreen mode

Every Request

Browser sends:

GET /orders

Cookie:
SESSION_ID=abc123

Enter fullscreen mode Exit fullscreen mode

Server:

Receive Session ID

        |
        v

Search session storage

        |
        v

Find user

        |
        v

Allow request

Enter fullscreen mode Exit fullscreen mode

Problems with Sessions

1. Server maintains state

The server must remember:

Session ID
      |
      v
User Information

Enter fullscreen mode Exit fullscreen mode

2. Scaling problem

Imagine multiple servers:

             Load Balancer

          /              \

     Server A          Server B

Enter fullscreen mode Exit fullscreen mode

User logs in:

Server A

Session stored here

Enter fullscreen mode Exit fullscreen mode

Next request:

Server B

No session found

Enter fullscreen mode Exit fullscreen mode

Solutions:

  • Sticky sessions
  • Shared session database

3. JWT Authentication (Stateless)

JWT solves this by putting information inside the token.

JWT:

JSON Web Token

It is a compact, signed representation of claims between two parties.

Example:

eyJhbGciOiJIUzI1Ni...

Enter fullscreen mode Exit fullscreen mode

JWT vs Session

Session

Server stores user state:

Server

Session ID
    |
    v
User Data

Enter fullscreen mode Exit fullscreen mode

JWT

Token contains information:

JWT

Header
+
Payload
+
Signature

Enter fullscreen mode Exit fullscreen mode

Server does not need to store session information.

4. JWT Structure

A JWT has three parts:

HEADER.PAYLOAD.SIGNATURE

Enter fullscreen mode Exit fullscreen mode

Example:

xxxxx.yyyyy.zzzzz

Enter fullscreen mode Exit fullscreen mode

Part 1: Header

Contains metadata.

Example:

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

Enter fullscreen mode Exit fullscreen mode

Meaning:

JWT uses RSA SHA256 algorithm

Enter fullscreen mode Exit fullscreen mode

Part 2: Payload

Contains claims.

Example:

{
 "sub":"12345",
 "name":"Bhargav",
 "role":"ADMIN",
 "exp":1788888888
}

Enter fullscreen mode Exit fullscreen mode

Common claims:

Claim Meaning sub User identifier iss Token issuer exp Expiration time iat Issued time roles User permissions

Important

JWT payload is NOT encrypted.

Anyone can decode:

Base64 decode

Enter fullscreen mode Exit fullscreen mode

Therefore never store:

Password
Credit card
Secrets

Enter fullscreen mode Exit fullscreen mode

inside JWT.

Part 3: Signature

Signature proves:

“This token was created by a trusted issuer and was not modified.”

Example:

Authorization Server:

Header + Payload

        |
        v

Private Key

        |
        v

Signature

Enter fullscreen mode Exit fullscreen mode

Final JWT:

Header.Payload.Signature

Enter fullscreen mode Exit fullscreen mode

5. Public Key and Private Key

JWT commonly uses asymmetric cryptography.

Private Key

Secret.

Only authorization server owns it.

Example:

Okta Private Key

Enter fullscreen mode Exit fullscreen mode

Used for:

Signing JWT

Enter fullscreen mode Exit fullscreen mode

Public Key

Can be shared.

Example:

Spring Boot API

Enter fullscreen mode Exit fullscreen mode

uses:

Okta Public Key

Enter fullscreen mode Exit fullscreen mode

to verify.

Flow:

Okta

Private Key
     |
     |
     v
Sign JWT


Spring Boot

Public Key
     |
     |
     v
Verify JWT

Enter fullscreen mode Exit fullscreen mode

6. How JWT Validation Works

Client sends:

GET /orders

Authorization:

Bearer JWT_TOKEN

Enter fullscreen mode Exit fullscreen mode

Spring Boot receives:

HEADER.PAYLOAD.SIGNATURE

Enter fullscreen mode Exit fullscreen mode

Checks:

1. Signature Validation

Spring calculates:

Verify(
 Header + Payload,
 Public Key
)

Enter fullscreen mode Exit fullscreen mode

If valid:

Token came from trusted issuer

Enter fullscreen mode Exit fullscreen mode

2. Expiration

Checks:

exp

Enter fullscreen mode Exit fullscreen mode

Example:

{
 "exp":1788888888
}

Enter fullscreen mode Exit fullscreen mode

3. Claims

Checks:

Example:

role = ADMIN

Enter fullscreen mode Exit fullscreen mode

Allows:

DELETE /users

Enter fullscreen mode Exit fullscreen mode

7. Stateless Nature of JWT

JWT is called stateless because:

Server does not store:

User Session

Enter fullscreen mode Exit fullscreen mode

Every request contains:

All required information

Enter fullscreen mode Exit fullscreen mode

Example:

Request

+
JWT

=
Enough information

Enter fullscreen mode Exit fullscreen mode

Benefits:

  • Easy horizontal scaling
  • Works well with microservices
  • No central session storage

8. JWT Security Best Practices

Short-lived Access Tokens

Example:

Access Token:

5 minutes
15 minutes
1 hour

Enter fullscreen mode Exit fullscreen mode

Why?

If stolen:

Attacker has limited time

Enter fullscreen mode Exit fullscreen mode

9. Refresh Token

Problem:

If access token expires every 15 minutes:

User must login repeatedly.

Solution:

Refresh token.

Flow:

Access Token

expires

        |
        v

Refresh Token

        |
        v

Authorization Server

        |
        v

New Access Token

Enter fullscreen mode Exit fullscreen mode

Example:

Access Token:

15 minutes

Enter fullscreen mode Exit fullscreen mode

Refresh Token:

days/weeks

Enter fullscreen mode Exit fullscreen mode

10. OAuth2 Relationship With JWT

Important:

OAuth2 does not require JWT.

OAuth2 defines:

How to get access

Enter fullscreen mode Exit fullscreen mode

JWT defines:

How to represent the token

Enter fullscreen mode Exit fullscreen mode

Together:

OAuth2
   |
   |
   v
Access Token

   |
   |
   v

JWT Format

Enter fullscreen mode Exit fullscreen mode

11. OAuth2 Components

Resource Owner

User.

Client

Application requesting access.

Example:

Angular Application

Enter fullscreen mode Exit fullscreen mode

Authorization Server

Creates tokens.

Examples:

Okta
Google
Azure AD
Auth0

Enter fullscreen mode Exit fullscreen mode

Resource Server

API protecting resources.

Example:

Spring Boot API

Enter fullscreen mode Exit fullscreen mode

12. OAuth2 Production Flow

Architecture:

Browser

Angular

Spring Boot API

Okta

Enter fullscreen mode Exit fullscreen mode

Phase 1: Backend Startup

Spring Boot starts.

Configuration:

issuer-uri=https://okta.com/oauth2/default

Enter fullscreen mode Exit fullscreen mode

Spring calls:

GET

/.well-known/openid-configuration

Enter fullscreen mode Exit fullscreen mode

This is a REST API.

Response:

{
 "authorization_endpoint":"",
 "token_endpoint":"",
 "jwks_uri":""
}

Enter fullscreen mode Exit fullscreen mode

Spring learns:

Where are public keys?
How to validate tokens?

Enter fullscreen mode Exit fullscreen mode

Phase 2: User Login

Browser opens:

https://myapp.com

Enter fullscreen mode Exit fullscreen mode

Angular loads.

Angular checks:

Do I have token?

Enter fullscreen mode Exit fullscreen mode

If no:

Redirect:

Browser

      |
      v

Okta Login Page

Enter fullscreen mode Exit fullscreen mode

Phase 3: User Authentication

User enters:

Username
Password
MFA

Enter fullscreen mode Exit fullscreen mode

Important:

Password goes to:

Okta

Enter fullscreen mode Exit fullscreen mode

Not:

Angular
Spring Boot

Enter fullscreen mode Exit fullscreen mode

Phase 4: Authorization Code

Okta returns:

authorization_code

Enter fullscreen mode Exit fullscreen mode

Example:

callback?code=abc123

Enter fullscreen mode Exit fullscreen mode

Phase 5: Token Exchange

Application calls:

POST /token

Enter fullscreen mode Exit fullscreen mode

Okta returns:

Access Token (JWT)
Refresh Token

Enter fullscreen mode Exit fullscreen mode

Phase 6: API Request

Angular sends:

GET /orders

Authorization:
Bearer JWT

Enter fullscreen mode Exit fullscreen mode

Phase 7: Spring Validation

Spring verifies:

JWT Signature

using

Okta Public Key

Enter fullscreen mode Exit fullscreen mode

If valid:

Request allowed

Enter fullscreen mode Exit fullscreen mode

13. PKCE (Proof Key for Code Exchange)

Used mainly for:

Angular
React
Mobile Apps

Enter fullscreen mode Exit fullscreen mode

because they cannot store:

client_secret

Enter fullscreen mode Exit fullscreen mode

PKCE Memory Rule

Remember:

CREATE
HIDE
PROVE

Enter fullscreen mode Exit fullscreen mode

1. Create

Angular creates:

code_verifier

Enter fullscreen mode Exit fullscreen mode

Example:

ABC123_SECRET

Enter fullscreen mode Exit fullscreen mode

2. Hide

Creates:

SHA256(code_verifier)

Enter fullscreen mode Exit fullscreen mode

Result:

code_challenge

Enter fullscreen mode Exit fullscreen mode

Sends:

code_challenge

Enter fullscreen mode Exit fullscreen mode

to Okta.

Keeps:

code_verifier

Enter fullscreen mode Exit fullscreen mode

secret.

3. Prove

Later sends:

authorization_code

+

code_verifier

Enter fullscreen mode Exit fullscreen mode

Okta checks:

SHA256(verifier)

=

stored challenge

Enter fullscreen mode Exit fullscreen mode

If match:

Issue JWT

Enter fullscreen mode Exit fullscreen mode

14. Implicit Flow (Old)

Old SPA flow:

Browser

     |
     v

Authorization Server

     |
     v

JWT Token Directly

     |
     v

Angular

Enter fullscreen mode Exit fullscreen mode

Problem:

Token exposed to browser.

Risks:

  • Browser history
  • URL leaks
  • XSS attacks

15. Token Storage Options

Local Storage

Example:

localStorage.setItem(
 "token",
 jwt
)

Enter fullscreen mode Exit fullscreen mode

Pros:

  • Simple
  • Persistent

Cons:

  • Vulnerable to XSS

Session Storage

Removed when tab closes.

Better than local storage but still accessible by JavaScript.

Secure HttpOnly Cookie

Example:

Cookie:

SESSION=abc123

HttpOnly
Secure
SameSite

Enter fullscreen mode Exit fullscreen mode

JavaScript cannot access it.

More secure.

Common with:

Backend For Frontend (BFF)

Enter fullscreen mode Exit fullscreen mode

16. Modern Recommendation

For SPA applications:

Use:

Authorization Code Flow
+
PKCE

Enter fullscreen mode Exit fullscreen mode

Avoid:

Implicit Flow

Enter fullscreen mode Exit fullscreen mode

Summary

JWT

A signed token containing claims that allows stateless authentication and authorization.

Session

Stateful authentication where server stores user session information.

OAuth2

Framework for delegated authorization.

OIDC

Authentication layer built on OAuth2.

Discovery Document

Metadata endpoint that provides OAuth endpoints and public keys.

PKCE

Security mechanism that prevents authorization code theft by proving that the same client started and completed authentication.

Production SPA Flow

Angular
   |
   | PKCE Login
   |
Okta
   |
   | JWT
   |
Spring Boot
   |
   | Verify Signature
   |
Allow Request

Enter fullscreen mode Exit fullscreen mode

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다