Authentication & Authorization
Introduction
Authentication and Authorization are fundamental security concepts that control access to resources. Authentication verifies who a user is, while authorization determines what they can do.
Key Concepts:
- Identity Management
- Access Control
- Session Management
- Token-based Auth
- Single Sign-On
- Multi-factor Authentication
Authentication Methods
Password Authentication
import { compare, hash } from 'bcrypt';
class PasswordAuth {
private readonly SALT_ROUNDS = 12;
async hashPassword(password: string): Promise {
return await hash(password, this.SALT_ROUNDS);
}
async verifyPassword(
password: string,
hashedPassword: string
): Promise {
return await compare(password, hashedPassword);
}
validatePasswordStrength(password: string): boolean {
const minLength = 12;
const hasUpperCase = /[A-Z]/.test(password);
const hasLowerCase = /[a-z]/.test(password);
const hasNumbers = /\d/.test(password);
const hasSpecialChars = /[!@#$%^&*]/.test(password);
return password.length >= minLength &&
hasUpperCase &&
hasLowerCase &&
hasNumbers &&
hasSpecialChars;
}
}
Multi-Factor Authentication
import { authenticator } from 'otplib';
import { createTransport } from 'nodemailer';
class MFAService {
private emailTransport;
constructor() {
this.emailTransport = createTransport({
host: 'smtp.example.com',
port: 587,
secure: false,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS
}
});
}
generateTOTPSecret(): string {
return authenticator.generateSecret();
}
verifyTOTP(token: string, secret: string): boolean {
return authenticator.verify({ token, secret });
}
async sendEmailCode(email: string): Promise {
const code = Math.random().toString(36).slice(-6);
await this.emailTransport.sendMail({
from: 'security@example.com',
to: email,
subject: 'Your verification code',
text: `Your verification code is: ${code}`
});
return code;
}
}
JWT Implementation
import { sign, verify } from 'jsonwebtoken';
interface TokenPayload {
userId: string;
roles: string[];
exp?: number;
}
class JWTService {
private readonly secret: string;
private readonly accessTokenExpiry: string;
private readonly refreshTokenExpiry: string;
constructor() {
this.secret = process.env.JWT_SECRET || 'your-secret-key';
this.accessTokenExpiry = '15m';
this.refreshTokenExpiry = '7d';
}
generateAccessToken(payload: TokenPayload): string {
return sign(payload, this.secret, {
expiresIn: this.accessTokenExpiry
});
}
generateRefreshToken(userId: string): string {
return sign({ userId }, this.secret, {
expiresIn: this.refreshTokenExpiry
});
}
verifyToken(token: string): TokenPayload {
try {
return verify(token, this.secret) as TokenPayload;
} catch (error) {
if (error.name === 'TokenExpiredError') {
throw new Error('Token has expired');
}
throw new Error('Invalid token');
}
}
refreshAccessToken(refreshToken: string): string {
const payload = this.verifyToken(refreshToken);
if (!payload.userId) {
throw new Error('Invalid refresh token');
}
return this.generateAccessToken({
userId: payload.userId,
roles: payload.roles || []
});
}
}
OAuth & OIDC
OAuth 2.0 Flow
class OAuthService {
private clientId: string;
private clientSecret: string;
private redirectUri: string;
constructor() {
this.clientId = process.env.OAUTH_CLIENT_ID;
this.clientSecret = process.env.OAUTH_CLIENT_SECRET;
this.redirectUri = process.env.OAUTH_REDIRECT_URI;
}
generateAuthUrl(
provider: string,
state: string,
scope: string[]
): string {
const params = new URLSearchParams({
client_id: this.clientId,
redirect_uri: this.redirectUri,
response_type: 'code',
scope: scope.join(' '),
state
});
return `${provider}/oauth/authorize?${params.toString()}`;
}
async exchangeCodeForToken(
provider: string,
code: string
): Promise {
const params = new URLSearchParams({
client_id: this.clientId,
client_secret: this.clientSecret,
code,
grant_type: 'authorization_code',
redirect_uri: this.redirectUri
});
const response = await fetch(
`${provider}/oauth/token`,
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: params.toString()
}
);
if (!response.ok) {
throw new Error('Failed to exchange code for token');
}
return response.json();
}
}
Best Practices
Authentication:
- Implement MFA
- Use strong password policies
- Secure password storage
- Rate limiting
- Account lockout
- Secure session management
Authorization:
- Principle of least privilege
- Role-based access control
- Regular access reviews
- Audit logging
- Token validation
- Secure token storage
Implementation:
- HTTPS everywhere
- Secure cookie settings
- CSRF protection
- XSS prevention
- Input validation
- Error handling