HeoLab
ToolsBlogAboutContact
HeoLab

Free developer tools with AI enhancement. Built for developers who ship.

Tools

  • JSON Formatter
  • JWT Decoder
  • Base64 Encoder
  • Timestamp Converter
  • Regex Tester
  • All Tools →

Resources

  • Blog
  • What is JSON?
  • JWT Deep Dive
  • Base64 Explained

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 HeoLab. All rights reserved.

Tools work in your browser. Zero data retention.

HomeBlogUnderstanding OAuth 2.0 and OpenID Connect: A Developer's Guide
Table of Contents▾
  • OAuth 2.0 vs OpenID Connect
  • The Players
  • Authorization Code Flow (The Right Way)
  • PKCE — Proof Key for Code Exchange
  • Token Types
  • Scopes
  • Client Credentials Flow
  • Validating JWTs
security#oauth#authentication#security

Understanding OAuth 2.0 and OpenID Connect: A Developer's Guide

How OAuth 2.0 and OIDC actually work — authorization code flow, PKCE, access tokens, refresh tokens, and when to use each grant type.

Trong Ngo
February 23, 2026
3 min read

OAuth 2.0 powers "Sign in with Google", "Login with GitHub", and most API authorization. Understanding it prevents critical security mistakes. This guide explains the flows that matter without the RFC jargon.

OAuth 2.0 vs OpenID Connect

These are often confused:

  • OAuth 2.0 — an authorization framework. Answers: "Can this app access your Google Drive?"
  • OpenID Connect (OIDC) — an identity layer on top of OAuth 2.0. Answers: "Who are you?"

OAuth 2.0 gives you an access token (to call APIs). OIDC additionally gives you an ID token (a JWT with user identity claims).

The Players

Resource Owner — the user (you)
Client         — the app requesting access (your web/mobile app)
Authorization Server — issues tokens (Google, GitHub, Auth0, your own server)
Resource Server      — the API being protected (Google Drive API, GitHub API)

Authorization Code Flow (The Right Way)

Used for server-side apps and SPAs with PKCE. This is the most secure flow:

1. User clicks 'Login with Google'

2. Client redirects to Authorization Server:
   GET https://accounts.google.com/o/oauth2/auth?
     response_type=code
     &client_id=YOUR_CLIENT_ID
     &redirect_uri=https://yourapp.com/callback
     &scope=openid email profile
     &state=RANDOM_CSRF_TOKEN
     &code_challenge=CODE_CHALLENGE          (PKCE)
     &code_challenge_method=S256             (PKCE)

3. User logs in and approves

4. Authorization Server redirects back:
   GET https://yourapp.com/callback?code=AUTH_CODE&state=RANDOM_CSRF_TOKEN

5. Client exchanges code for tokens (server-to-server):
   POST https://oauth2.googleapis.com/token
   { code, client_id, client_secret, redirect_uri, code_verifier }

6. Authorization Server returns:
   { access_token, refresh_token, id_token, expires_in }

7. Client uses access_token to call the API
   Authorization: Bearer ACCESS_TOKEN

PKCE — Proof Key for Code Exchange

PKCE (pronounced 'pixie') prevents authorization code interception attacks. Required for public clients (SPAs, mobile apps) since they can't store a client secret:

// 1. Generate a random code_verifier
const codeVerifier = crypto.randomBytes(32).toString('base64url');

// 2. Hash it to get code_challenge
const codeChallenge = crypto
  .createHash('sha256')
  .update(codeVerifier)
  .digest('base64url');

// 3. Send code_challenge in the auth request
// 4. Send code_verifier when exchanging the code
// The server verifies: SHA256(code_verifier) === code_challenge

Token Types

TokenFormatLifespanPurpose
Access TokenJWT or opaque15min – 1hrCall protected APIs
Refresh TokenOpaqueDays – monthsGet new access tokens
ID TokenJWT (OIDC only)ShortVerify user identity

Scopes

Scopes limit what the access token can do:

openid           — basic OIDC (required for ID token)
profile          — name, picture, locale
email            — email address
read:repos       — GitHub: read repositories
write:repos      — GitHub: write repositories
https://www.googleapis.com/auth/drive.readonly

Request only the scopes you need — users are more likely to approve minimal permissions.

Client Credentials Flow

For machine-to-machine communication (no user involved):

POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&scope=read:data

Use this for backend services calling each other, CI/CD pipelines, scheduled jobs.

Validating JWTs

When your API receives an access token JWT, verify it properly:

const { createRemoteJWKSet, jwtVerify } = require('jose');

const JWKS = createRemoteJWKSet(
  new URL('https://accounts.google.com/.well-known/jwks.json')
);

async function validateToken(token) {
  const { payload } = await jwtVerify(token, JWKS, {
    issuer: 'https://accounts.google.com',
    audience: 'YOUR_CLIENT_ID',
  });
  // payload is verified and typed
  return payload;
}

Never skip signature verification. Never trust the claims in an unverified JWT. Use the JWT Decoder and JWT Claims Validator tools to inspect tokens during development.

Try These Tools

JWT Decoder & Inspector

Decode and inspect JSON Web Tokens. View header, payload, and verify structure instantly.

JWT Claims Validator

Decode a JWT and validate exp, iat, nbf claims. Shows token age, expiry countdown, and validity.

Related Articles

The Developer's Guide to Password Security

4 min read

Content Security Policy (CSP): A Practical Guide for Developers

3 min read

How to Implement TOTP Two-Factor Authentication in Your App

3 min read

Back to Blog

Table of Contents

  • OAuth 2.0 vs OpenID Connect
  • The Players
  • Authorization Code Flow (The Right Way)
  • PKCE — Proof Key for Code Exchange
  • Token Types
  • Scopes
  • Client Credentials Flow
  • Validating JWTs

Related Articles

The Developer's Guide to Password Security

4 min read

Content Security Policy (CSP): A Practical Guide for Developers

3 min read

How to Implement TOTP Two-Factor Authentication in Your App

3 min read