
Oauth Implementation
- 504 installs
- 305 repo stars
- Updated March 4, 2026
- aj-geddes/useful-ai-prompts
oauth-implementation is a Claude skill that implements secure OAuth 2.0, OpenID Connect, JWT authentication, refresh tokens, session management, and SSO integration for web, mobile, and API applications.
About
oauth-implementation is a Claude skill from aj-geddes/useful-ai-prompts that guides secure auth system construction using OAuth 2.0 and OpenID Connect with JWT access tokens, refresh tokens, and session management. It applies when building user authentication, third-party API authorization, or single sign-on across web and mobile clients. The skill includes overview, quick start, reference guides, and best practices for token lifecycle and secure flows. Developers reach for oauth-implementation when adding login to a new API, integrating an identity provider, or replacing ad-hoc session cookies with standards-based OIDC and JWT patterns.
- Complete OAuth 2.0 and OpenID Connect (OIDC) server implementation
- JWT token handling with refresh tokens and secure session management
- Supports user authentication, third-party API integration, SSO, social login, and microservices security
- Production-ready patterns for web and mobile applications
- Includes registration, authorization code, and token exchange flows
Oauth Implementation by the numbers
- 504 all-time installs (skills.sh)
- Ranked #825 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/aj-geddes/useful-ai-prompts --skill oauth-implementationAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 504 |
|---|---|
| repo stars | ★ 305 |
| Last updated | March 4, 2026 |
| Repository | aj-geddes/useful-ai-prompts ↗ |
How do you implement OAuth 2.0 and OIDC securely?
Add secure OAuth 2.0, OpenID Connect, JWT, and SSO flows to web, mobile, or API products.
Who is it for?
Backend developers adding standards-based authentication to web apps, mobile clients, or APIs with third-party identity provider integration.
Skip if: Teams needing passwordless magic-link-only auth with no OAuth provider or projects with existing fully configured auth libraries requiring no changes.
When should I use this skill?
Code needs OAuth 2.0 flows, OpenID Connect login, JWT tokens, refresh tokens, or SSO across web or mobile clients.
What you get
OAuth 2.0 and OIDC auth flows, JWT and refresh token handling, session management, and SSO integration code
- auth flow implementation
- token handling module
- SSO integration config
Files
OAuth Implementation
Table of Contents
Overview
Implement industry-standard OAuth 2.0 and OpenID Connect authentication flows with JWT tokens, refresh tokens, and secure session management.
When to Use
- User authentication systems
- Third-party API integration
- Single Sign-On (SSO) implementation
- Mobile app authentication
- Microservices security
- Social login integration
Quick Start
Minimal working example:
// oauth-server.js - Complete OAuth 2.0 implementation
const express = require("express");
const jwt = require("jsonwebtoken");
const crypto = require("crypto");
const bcrypt = require("bcrypt");
class OAuthServer {
constructor() {
this.app = express();
this.clients = new Map();
this.authorizationCodes = new Map();
this.refreshTokens = new Map();
this.accessTokens = new Map();
// JWT signing keys
this.privateKey = process.env.JWT_PRIVATE_KEY;
this.publicKey = process.env.JWT_PUBLIC_KEY;
this.setupRoutes();
}
// Register OAuth client
registerClient(clientId, clientSecret, redirectUris) {
this.clients.set(clientId, {
clientSecret: bcrypt.hashSync(clientSecret, 10),
// ... (see reference guides for full implementation)Reference Guides
Detailed implementations in the references/ directory:
| Guide | Contents |
|---|---|
| Node.js OAuth 2.0 Server | Node.js OAuth 2.0 Server |
| Python OpenID Connect Implementation | Python OpenID Connect Implementation |
| Java Spring Security OAuth | Java Spring Security OAuth |
Best Practices
✅ DO
- Use PKCE for public clients
- Implement token rotation
- Store tokens securely
- Use HTTPS everywhere
- Validate redirect URIs
- Implement rate limiting
- Use short-lived access tokens
- Log authentication events
❌ DON'T
- Store tokens in localStorage
- Use implicit flow
- Skip state parameter
- Expose client secrets
- Allow open redirects
- Use weak signing keys
Java Spring Security OAuth
Java Spring Security OAuth
// OAuth2AuthorizationServerConfig.java
package com.example.oauth;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client-app")
.secret("{bcrypt}$2a$10$...")
.authorizedGrantTypes("authorization_code", "refresh_token")
.scopes("read", "write")
.redirectUris("https://myapp.com/callback")
.accessTokenValiditySeconds(3600)
.refreshTokenValiditySeconds(86400)
.and()
.withClient("mobile-app")
.secret("{bcrypt}$2a$10$...")
.authorizedGrantTypes("password", "refresh_token")
.scopes("read")
.accessTokenValiditySeconds(7200);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
.tokenStore(tokenStore())
.accessTokenConverter(accessTokenConverter());
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("secret-key"); // Use proper key management
return converter;
}
}Node.js OAuth 2.0 Server
Node.js OAuth 2.0 Server
// oauth-server.js - Complete OAuth 2.0 implementation
const express = require("express");
const jwt = require("jsonwebtoken");
const crypto = require("crypto");
const bcrypt = require("bcrypt");
class OAuthServer {
constructor() {
this.app = express();
this.clients = new Map();
this.authorizationCodes = new Map();
this.refreshTokens = new Map();
this.accessTokens = new Map();
// JWT signing keys
this.privateKey = process.env.JWT_PRIVATE_KEY;
this.publicKey = process.env.JWT_PUBLIC_KEY;
this.setupRoutes();
}
// Register OAuth client
registerClient(clientId, clientSecret, redirectUris) {
this.clients.set(clientId, {
clientSecret: bcrypt.hashSync(clientSecret, 10),
redirectUris,
grants: ["authorization_code", "refresh_token"],
});
}
setupRoutes() {
this.app.use(express.json());
this.app.use(express.urlencoded({ extended: true }));
// Authorization endpoint
this.app.get("/oauth/authorize", (req, res) => {
const { client_id, redirect_uri, response_type, scope, state } =
req.query;
// Validate client
if (!this.clients.has(client_id)) {
return res.status(400).json({ error: "invalid_client" });
}
const client = this.clients.get(client_id);
// Validate redirect URI
if (!client.redirectUris.includes(redirect_uri)) {
return res.status(400).json({ error: "invalid_redirect_uri" });
}
// Validate response type
if (response_type !== "code") {
return res.status(400).json({ error: "unsupported_response_type" });
}
// Generate authorization code
const code = crypto.randomBytes(32).toString("hex");
this.authorizationCodes.set(code, {
clientId: client_id,
redirectUri: redirect_uri,
scope: scope || "read",
userId: req.user?.id, // From session
expiresAt: Date.now() + 600000, // 10 minutes
});
// Redirect with authorization code
const redirectUrl = new URL(redirect_uri);
redirectUrl.searchParams.set("code", code);
if (state) redirectUrl.searchParams.set("state", state);
res.redirect(redirectUrl.toString());
});
// Token endpoint
this.app.post("/oauth/token", async (req, res) => {
const {
grant_type,
code,
refresh_token,
client_id,
client_secret,
redirect_uri,
} = req.body;
// Validate client credentials
const client = this.clients.get(client_id);
if (!client || !bcrypt.compareSync(client_secret, client.clientSecret)) {
return res.status(401).json({ error: "invalid_client" });
}
if (grant_type === "authorization_code") {
return this.handleAuthorizationCodeGrant(
req,
res,
code,
client_id,
redirect_uri,
);
} else if (grant_type === "refresh_token") {
return this.handleRefreshTokenGrant(req, res, refresh_token, client_id);
}
res.status(400).json({ error: "unsupported_grant_type" });
});
// Token introspection endpoint
this.app.post("/oauth/introspect", (req, res) => {
const { token } = req.body;
try {
const decoded = jwt.verify(token, this.publicKey, {
algorithms: ["RS256"],
});
res.json({
active: true,
scope: decoded.scope,
client_id: decoded.client_id,
user_id: decoded.sub,
exp: decoded.exp,
});
} catch (error) {
res.json({ active: false });
}
});
// Token revocation endpoint
this.app.post("/oauth/revoke", (req, res) => {
const { token, token_type_hint } = req.body;
if (token_type_hint === "refresh_token") {
this.refreshTokens.delete(token);
} else {
this.accessTokens.delete(token);
}
res.status(200).json({ success: true });
});
}
handleAuthorizationCodeGrant(req, res, code, clientId, redirectUri) {
const authCode = this.authorizationCodes.get(code);
if (!authCode) {
return res.status(400).json({ error: "invalid_grant" });
}
// Validate authorization code
if (
authCode.clientId !== clientId ||
authCode.redirectUri !== redirectUri
) {
return res.status(400).json({ error: "invalid_grant" });
}
if (authCode.expiresAt < Date.now()) {
this.authorizationCodes.delete(code);
return res.status(400).json({ error: "expired_grant" });
}
// Delete used authorization code
this.authorizationCodes.delete(code);
// Generate tokens
const tokens = this.generateTokens(
clientId,
authCode.userId,
authCode.scope,
);
res.json(tokens);
}
handleRefreshTokenGrant(req, res, refreshToken, clientId) {
const storedToken = this.refreshTokens.get(refreshToken);
if (!storedToken || storedToken.clientId !== clientId) {
return res.status(400).json({ error: "invalid_grant" });
}
if (storedToken.expiresAt < Date.now()) {
this.refreshTokens.delete(refreshToken);
return res.status(400).json({ error: "expired_refresh_token" });
}
// Generate new access token
const tokens = this.generateTokens(
clientId,
storedToken.userId,
storedToken.scope,
);
res.json(tokens);
}
generateTokens(clientId, userId, scope) {
// Generate access token (JWT)
const accessToken = jwt.sign(
{
sub: userId,
client_id: clientId,
scope: scope,
type: "access_token",
},
this.privateKey,
{
algorithm: "RS256",
expiresIn: "1h",
issuer: "https://auth.example.com",
audience: "https://api.example.com",
},
);
// Generate refresh token
const refreshToken = crypto.randomBytes(64).toString("hex");
this.refreshTokens.set(refreshToken, {
clientId,
userId,
scope,
expiresAt: Date.now() + 2592000000, // 30 days
});
return {
access_token: accessToken,
token_type: "Bearer",
expires_in: 3600,
refresh_token: refreshToken,
scope: scope,
};
}
// Middleware to protect routes
authenticate() {
return (req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith("Bearer ")) {
return res.status(401).json({ error: "missing_token" });
}
const token = authHeader.substring(7);
try {
const decoded = jwt.verify(token, this.publicKey, {
algorithms: ["RS256"],
issuer: "https://auth.example.com",
audience: "https://api.example.com",
});
req.user = {
id: decoded.sub,
clientId: decoded.client_id,
scope: decoded.scope,
};
next();
} catch (error) {
if (error.name === "TokenExpiredError") {
return res.status(401).json({ error: "token_expired" });
}
return res.status(401).json({ error: "invalid_token" });
}
};
}
start(port = 3000) {
this.app.listen(port, () => {
console.log(`OAuth server running on port ${port}`);
});
}
}
// Usage
const oauthServer = new OAuthServer();
// Register OAuth client
oauthServer.registerClient("client-app-123", "super-secret-key", [
"https://myapp.com/callback",
]);
// Protected API endpoint
oauthServer.app.get(
"/api/user/profile",
oauthServer.authenticate(),
(req, res) => {
res.json({
userId: req.user.id,
scope: req.user.scope,
});
},
);
oauthServer.start(3000);Python OpenID Connect Implementation
Python OpenID Connect Implementation
# oidc_provider.py
from flask import Flask, request, jsonify, redirect
from authlib.integrations.flask_oauth2 import AuthorizationServer
from authlib.integrations.flask_oauth2 import ResourceProtector
from authlib.oauth2.rfc6749 import grants
from authlib.jose import jwt
import secrets
import time
from datetime import datetime, timedelta
app = Flask(__name__)
app.config['SECRET_KEY'] = secrets.token_hex(32)
class OIDCProvider:
def __init__(self):
self.clients = {}
self.authorization_codes = {}
self.access_tokens = {}
self.id_tokens = {}
# RSA keys for JWT signing
self.private_key = self._load_private_key()
self.public_key = self._load_public_key()
def _load_private_key(self):
# Load from environment or key management service
return """-----BEGIN RSA PRIVATE KEY-----
... Your private key ...
-----END RSA PRIVATE KEY-----"""
def _load_public_key(self):
return """-----BEGIN PUBLIC KEY-----
... Your public key ...
-----END PUBLIC KEY-----"""
def register_client(self, client_id, client_secret, redirect_uris, scopes):
"""Register OIDC client"""
self.clients[client_id] = {
'client_secret': client_secret,
'redirect_uris': redirect_uris,
'scopes': scopes,
'response_types': ['code', 'id_token', 'token']
}
def generate_id_token(self, user_id, client_id, nonce=None):
"""Generate OpenID Connect ID Token"""
now = int(time.time())
payload = {
'iss': 'https://auth.example.com',
'sub': user_id,
'aud': client_id,
'exp': now + 3600,
'iat': now,
'auth_time': now,
'nonce': nonce
}
# Add optional claims
payload.update({
'email': f'{user_id}@example.com',
'email_verified': True,
'name': 'John Doe',
'given_name': 'John',
'family_name': 'Doe',
'picture': 'https://example.com/avatar.jpg'
})
header = {'alg': 'RS256', 'typ': 'JWT'}
return jwt.encode(header, payload, self.private_key)
def generate_access_token(self, user_id, client_id, scope):
"""Generate OAuth 2.0 access token"""
token = secrets.token_urlsafe(32)
self.access_tokens[token] = {
'user_id': user_id,
'client_id': client_id,
'scope': scope,
'expires_at': datetime.now() + timedelta(hours=1)
}
return token
def verify_token(self, token):
"""Verify JWT token"""
try:
claims = jwt.decode(token, self.public_key)
claims.validate()
return claims
except Exception as e:
return None
# OIDC Endpoints
provider = OIDCProvider()
@app.route('/.well-known/openid-configuration')
def openid_configuration():
"""OpenID Connect Discovery endpoint"""
return jsonify({
'issuer': 'https://auth.example.com',
'authorization_endpoint': 'https://auth.example.com/oauth/authorize',
'token_endpoint': 'https://auth.example.com/oauth/token',
'userinfo_endpoint': 'https://auth.example.com/oauth/userinfo',
'jwks_uri': 'https://auth.example.com/.well-known/jwks.json',
'response_types_supported': ['code', 'id_token', 'token id_token'],
'subject_types_supported': ['public'],
'id_token_signing_alg_values_supported': ['RS256'],
'scopes_supported': ['openid', 'profile', 'email'],
'token_endpoint_auth_methods_supported': ['client_secret_basic', 'client_secret_post'],
'claims_supported': ['sub', 'iss', 'aud', 'exp', 'iat', 'name', 'email']
})
@app.route('/.well-known/jwks.json')
def jwks():
"""JSON Web Key Set endpoint"""
# Return public key in JWK format
return jsonify({
'keys': [
{
'kty': 'RSA',
'use': 'sig',
'kid': '1',
'n': '...', # Public key modulus
'e': 'AQAB'
}
]
})
@app.route('/oauth/userinfo')
def userinfo():
"""UserInfo endpoint"""
auth_header = request.headers.get('Authorization')
if not auth_header or not auth_header.startswith('Bearer '):
return jsonify({'error': 'invalid_token'}), 401
token = auth_header[7:]
claims = provider.verify_token(token)
if not claims:
return jsonify({'error': 'invalid_token'}), 401
return jsonify({
'sub': claims['sub'],
'email': claims.get('email'),
'name': claims.get('name'),
'picture': claims.get('picture')
})
# Register sample client
provider.register_client(
'sample-app',
'secret123',
['https://myapp.com/callback'],
['openid', 'profile', 'email']
)
if __name__ == '__main__':
app.run(port=3000, debug=True)#!/bin/bash
# security-checklist.sh - Generate a security review checklist
# Usage: ./security-checklist.sh [--output checklist.md]
set -euo pipefail
OUTPUT="${{1:-/dev/stdout}}"
cat > "$OUTPUT" << 'CHECKLIST'
# Security Review Checklist
## Authentication & Authorization
- [ ] All endpoints require authentication
- [ ] Role-based access control implemented
- [ ] Session management is secure
## Input Validation
- [ ] All user inputs are validated
- [ ] SQL injection prevention
- [ ] XSS prevention
## Data Protection
- [ ] Sensitive data encrypted at rest
- [ ] Sensitive data encrypted in transit
- [ ] PII handling compliant
## TODO: Add domain-specific security checks
CHECKLIST
echo "Checklist generated: $OUTPUT" >&2
Related skills
How it compares
Pick oauth-implementation for full OAuth/OIDC/JWT flow design rather than API key-only authentication or frontend-only login UI skills.
FAQ
What standards does oauth-implementation cover?
oauth-implementation covers OAuth 2.0, OpenID Connect, JWT authentication, refresh tokens, secure session management, and SSO integration for web and mobile applications.
When should developers use oauth-implementation?
oauth-implementation applies when building user authentication systems, integrating third-party APIs that require OAuth, or adding single sign-on across web and mobile clients.