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

144 lines
4.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
}
}
};