fenghuo/packages/oidc-provider/examples/zod-validation-example.ts

144 lines
4.6 KiB
TypeScript
Raw Normal View History

2025-05-29 12:23:29 +08:00
import { OIDCProvider } from '../src/provider';
import { MemoryStorageAdapter } from '../src/storage/memory';
import type { OIDCProviderConfig, OIDCUser, OIDCClient } from '../src/types';
// 示例带有zod验证的OIDC Provider使用
// 创建存储适配器
const storage = new MemoryStorageAdapter();
// 示例用户查找函数
const findUser = async (userId: string): Promise<OIDCUser | null> => {
const users: Record<string, OIDCUser> = {
'user123': {
sub: 'user123',
username: 'john@example.com',
email: 'john@example.com',
email_verified: true,
name: 'John Doe',
given_name: 'John',
family_name: 'Doe',
}
};
return users[userId] || null;
};
// 示例客户端查找函数
const findClient = async (clientId: string): Promise<OIDCClient | null> => {
const clients: Record<string, OIDCClient> = {
'demo-client': {
client_id: 'demo-client',
client_secret: 'demo-secret',
client_name: 'Demo Application',
client_type: 'confidential',
redirect_uris: ['https://app.example.com/callback'],
grant_types: ['authorization_code', 'refresh_token'],
response_types: ['code'],
scopes: ['openid', 'profile', 'email'],
created_at: new Date(),
updated_at: new Date(),
}
};
return clients[clientId] || null;
};
// 密码验证器
const passwordValidator = async (username: string, password: string): Promise<string | null> => {
// 这里应该实现真实的密码验证逻辑
if (username === 'john@example.com' && password === 'password123') {
return 'user123'; // 返回用户ID
}
return null;
};
// 配置OIDC Provider
const config: OIDCProviderConfig = {
issuer: 'https://auth.example.com',
signingKey: 'your-secret-key-for-development-only',
signingAlgorithm: 'HS256',
storage,
findUser,
findClient,
authConfig: {
passwordValidator,
sessionTTL: 3600, // 1小时
pageConfig: {
title: 'My Auth Server',
brandName: 'Example Corp',
logoUrl: 'https://example.com/logo.png',
},
rememberMeMaxAge: 30 * 24 * 3600, // 30天
},
tokenTTL: {
accessToken: 3600, // 1小时
refreshToken: 30 * 24 * 3600, // 30天
authorizationCode: 600, // 10分钟
idToken: 3600, // 1小时
},
enablePKCE: true,
requirePKCE: true, // 对公共客户端强制要求PKCE
rotateRefreshTokens: true,
};
// 创建OIDC Provider实例
const provider = new OIDCProvider(config);
// 导出配置好的provider
export { provider };
// 使用示例:
// 1. 授权请求会自动使用zod验证所有参数
// 2. 令牌请求会验证FormData和Basic认证头
// 3. 用户信息请求会验证Bearer token格式
// 4. 令牌撤销和内省请求会验证相应的参数
// 错误处理示例:
export const handleAuthorizationExample = async (query: Record<string, string>) => {
try {
// 这会触发zod验证
const result = await provider.handleAuthorizationRequest({
response_type: query.response_type,
client_id: query.client_id,
redirect_uri: query.redirect_uri,
scope: query.scope,
state: query.state,
// ... 其他参数
});
if (result.success) {
console.log('授权码:', result.code);
} else {
console.error('授权失败:', result.error);
}
} catch (error) {
if (error instanceof Error && error.message.includes('授权请求参数无效')) {
console.error('参数验证失败:', error.message);
} else {
console.error('未知错误:', error);
}
}
};
// 令牌请求示例
export const handleTokenExample = async (formData: FormData) => {
try {
// 这会触发zod验证FormData
const result = await provider.handleTokenRequest({
grant_type: formData.get('grant_type')?.toString() || '',
client_id: formData.get('client_id')?.toString() || '',
// ... 其他参数会被自动验证
});
if (result.success) {
console.log('访问令牌:', result.response.access_token);
} else {
console.error('令牌请求失败:', result.error);
}
} catch (error) {
if (error instanceof Error && error.message.includes('令牌请求参数无效')) {
console.error('参数验证失败:', error.message);
} else {
console.error('未知错误:', error);
}
}
};