fenghuo/apps/backend/src/oidc-demo.ts

134 lines
4.4 KiB
TypeScript
Raw Normal View History

2025-05-28 08:23:14 +08:00
import { createOIDCProvider } from '@repo/oidc-provider';
import { RedisStorageAdapter } from '@repo/oidc-provider';
import type { OIDCClient, OIDCUser, OIDCProviderConfig } from '@repo/oidc-provider';
import redis from './redis';
// 示例客户端数据
const demoClients: OIDCClient[] = [
{
client_id: 'demo-client',
client_secret: 'demo-client-secret',
client_name: 'Demo Application',
client_type: 'confidential',
redirect_uris: [
'http://localhost:3001/auth/callback',
'http://localhost:8080/callback',
'https://oauth.pstmn.io/v1/callback'
],
grant_types: ['authorization_code', 'refresh_token'],
response_types: ['code'],
scopes: ['openid', 'profile', 'email'],
token_endpoint_auth_method: 'client_secret_basic',
created_at: new Date(),
updated_at: new Date(),
},
{
client_id: 'demo-public-client',
client_name: 'Demo Public Application',
client_type: 'public',
redirect_uris: [
'http://localhost:3000/callback',
'myapp://callback'
],
grant_types: ['authorization_code'],
response_types: ['code'],
scopes: ['openid', 'profile', 'email'],
token_endpoint_auth_method: 'none',
created_at: new Date(),
updated_at: new Date(),
}
];
// 示例用户数据
const demoUsers: OIDCUser[] = [
{
sub: 'demo-user',
username: 'demouser',
email: 'demo@example.com',
email_verified: true,
name: 'Demo User',
given_name: 'Demo',
family_name: 'User',
picture: 'https://via.placeholder.com/150',
profile: 'https://example.com/demouser',
website: 'https://example.com',
gender: 'prefer_not_to_say',
birthdate: '1990-01-01',
zoneinfo: 'Asia/Shanghai',
locale: 'zh-CN',
phone_number: '+86-123-4567-8901',
phone_number_verified: true,
address: {
formatted: '北京市朝阳区建国门外大街1号',
street_address: '建国门外大街1号',
locality: '朝阳区',
region: '北京市',
postal_code: '100020',
country: 'CN'
},
updated_at: Math.floor(Date.now() / 1000)
}
];
// 查找客户端的函数
async function findClient(clientId: string): Promise<OIDCClient | null> {
return demoClients.find(client => client.client_id === clientId) || null;
}
// 查找用户的函数
async function findUser(userId: string): Promise<OIDCUser | null> {
return demoUsers.find(user => user.sub === userId) || null;
}
// 密码验证函数
async function validatePassword(username: string, password: string): Promise<string | null> {
// 查找用户并验证密码
const user = demoUsers.find(u => u.username === username);
if (!user || password !== 'demo123') {
return null;
}
return user.sub; // 返回用户ID
}
// OIDC Provider 配置
const oidcConfig: OIDCProviderConfig = {
issuer: 'http://localhost:3000/oidc',
signingKey: 'your-super-secret-signing-key-at-least-32-characters-long',
signingAlgorithm: 'HS256',
storage: new RedisStorageAdapter(redis),
findClient,
findUser,
tokenTTL: {
accessToken: 3600, // 1小时
refreshToken: 30 * 24 * 3600, // 30天
authorizationCode: 600, // 10分钟
idToken: 3600, // 1小时
},
responseTypes: ['code'],
grantTypes: ['authorization_code', 'refresh_token'],
scopes: ['openid', 'profile', 'email', 'phone', 'address'],
claims: [
'sub', 'name', 'given_name', 'family_name', 'middle_name', 'nickname',
'preferred_username', 'profile', 'picture', 'website', 'email',
'email_verified', 'gender', 'birthdate', 'zoneinfo', 'locale',
'phone_number', 'phone_number_verified', 'address', 'updated_at'
],
enablePKCE: true,
requirePKCE: false,
rotateRefreshTokens: true,
};
// 使用新的内置认证处理器创建OIDC Provider
export const oidcApp = createOIDCProvider({
config: oidcConfig,
useBuiltInAuth: true,
builtInAuthConfig: {
passwordValidator: validatePassword,
sessionTTL: 24 * 60 * 60, // 24小时
loginPageTitle: 'OIDC Demo 登录',
brandName: 'OIDC Demo Provider',
},
});
// 导出示例数据用于测试
export { demoClients, demoUsers, oidcConfig };