Skip to main content ホーム クリエイター ynulihao agentskillos auth-implementation-patterns
auth-implementation-patterns Master authentication and authorization patterns including JWT, OAuth2, session management, and RBAC to build secure, scalable access control systems. Use when implementing auth systems, securing APIs, or debugging security issues.
インストールへ移動 Skills Marketplace コミュニティが作成したAIスキルを発見・探索
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
直接コマンドでは確認用 Prompt が省略されます。実行前にソースを確認してください。
npx skills add https://github.com/ynulihao/AgentSkillOS --skill auth-implementation-patternsコマンドは1行のまま表示されます。コピー前に横へスクロールして全体を確認してください。
ローカルで確認しますか?SkillsMP が現在取得できるファイルをダウンロードできます。
Zipをダウンロード ダウンロード中... name auth-implementation-patterns description Master authentication and authorization patterns including JWT, OAuth2, session management, and RBAC to build secure, scalable access control systems. Use when implementing auth systems, securing APIs, or debugging security issues.
Authentication & Authorization Implementation Patterns
Build secure, scalable authentication and authorization systems using industry-standard patterns and modern best practices.
When to Use This Skill
Implementing user authentication systems
Securing REST or GraphQL APIs
Adding OAuth2/social login
Implementing role-based access control (RBAC)
Designing session management
Migrating authentication systems
Debugging auth issues
Implementing SSO or multi-tenancy
Core Concepts
1. Authentication vs Authorization
Authentication (AuthN) : Who are you?
Verifying identity (username/password, OAuth, biometrics)
Issuing credentials (sessions, tokens)
Managing login/logout
Authorization (AuthZ) : What can you do?
Permission checking
Role-based access control (RBAC)
Resource ownership validation
Policy enforcement
2. Authentication Strategies
Session-Based:
Server stores session state
Session ID in cookie
Traditional, simple, stateful
Token-Based (JWT):
Stateless, self-contained
Scales horizontally
Can store claims
OAuth2/OpenID Connect:
Delegate authentication
Social login (Google, GitHub)
Enterprise SSO
JWT Authentication
Pattern 1: JWT Implementation
import jwt from 'jsonwebtoken' ;
import { Request , Response , NextFunction } from 'express' ;
interface JWTPayload {
userId : string ;
email : string ;
role : string ;
iat : number ;
exp : number ;
}
function generateTokens (userId : string , email : string , role : string ) {
const accessToken = jwt.sign (
{ userId, email, role },
process.env .JWT_SECRET !,
{ expiresIn : '15m' }
);
const refreshToken = jwt.sign (
{ userId },
process.env .JWT_REFRESH_SECRET !,
{ expiresIn : '7d' }
);
return { accessToken, refreshToken };
}
function verifyToken (token : string ): JWTPayload {
try {
return jwt.verify (token, process.env .JWT_SECRET !) as JWTPayload ;
} catch (error) {
if (error instanceof jwt.TokenExpiredError ) {
throw new Error ('Token expired' );
}
if (error instanceof jwt.JsonWebTokenError ) {
throw new Error ('Invalid token' );
}
throw error;
}
}
function authenticate (req : Request , res : Response , next : NextFunction ) {
const authHeader = req.headers .authorization ;
if (!authHeader?.startsWith ('Bearer ' )) {
return res.status (401 ).json ({ error : 'No token provided' });
}
const token = authHeader.substring (7 );
try {
const payload = verifyToken (token);
req.user = payload;
next ();
} catch (error) {
return res.status (401 ).json ({ error : 'Invalid token' });
}
}
app.get ('/api/profile' , authenticate, (req, res ) => {
res.json ({ user : req.user });
});
Pattern 2: Refresh Token Flow interface StoredRefreshToken {
token : string ;
userId : string ;
expiresAt : Date ;
createdAt : Date ;
}
class RefreshTokenService {
async storeRefreshToken (userId : string , refreshToken : string ) {
const expiresAt = new Date (Date .now () + 7 * 24 * 60 * 60 * 1000 );
await db.refreshTokens .create ({
token : await hash (refreshToken),
userId,
expiresAt,
});
}
async refreshAccessToken (refreshToken : string ) {
let payload;
try {
payload = jwt.verify (
refreshToken,
process.env .JWT_REFRESH_SECRET !
) as { userId : string };
} catch {
throw new Error ('Invalid refresh token' );
}
const storedToken = await db.refreshTokens .findOne ({
where : {
token : await hash (refreshToken),
userId : payload.userId ,
expiresAt : { $gt : new Date () },
},
});
if (!storedToken) {
throw new Error ('Refresh token not found or expired' );
}
const user = await db.users .findById (payload.userId );
if (!user) {
throw new Error ('User not found' );
}
const accessToken = jwt.sign (
{ userId : user.id , email : user.email , role : user.role },
process.env .JWT_SECRET !,
{ expiresIn : '15m' }
);
return { accessToken };
}
async revokeRefreshToken (refreshToken : string ) {
await db.refreshTokens .deleteOne ({
token : await hash (refreshToken),
});
}
async revokeAllUserTokens (userId : string ) {
await db.refreshTokens .deleteMany ({ userId });
}
}
app.post ('/api/auth/refresh' , async (req, res) => {
const { refreshToken } = req.body ;
try {
const { accessToken } = await refreshTokenService
.refreshAccessToken (refreshToken);
res.json ({ accessToken });
} catch (error) {
res.status (401 ).json ({ error : 'Invalid refresh token' });
}
});
app.post ('/api/auth/logout' , authenticate, async (req, res) => {
const { refreshToken } = req.body ;
await refreshTokenService.revokeRefreshToken (refreshToken);
res.json ({ message : 'Logged out successfully' });
});
Session-Based Authentication
Pattern 1: Express Session import session from 'express-session' ;
import RedisStore from 'connect-redis' ;
import { createClient } from 'redis' ;
const redisClient = createClient ({
url : process.env .REDIS_URL ,
});
await redisClient.connect ();
app.use (
session ({
store : new RedisStore ({ client : redisClient }),
secret : process.env .SESSION_SECRET !,
resave : false ,
saveUninitialized : false ,
cookie : {
secure : process.env .NODE_ENV === 'production' ,
httpOnly : true ,
maxAge : 24 * 60 * 60 * 1000 ,
sameSite : 'strict' ,
},
})
);
app.post ('/api/auth/login' , async (req, res) => {
const { email, password } = req.body ;
const user = await db.users .findOne ({ email });
if (!user || !(await verifyPassword (password, user.passwordHash ))) {
return res.status (401 ).json ({ error : 'Invalid credentials' });
}
req.session .userId = user.id ;
req.session .role = user.role ;
res.json ({ user : { id : user.id , email : user.email , role : user.role } });
});
function requireAuth (req : Request , res : Response , next : NextFunction ) {
if (!req.session .userId ) {
return res.status (401 ).json ({ error : 'Not authenticated' });
}
next ();
}
app.get ('/api/profile' , requireAuth, async (req, res) => {
const user = await db.users .findById (req.session .userId );
res.json ({ user });
});
app.post ('/api/auth/logout' , (req, res ) => {
req.session .destroy ((err ) => {
if (err) {
return res.status (500 ).json ({ error : 'Logout failed' });
}
res.clearCookie ('connect.sid' );
res.json ({ message : 'Logged out successfully' });
});
});
OAuth2 / Social Login
Pattern 1: OAuth2 with Passport.js import passport from 'passport' ;
import { Strategy as GoogleStrategy } from 'passport-google-oauth20' ;
import { Strategy as GitHubStrategy } from 'passport-github2' ;
passport.use (
new GoogleStrategy (
{
clientID : process.env .GOOGLE_CLIENT_ID !,
clientSecret : process.env .GOOGLE_CLIENT_SECRET !,
callbackURL : '/api/auth/google/callback' ,
},
async (accessToken, refreshToken, profile, done) => {
try {
let user = await db.users .findOne ({
googleId : profile.id ,
});
if (!user) {
user = await db.users .create ({
googleId : profile.id ,
email : profile.emails ?.[0 ]?.value ,
name : profile.displayName ,
avatar : profile.photos ?.[0 ]?.value ,
});
}
return done (null , user);
} catch (error) {
return done (error, undefined );
}
}
)
);
app.get ('/api/auth/google' , passport.authenticate ('google' , {
scope : ['profile' , 'email' ],
}));
app.get (
'/api/auth/google/callback' ,
passport.authenticate ('google' , { session : false }),
(req, res ) => {
const tokens = generateTokens (req.user .id , req.user .email , req.user .role );
res.redirect (`${process.env.FRONTEND_URL} /auth/callback?token=${tokens.accessToken} ` );
}
);
Authorization Patterns
Pattern 1: Role-Based Access Control (RBAC) enum Role {
USER = 'user' ,
MODERATOR = 'moderator' ,
ADMIN = 'admin' ,
}
const roleHierarchy : Record <Role , Role []> = {
[Role .ADMIN ]: [Role .ADMIN , Role .MODERATOR , Role .USER ],
[Role .MODERATOR ]: [Role .MODERATOR , Role .USER ],
[Role .USER ]: [Role .USER ],
};
function hasRole (userRole : Role , requiredRole : Role ): boolean {
return roleHierarchy[userRole].includes (requiredRole);
}
function requireRole (...roles : Role [] ) {
return (req : Request , res : Response , next : NextFunction ) => {
if (!req.user ) {
return res.status (401 ).json ({ error : 'Not authenticated' });
}
if (!roles.some (role => hasRole (req.user .role , role))) {
return res.status (403 ).json ({ error : 'Insufficient permissions' });
}
next ();
};
}
app.delete ('/api/users/:id' ,
authenticate,
requireRole (Role .ADMIN ),
async (req, res) => {
await db.users .delete (req.params .id );
res.json ({ message : 'User deleted' });
}
);
Pattern 2: Permission-Based Access Control enum Permission {
READ_USERS = 'read:users' ,
WRITE_USERS = 'write:users' ,
DELETE_USERS = 'delete:users' ,
READ_POSTS = 'read:posts' ,
WRITE_POSTS = 'write:posts' ,
}
const rolePermissions : Record <Role , Permission []> = {
[Role .USER ]: [Permission .READ_POSTS , Permission .WRITE_POSTS ],
[Role .MODERATOR ]: [
Permission .READ_POSTS ,
Permission .WRITE_POSTS ,
Permission .READ_USERS ,
],
[Role .ADMIN ]: Object .values (Permission ),
};
function hasPermission (userRole : Role , permission : Permission ): boolean {
return rolePermissions[userRole]?.includes (permission) ?? false ;
}
function requirePermission (...permissions : Permission [] ) {
return (req : Request , res : Response , next : NextFunction ) => {
if (!req.user ) {
return res.status (401 ).json ({ error : 'Not authenticated' });
}
const hasAllPermissions = permissions.every (permission =>
hasPermission (req.user .role , permission)
);
if (!hasAllPermissions) {
return res.status (403 ).json ({ error : 'Insufficient permissions' });
}
next ();
};
}
app.get ('/api/users' ,
authenticate,
requirePermission (Permission .READ_USERS ),
async (req, res) => {
const users = await db.users .findAll ();
res.json ({ users });
}
);
Pattern 3: Resource Ownership
async function requireOwnership (
resourceType : 'post' | 'comment' ,
resourceIdParam : string = 'id'
) {
return async (req : Request , res : Response , next : NextFunction ) => {
if (!req.user ) {
return res.status (401 ).json ({ error : 'Not authenticated' });
}
const resourceId = req.params [resourceIdParam];
if (req.user .role === Role .ADMIN ) {
return next ();
}
let resource;
if (resourceType === 'post' ) {
resource = await db.posts .findById (resourceId);
} else if (resourceType === 'comment' ) {
resource = await db.comments .findById (resourceId);
}
if (!resource) {
return res.status (404 ).json ({ error : 'Resource not found' });
}
if (resource.userId !== req.user .userId ) {
return res.status (403 ).json ({ error : 'Not authorized' });
}
next ();
};
}
app.put ('/api/posts/:id' ,
authenticate,
requireOwnership ('post' ),
async (req, res) => {
const post = await db.posts .update (req.params .id , req.body );
res.json ({ post });
}
);
Security Best Practices
Pattern 1: Password Security import bcrypt from 'bcrypt' ;
import { z } from 'zod' ;
const passwordSchema = z.string ()
.min (12 , 'Password must be at least 12 characters' )
.regex (/[A-Z]/ , 'Password must contain uppercase letter' )
.regex (/[a-z]/ , 'Password must contain lowercase letter' )
.regex (/[0-9]/ , 'Password must contain number' )
.regex (/[^A-Za-z0-9]/ , 'Password must contain special character' );
async function hashPassword (password : string ): Promise <string > {
const saltRounds = 12 ;
return bcrypt.hash (password, saltRounds);
}
async function verifyPassword (
password : string ,
hash : string
): Promise <boolean > {
return bcrypt.compare (password, hash);
}
app.post ('/api/auth/register' , async (req, res) => {
try {
const { email, password } = req.body ;
passwordSchema.parse (password);
const existingUser = await db.users .findOne ({ email });
if (existingUser) {
return res.status (400 ).json ({ error : 'Email already registered' });
}
const passwordHash = await hashPassword (password);
const user = await db.users .create ({
email,
passwordHash,
});
const tokens = generateTokens (user.id , user.email , user.role );
res.status (201 ).json ({
user : { id : user.id , email : user.email },
...tokens,
});
} catch (error) {
if (error instanceof z.ZodError ) {
return res.status (400 ).json ({ error : error.errors [0 ].message });
}
res.status (500 ).json ({ error : 'Registration failed' });
}
});
Pattern 2: Rate Limiting import rateLimit from 'express-rate-limit' ;
import RedisStore from 'rate-limit-redis' ;
const loginLimiter = rateLimit ({
store : new RedisStore ({ client : redisClient }),
windowMs : 15 * 60 * 1000 ,
max : 5 ,
message : 'Too many login attempts, please try again later' ,
standardHeaders : true ,
legacyHeaders : false ,
});
const apiLimiter = rateLimit ({
windowMs : 60 * 1000 ,
max : 100 ,
standardHeaders : true ,
});
app.post ('/api/auth/login' , loginLimiter, async (req, res) => {
});
app.use ('/api/' , apiLimiter);
Best Practices
Never Store Plain Passwords : Always hash with bcrypt/argon2
Use HTTPS : Encrypt data in transit
Short-Lived Access Tokens : 15-30 minutes max
Secure Cookies : httpOnly, secure, sameSite flags
Validate All Input : Email format, password strength
Rate Limit Auth Endpoints : Prevent brute force attacks
Implement CSRF Protection : For session-based auth
Rotate Secrets Regularly : JWT secrets, session secrets
Log Security Events : Login attempts, failed auth
Use MFA When Possible : Extra security layer
Common Pitfalls
Weak Passwords : Enforce strong password policies
JWT in localStorage : Vulnerable to XSS, use httpOnly cookies
No Token Expiration : Tokens should expire
Client-Side Auth Checks Only : Always validate server-side
Insecure Password Reset : Use secure tokens with expiration
No Rate Limiting : Vulnerable to brute force
Trusting Client Data : Always validate on server
Resources
references/jwt-best-practices.md : JWT implementation guide
references/oauth2-flows.md : OAuth2 flow diagrams and examples
references/session-security.md : Secure session management
assets/auth-security-checklist.md : Security review checklist
assets/password-policy-template.md : Password requirements template
scripts/token-validator.ts : JWT validation utility