OAuth2 Fundamentals

OAuth2 Implementation

OAuth2 is the industry-standard protocol for authorization. It enables third-party applications to obtain limited access to user resources without exposing credentials.

Grant Types

Authorization Code Grant (with PKCE)

The recommended flow for public clients:

// PKCE code challenge generation

const crypto = require("crypto");

function generatePKCE() {

const verifier = crypto.randomBytes(32)

.toString("base64url");

const challenge = crypto.createHash("sha256")

.update(verifier)

.digest("base64url");

return { verifier, challenge };

}

// Authorization request

const { verifier, challenge } = generatePKCE();

const authUrl = `https://auth.example.com/authorize?

response_type=code&

client_id=app123&

redirect_uri=https://app.example.com/callback&

code_challenge=${challenge}&

code_challenge_method=S256&

scope=openid%20profile`;

// Token exchange

async function exchangeCode(code, verifier) {

const resp = await fetch("https://auth.example.com/token", {

method: "POST",

headers: { "Content-Type": "application/x-www-form-urlencoded" },

body: new URLSearchParams({

grant_type: "authorization_code",

code: code,

client_id: "app123",

code_verifier: verifier,

redirect_uri: "https://app.example.com/callback"

})

});

return resp.json();

}

Client Credentials Grant

For server-to-server communication:

import requests

def get_client_credentials_token(client_id, client_secret, scope):

resp = requests.post(

"https://auth.example.com/token",

data={

"grant_type": "client_credentials",

"client_id": client_id,

"client_secret": client_secret,

"scope": scope

},

headers={"Content-Type": "application/x-www-form-urlencoded"}

)

return resp.json()["access_token"]

Token Handling

Access Token Validation

// JWT verification middleware

const jwt = require("jsonwebtoken");

const jwksClient = require("jwks-rsa");

const client = jwksClient({

jwksUri: "https://auth.example.com/.well-known/jwks.json"

});

function verifyToken(req, res, next) {

const authHeader = req.headers.authorization;

if (!authHeader?.startsWith("Bearer ")) {

return res.status(401).json({ error: "Missing token" });

}

const token = authHeader.split(" ")[1];

jwt.verify(token, (header, callback) => {

client.getSigningKey(header.kid, (err, key) => {

callback(err, key.getPublicKey());

});

}, {

algorithms: ["RS256"],

issuer: "https://auth.example.com",

audience: "https://api.example.com"

}, (err, decoded) => {

if (err) return res.status(401).json({ error: "Invalid token" });

req.user = decoded;

next();

});

}

Refresh Token Rotation

def rotate_refresh_token(old_token):

Verify the old refresh token

token_data = verify_refresh_token(old_token)

Revoke the old token

revoke_token(old_token)

Issue new tokens

new_access = create_access_token(token_data["user_id"])

new_refresh = create_refresh_token(token_data["user_id"])

return {

"access_token": new_access,

"refresh_token": new_refresh,

"expires_in": 3600

}

Best Practices

oauth2_best_practices:

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- Always use PKCE for public clients

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- Use short-lived access tokens (15-60 minutes)

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- Implement refresh token rotation

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- Use RS256 or ES256 for JWT signing

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- Validate all claims (iss, aud, exp, nbf)

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- Store tokens securely (httpOnly cookies, secure storage)

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- Implement token revocation

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- Log all token issuance and usage

Conclusion

OAuth2 is complex but essential for modern authentication. PKCE makes authorization code flow safe for single-page apps. Use short-lived access tokens with refresh token rotation. Always validate tokens thoroughly on the server side. Keep your JWKS endpoint secure and rotate signing keys regularly.