OAuth 2.0 & OpenID Connect — SKILL.md
Raw skill file that agents receive when using this skill
---
name: "OAuth 2.0 & OpenID Connect"
description: "Implement OAuth 2.0 and OIDC: Authorization Code + PKCE, Client Credentials, token management, refresh flows, security best practices, building your own OAuth provider, popular libraries (passport.js, authlib), and managed services (Auth0, Clerk, Keycloak)."
version: "1.0.0"
author: "skynet"
category: "dev"
agents: ["claude-code", "codex", "gemini"]
tags: ["oauth", "oidc", "authentication", "security", "pkce", "tokens"]
---
# OAuth 2.0 & OpenID Connect
---
name: "OAuth 2.0 & OpenID Connect"
description: "Implement OAuth 2.0 and OIDC: Authorization Code + PKCE, Client Credentials, token management, refresh flows, security best practices, building your own OAuth provider, popular libraries (passport.js,"
version: "1.0.0"
author: "skynet"
category: "dev"
tags: ["oauth", "oidc", "authentication", "security", "pkce", "tokens"]
---
I will start by checking the knowledge graph for any existing notes on OAuth 2.0 or OpenID Connect to ensure consistency and leverage any previously stored insights. call mcp_brain_rah_search_nodes(query="OAuth OIDC security")
### OAuth 2.0 & OIDC: The SaaS Security Reference
#### 1. OAuth 2.0 Flows: Strategic Selection
OAuth 2.0 is a framework of "grants" designed for different trust models.
| Flow | Primary Use Case | Trust Level | Security Requirement |
| :--- | :--- | :--- | :--- |
| **Auth Code + PKCE** | **Web/Mobile/SPA.** The standard for user-facing apps. | Medium/High | **PKCE is mandatory.** |
| **Client Credentials** | **M2M (Machine-to-Machine).** Service A → Service B. | High (Server) | Client Secret must be in a Vault. |
| **Device Code** | **CLIs, Smart TVs, IoT.** Input-constrained devices. | Medium | User approves via secondary device. |
| **Refresh Token** | **Session persistence.** Silent re-authentication. | High | Must be rotated and revoked on reuse. |
---
#### 2. Core Implementation: Authorization Code + PKCE
**PKCE (Proof Key for Code Exchange)** is required for all clients to prevent authorization code injection.
1. **Generate PKCE Pair:**
* `code_verifier`: Cryptographically random string (43–128 chars).
* `code_challenge`: `Base64URL(SHA256(code_verifier))`.
2. **Authorization URL:** Include `state` (CSRF protection), `code_challenge`, and `code_challenge_method=S256`.
3. **Token Exchange:** Send the original `code_verifier` to the `/token` endpoint. The server hashes it and compares it to the previously stored challenge.
**Token Storage Decision:**
* **Server-Side:** Use encrypted **HttpOnly, Secure, SameSite=Lax** cookies.
* **SPA/Frontend:** Do not use `localStorage` (XSS risk). Use a **BFF (Backend-for-Frontend)** pattern to manage tokens server-side.
---
#### 3. Token Management & Lifecycles
* **Access Tokens (AT):** Short-lived (15m–1hr). Should be JWTs if using stateless validation.
* **Refresh Tokens (RT):** Long-lived.
* **Rotation:** Issue a new RT on every use; invalidate the old one.
* **Revocation:** Provide a `/revoke` endpoint for user logout or security breaches.
* **Sliding Expiration:** Extend RT lifetime on activity, but set an absolute "Max Age" (e.g., 30 days).
---
#### 4. OpenID Connect (OIDC): Identity Layer
OIDC adds identity to OAuth.
* **ID Token:** A JWT containing `sub` (unique ID), `email`, and `name`. **Validate the signature (RS256) locally.**
* **Discovery:** Use the `/.well-known/openid-configuration` endpoint to find JWKS, token, and auth endpoints.
* **Nonce:** Use to prevent replay attacks by binding the ID token to the original request.
---
#### 5. Security Checklist
* **Redirect URI Validation:** Use strict string matching. **No wildcards.**
* **DPoP (Demonstrating Proof-of-Possession):** Binds tokens to a private key held by the client, neutralizing stolen bearer tokens.
* **HTTPS:** Mandatory for all redirects and endpoints.
* **CORS:** Restrict token endpoints to your specific frontend domains.
---
#### 6. Building Your Own OAuth Provider
If your SaaS exposes an API to 3rd party developers:
* **Scopes:** Use granular permissions (e.g., `reports:read`, `settings:write`).
* **Consent:** Build a clear UI showing exactly what data the developer is requesting.
* **Client Management:** Allow developers to cycle secrets and define allowed redirect URIs.
---
#### 7. Modern Ecosystem
* **Libraries:**
* **Node.js:** `Arctic` (minimalist), `Auth.js` (Next.js/React), `Lucia` (Session focus).
* **Python:** `Authlib` (comprehensive), `PyOIDC`.
* **Java:** `Spring Security OAuth2`.
* **Managed Services (Buy vs Build):**
* **Buy:** *Clerk, Auth0, Supabase Auth.* High speed-to-market, handles MFA/Security.
* **Build:** *Keycloak, Ory Hydra, FusionAuth.* High control, data residency compliance.
---
#### 8. Common Mistakes (Anti-Patterns)
* **Implicit Flow:** **Deprecated.** Use Auth Code + PKCE instead.
* **Infinite Lifetimes:** Never issue tokens that don't expire.
* **JWT as Session:** Storing sensitive, mutable data in JWTs is risky; use them for stateless auth only.
* **Missing State:** Failing to validate the `state` parameter leads to Login CSRF.
---
#### 9. Code Examples: Auth Code + PKCE
**Node.js (using `arctic`)**
```javascript
import { GitHub, generateState, generateCodeVerifier } from "arctic";
// 1. Redirect to Auth Provider
const state = generateState();
const codeVerifier = generateCodeVerifier();
const url = await github.createAuthorizationURL(state, codeVerifier, {
scopes: ["user:email"]
});
// STORE state & codeVerifier in an HttpOnly session cookie
res.appendHeader("Set-Cookie", `state=${state}; HttpOnly; Secure`);
res.redirect(url.toString());
// 2. Callback Handling
const code = req.query.code;
const storedState = req.cookies.state;
if (req.query.state !== storedState) throw new Error("CSRF Error");
const tokens = await github.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
```
**Python (using `Authlib` + FastAPI)**
```python
from authlib.integrations.starlette_client import OAuth
from fastapi import FastAPI, Request
oauth = OAuth()
oauth.register(
name='google',
server_metadata_url='https://accounts.google.com/.well-known/openid-configuration',
client_kwargs={'scope': 'openid email profile'}
)
@app.get('/login')
async def login(request: Request):
redirect_uri = request.url_for('auth_callback')
# Authlib handles PKCE and State generation automatically
return await oauth.google.authorize_redirect(request, redirect_uri)
@app.get('/callback')
async def auth_callback(request: Request):
token = await oauth.google.authorize_access_token(request)
user = token.get('userinfo')
return {"user": user, "at": token['access_token']}
```
I'd add this as: **OAuth 2.0 & OIDC Technical Reference** in **security, architecture** — want me to?
curl -s https://skills.skynet.ceo/api/skills/oauth2-oidc/skill.md