Oauth2 auth patterns
Skill goharabbas321/zeoel-framework/all-skills/oauth2-auth-patterns
OAuth 2.0 and OpenID Connect authentication patterns. Covers authorization code flow, PKCE, JWT, session management, and provider integration.From its SKILL.md
npx -y skills add goharabbas321/zeoel-framework --skill oauth2-auth-patternsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
4.3 KB, ~1.0k tokens by cl100k_base, as published. Nobody here has run it
OAuth2 & Authentication Patterns
Overview
Production patterns for implementing authentication using OAuth 2.0, OpenID Connect, JWT, and session-based auth. Covers social login integration, token management, and security best practices.
When to Use
- Implementing "Sign in with Google/GitHub/Apple"
- Building custom auth with JWT + refresh tokens
- Session-based authentication for server-rendered apps
- Multi-tenant applications with SSO
Authorization Code Flow with PKCE
// 1. Generate PKCE challenge
function generatePKCE() {
const verifier = crypto.randomBytes(32).toString('base64url')
const challenge = crypto.createHash('sha256').update(verifier).digest('base64url')
return { verifier, challenge }
}
// 2. Redirect to provider
app.get('/auth/login', (req, res) => {
const { verifier, challenge } = generatePKCE()
req.session.codeVerifier = verifier
const params = new URLSearchParams({
response_type: 'code',
client_id: CLIENT_ID,
redirect_uri: REDIRECT_URI,
scope: 'openid profile email',
state: crypto.randomBytes(16).toString('hex'),
code_challenge: challenge,
code_challenge_method: 'S256',
})
res.redirect(`https://provider.com/authorize?${params}`)
})
// 3. Handle callback
app.get('/auth/callback', async (req, res) => {
const { code, state } = req.query
// Exchange code for tokens
const tokenResponse = await fetch('https://provider.com/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
code: code as string,
redirect_uri: REDIRECT_URI,
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
code_verifier: req.session.codeVerifier,
}),
})
const { access_token, id_token, refresh_token } = await tokenResponse.json()
// Verify id_token, create session, store refresh_token securely
})
JWT Pattern
import jwt from 'jsonwebtoken'
// Create tokens
function createTokens(userId: string) {
const accessToken = jwt.sign(
{ sub: userId, type: 'access' },
process.env.JWT_SECRET!,
{ expiresIn: '15m' }
)
const refreshToken = jwt.sign(
{ sub: userId, type: 'refresh' },
process.env.JWT_REFRESH_SECRET!,
{ expiresIn: '7d' }
)
return { accessToken, refreshToken }
}
// Verify middleware
function authMiddleware(req, res, next) {
const token = req.headers.authorization?.replace('Bearer ', '')
if (!token) return res.status(401).json({ error: 'No token' })
try {
const payload = jwt.verify(token, process.env.JWT_SECRET!)
req.user = payload
next()
} catch {
return res.status(401).json({ error: 'Invalid token' })
}
}
// Refresh endpoint
app.post('/auth/refresh', async (req, res) => {
const { refreshToken } = req.body
try {
const payload = jwt.verify(refreshToken, process.env.JWT_REFRESH_SECRET!)
// Check if refresh token is revoked (stored in DB or Redis)
const isRevoked = await checkRevoked(refreshToken)
if (isRevoked) return res.status(401).json({ error: 'Token revoked' })
const tokens = createTokens(payload.sub)
// Rotate: revoke old refresh token
await revokeToken(refreshToken)
res.json(tokens)
} catch {
return res.status(401).json({ error: 'Invalid refresh token' })
}
})
Guidelines
- Always use PKCE for authorization code flow (even for confidential clients)
- Short-lived access tokens (15 min), long-lived refresh tokens (7 days)
- Rotate refresh tokens — revoke the old one when issuing a new one
- Store refresh tokens server-side (database or Redis), never in localStorage
- Use
httpOnly,secure,sameSitecookies for web session tokens - Verify
id_tokensignature before trusting claims
Anti-Patterns
- ❌ Storing JWTs in localStorage (XSS vulnerable)
- ❌ Long-lived access tokens (use refresh tokens instead)
- ❌ Not rotating refresh tokens (allows stolen tokens to persist)
- ❌ Skipping PKCE ("my app is server-side so I don't need it")
- ❌ Putting sensitive data in JWT payload (it's base64, not encrypted)
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.