🎯 empfohlene Sammlungen
Balanced sample collections from various categories for you to explore
OAuth 2.0 & OpenID Connect Beispiele
Beispiele für das OAuth 2.0 Autorisierungs-Framework und das OpenID Connect Authentifizierungsprotokoll
💻 Resource Owner Password Credentials Fluss javascript
🟢 simple
⭐⭐⭐
Implementierung des OAuth 2.0 Resource Owner Password Credentials Grant
⏱️ 25 min
🏷️ oauth, password, authentication, jwt, security
Prerequisites:
Node.js, JWT, bcrypt, OAuth 2.0 concepts
// OAuth 2.0 Resource Owner Password Credentials Flow
const express = require('express');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const app = express();
app.use(express.json());
// Configuration
const config = {
jwtSecret: 'your-super-secret-jwt-key',
jwtExpiration: '15m',
refreshTokenExpiration: '7d',
bcryptRounds: 12,
rateLimitWindow: 15 * 60 * 1000, // 15 minutes
rateLimitMax: 5 // max attempts per window
};
// In-memory user database (in production, use a proper database)
const users = new Map();
const refreshTokens = new Set();
const rateLimitStore = new Map();
// Initialize with a test user
async function initializeTestUser() {
const hashedPassword = await bcrypt.hash('password123', config.bcryptRounds);
users.set('[email protected]', {
id: 1,
email: '[email protected]',
password: hashedPassword,
name: 'John Doe',
role: 'user',
permissions: ['read:profile', 'write:profile']
});
// Add admin user
const adminHashedPassword = await bcrypt.hash('admin123', config.bcryptRounds);
users.set('[email protected]', {
id: 2,
email: '[email protected]',
password: adminHashedPassword,
name: 'Admin User',
role: 'admin',
permissions: ['read:profile', 'write:profile', 'read:users', 'write:users']
});
}
// Rate limiting middleware
function rateLimit(req, res, next) {
const clientIp = req.ip || req.connection.remoteAddress;
const now = Date.now();
// Clean old entries
for (const [ip, attempts] of rateLimitStore.entries()) {
if (now - attempts.timestamp > config.rateLimitWindow) {
rateLimitStore.delete(ip);
}
}
const attempts = rateLimitStore.get(clientIp) || { count: 0, timestamp: now };
if (now - attempts.timestamp > config.rateLimitWindow) {
attempts.count = 1;
attempts.timestamp = now;
} else {
attempts.count++;
}
rateLimitStore.set(clientIp, attempts);
if (attempts.count > config.rateLimitMax) {
const remainingTime = Math.ceil((config.rateLimitWindow - (now - attempts.timestamp)) / 1000);
res.set('Retry-After', remainingTime);
return res.status(429).json({
error: 'Too many authentication attempts',
retryAfter: remainingTime
});
}
next();
}
// Generate tokens
function generateTokens(user) {
const payload = {
sub: user.id,
email: user.email,
name: user.name,
role: user.role,
permissions: user.permissions,
type: 'access'
};
const accessToken = jwt.sign(payload, config.jwtSecret, {
expiresIn: config.jwtExpiration,
issuer: 'your-auth-server',
audience: 'your-api'
});
const refreshTokenPayload = {
sub: user.id,
type: 'refresh',
jti: crypto.randomBytes(16).toString('hex') // Unique identifier for refresh token
};
const refreshToken = jwt.sign(refreshTokenPayload, config.jwtSecret, {
expiresIn: config.refreshTokenExpiration
});
refreshTokens.add(refreshToken);
return {
accessToken,
refreshToken,
tokenType: 'Bearer',
expiresIn: 900 // 15 minutes in seconds
};
}
// Verify refresh token
function verifyRefreshToken(token) {
try {
const decoded = jwt.verify(token, config.jwtSecret);
if (decoded.type !== 'refresh') {
throw new Error('Invalid token type');
}
if (!refreshTokens.has(token)) {
throw new Error('Refresh token not found');
}
return decoded;
} catch (error) {
throw new Error('Invalid refresh token');
}
}
// Generate scope-based access token
function generateScopedToken(user, requestedScopes) {
// Define available scopes and what they grant
const availableScopes = {
'read:profile': 'Read user profile information',
'write:profile': 'Update user profile information',
'read:users': 'Read user list (admin only)',
'write:users': 'Manage users (admin only)',
'admin': 'Full administrative access'
};
// Validate requested scopes
const validScopes = [];
for (const scope of requestedScopes) {
if (user.permissions.includes(scope) ||
(scope === 'admin' && user.role === 'admin')) {
validScopes.push(scope);
}
}
const payload = {
sub: user.id,
email: user.email,
name: user.name,
role: user.role,
scopes: validScopes,
type: 'access'
};
return jwt.sign(payload, config.jwtSecret, {
expiresIn: config.jwtExpiration,
issuer: 'your-auth-server',
audience: 'your-api'
});
}
// OAuth 2.0 Token Endpoint
app.post('/oauth/token', rateLimit, async (req, res) => {
const { grant_type, username, password, scope, refresh_token } = req.body;
try {
switch (grant_type) {
case 'password':
// Resource Owner Password Credentials Grant
if (!username || !password) {
return res.status(400).json({
error: 'invalid_request',
error_description: 'username and password are required'
});
}
const user = users.get(username);
if (!user || !(await bcrypt.compare(password, user.password))) {
return res.status(401).json({
error: 'invalid_grant',
error_description: 'Invalid username or password'
});
}
// Handle requested scopes
const requestedScopes = scope ? scope.split(' ') : ['read:profile'];
const accessToken = generateScopedToken(user, requestedScopes);
const tokenData = generateTokens(user);
return res.json({
access_token: accessToken,
refresh_token: tokenData.refreshToken,
token_type: 'Bearer',
expires_in: 900,
scope: requestedScopes.join(' ')
});
case 'refresh_token':
// Refresh Token Grant
if (!refresh_token) {
return res.status(400).json({
error: 'invalid_request',
error_description: 'refresh_token is required'
});
}
try {
const decoded = verifyRefreshToken(refresh_token);
const user = Array.from(users.values()).find(u => u.id === decoded.sub);
if (!user) {
return res.status(401).json({
error: 'invalid_grant',
error_description: 'User not found'
});
}
// Revoke old refresh token
refreshTokens.delete(refresh_token);
// Generate new tokens
const newTokens = generateTokens(user);
res.json({
access_token: newTokens.accessToken,
refresh_token: newTokens.refreshToken,
token_type: 'Bearer',
expires_in: 900
});
} catch (error) {
return res.status(401).json({
error: 'invalid_grant',
error_description: 'Invalid refresh token'
});
}
default:
return res.status(400).json({
error: 'unsupported_grant_type',
error_description: 'Only password and refresh_token grants are supported'
});
}
} catch (error) {
console.error('Token endpoint error:', error);
return res.status(500).json({
error: 'server_error',
error_description: 'Internal server error'
});
}
});
// Token Revocation
app.post('/oauth/revoke', (req, res) => {
const { token, token_type_hint } = req.body;
if (!token) {
return res.status(400).json({
error: 'invalid_request',
error_description: 'token is required'
});
}
try {
if (token_type_hint === 'refresh_token') {
refreshTokens.delete(token);
} else {
// For access tokens, we could maintain a blacklist
// For this demo, we'll just accept it
}
res.json({});
} catch (error) {
res.status(500).json({
error: 'server_error',
error_description: 'Failed to revoke token'
});
}
});
// Introspection Endpoint
app.post('/oauth/introspect', (req, res) => {
const { token, token_type_hint } = req.body;
if (!token) {
return res.status(400).json({
error: 'invalid_request',
error_description: 'token is required'
});
}
try {
const decoded = jwt.verify(token, config.jwtSecret);
const response = {
active: true,
scope: decoded.scopes?.join(' ') || 'read:profile',
client_id: 'your-client-id',
sub: decoded.sub.toString(),
exp: decoded.exp,
iat: decoded.iat,
token_type: 'Bearer'
};
res.json(response);
} catch (error) {
res.json({
active: false
});
}
});
// Protected API endpoints
function authenticateToken(req, res, next) {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return res.status(401).json({
error: 'invalid_token',
error_description: 'Access token required'
});
}
const token = authHeader.substring(7);
try {
const decoded = jwt.verify(token, config.jwtSecret);
if (decoded.type !== 'access') {
throw new Error('Invalid token type');
}
req.user = {
id: decoded.sub,
email: decoded.email,
name: decoded.name,
role: decoded.role,
scopes: decoded.scopes || ['read:profile']
};
next();
} catch (error) {
return res.status(401).json({
error: 'invalid_token',
error_description: 'Invalid or expired token'
});
}
}
function requireScope(scope) {
return (req, res, next) => {
if (!req.user.scopes.includes(scope) && !req.user.scopes.includes('admin')) {
return res.status(403).json({
error: 'insufficient_scope',
error_description: `Required scope: ${scope}`
});
}
next();
};
}
// Profile endpoint
app.get('/api/profile', authenticateToken, requireScope('read:profile'), (req, res) => {
const user = users.get(req.user.email);
res.json({
id: user.id,
email: user.email,
name: user.name,
role: user.role,
scopes: req.user.scopes
});
});
// Update profile endpoint
app.put('/api/profile', authenticateToken, requireScope('write:profile'), (req, res) => {
const { name } = req.body;
if (!name) {
return res.status(400).json({
error: 'invalid_request',
error_description: 'name is required'
});
}
const user = users.get(req.user.email);
user.name = name;
res.json({
message: 'Profile updated successfully',
user: {
id: user.id,
email: user.email,
name: user.name
}
});
});
// Admin endpoint to list users
app.get('/api/users', authenticateToken, requireScope('read:users'), (req, res) => {
const userList = Array.from(users.values()).map(user => ({
id: user.id,
email: user.email,
name: user.name,
role: user.role
}));
res.json({ users: userList });
});
// Health check endpoint
app.get('/health', (req, res) => {
res.json({
status: 'healthy',
timestamp: new Date().toISOString(),
version: '1.0.0'
});
});
// Initialize and start server
initializeTestUser().then(() => {
app.listen(3000, () => {
console.log('OAuth 2.0 Resource Owner Password Credentials server running on port 3000');
});
});
// Example client usage:
/*
// Get access token with password grant
POST /oauth/token
{
"grant_type": "password",
"username": "[email protected]",
"password": "password123",
"scope": "read:profile write:profile"
}
// Refresh token
POST /oauth/token
{
"grant_type": "refresh_token",
"refresh_token": "your-refresh-token"
}
// Access protected resource
GET /api/profile
Authorization: Bearer your-access-token
// Revoke token
POST /oauth/revoke
{
"token": "your-refresh-token",
"token_type_hint": "refresh_token"
}
*/
💻 OAuth 2.0 Autorisierungscode-Fluss javascript
🟡 intermediate
⭐⭐⭐⭐
Implementierung des OAuth 2.0 Autorisierungscode-Flusses für sicheren API-Zugriff
⏱️ 30 min
🏷️ oauth, authentication, authorization, security, express
Prerequisites:
Node.js, OAuth 2.0 concepts, Express.js
// OAuth 2.0 Authorization Code Flow
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());
// OAuth configuration
const oauth = {
client_id: 'your-client-id',
client_secret: 'your-client-secret',
redirect_uri: 'http://localhost:3000/callback',
auth_url: 'https://oauth-provider.com/authorize',
token_url: 'https://oauth-provider.com/token'
};
// Initiate OAuth flow
app.get('/auth', (req, res) => {
const state = crypto.randomBytes(16).toString('hex');
const params = new URLSearchParams({
response_type: 'code',
client_id: oauth.client_id,
redirect_uri: oauth.redirect_uri,
scope: 'read write',
state: state
});
const url = `${oauth.auth_url}?${params.toString()}`;
res.redirect(url);
});
// Handle OAuth callback
app.post('/token', async (req, res) => {
const { code } = req.body;
try {
// Exchange code for tokens
const response = await fetch(oauth.token_url, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
code: code,
client_id: oauth.client_id,
client_secret: oauth.client_secret,
redirect_uri: oauth.redirect_uri
})
});
const tokens = await response.json();
res.json(tokens);
} catch (error) {
res.status(400).json({ error: 'Token exchange failed' });
}
});
// Protected API endpoint
function requireToken(req, res, next) {
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) return res.status(401).json({ error: 'Token required' });
// Validate token (implement your validation logic)
req.token = token;
next();
}
app.get('/api/data', requireToken, (req, res) => {
res.json({ message: 'Protected data', token: req.token });
});
// PKCE support for enhanced security
function generatePKCE() {
const codeVerifier = crypto.randomBytes(32).toString('base64url');
const codeChallenge = crypto
.createHash('sha256')
.update(codeVerifier)
.digest('base64url');
return { codeVerifier, codeChallenge };
}
// OAuth with PKCE
app.get('/auth-pkce', (req, res) => {
const { codeVerifier, codeChallenge } = generatePKCE();
const params = new URLSearchParams({
response_type: 'code',
client_id: oauth.client_id,
redirect_uri: oauth.redirect_uri,
code_challenge: codeChallenge,
code_challenge_method: 'S256'
});
const url = `${oauth.auth_url}?${params.toString()}`;
res.json({
authUrl: url,
codeVerifier,
message: 'Store codeVerifier for token exchange'
});
});
// Token exchange with PKCE
app.post('/token-pkce', async (req, res) => {
const { code, codeVerifier } = req.body;
const response = await fetch(oauth.token_url, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
code: code,
client_id: oauth.client_id,
client_secret: oauth.client_secret,
redirect_uri: oauth.redirect_uri,
code_verifier: codeVerifier
})
});
const tokens = await response.json();
res.json(tokens);
});
💻 OpenID Connect (OIDC) Implementierung python
🟡 intermediate
⭐⭐⭐⭐
Vollständige OpenID Connect Implementierung mit ID-Tokens und Benutzerauthentifizierung
⏱️ 35 min
🏷️ openid, jwt, authentication, flask, security
Prerequisites:
Python, Flask, JWT concepts, OIDC knowledge
# OpenID Connect with Node.js
const express = require('express');
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const app = express();
app.use(express.json());
// OIDC configuration
const oidc = {
issuer: 'https://accounts.google.com',
client_id: 'your-oidc-client-id',
client_secret: 'your-oidc-secret',
redirect_uri: 'http://localhost:3000/callback'
};
// Verify JWT ID token
function verifyIdToken(token) {
try {
const decoded = jwt.verify(token, oidc.client_secret);
return decoded;
} catch (error) {
throw new Error('Invalid ID token');
}
}
// OIDC login
app.get('/auth/oidc', (req, res) => {
const params = new URLSearchParams({
response_type: 'code',
client_id: oidc.client_id,
redirect_uri: oidc.redirect_uri,
scope: 'openid email profile',
response_mode: 'query'
});
const url = `${oidc.issuer}/o/oauth2/v2/auth?${params.toString()}`;
res.redirect(url);
});
// OIDC callback
app.post('/oidc/callback', async (req, res) => {
const { code } = req.body;
// Exchange code for tokens
const tokenResponse = await fetch(`${oidc.issuer}/oauth2/v4/token`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
code: code,
client_id: oidc.client_id,
client_secret: oidc.client_secret,
redirect_uri: oidc.redirect_uri,
grant_type: 'authorization_code'
})
});
const tokens = await tokenResponse.json();
// Verify ID token
const idToken = tokens.id_token;
const user = verifyIdToken(idToken);
res.json({
user,
tokens: { accessToken: tokens.access_token }
});
});