@55387.ai/uniauth-server 1.1.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +110 -0
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -63,6 +63,116 @@ app.get('/api/profile', (c) => {
63
63
  });
64
64
  ```
65
65
 
66
+ ## SSO OAuth2 后端代理登录
67
+
68
+ 当应用配置为 **Confidential Client**(机密客户端)时,需要通过后端完成 Token 交换。
69
+
70
+ ### 流程概述
71
+
72
+ ```
73
+ 用户 → 前端 → /api/auth/login → 后端生成授权 URL → 重定向到 SSO
74
+
75
+ 用户 ← 前端 ← / ← 后端设置 Cookie ← SSO 回调到 /api/auth/callback
76
+
77
+ 后端用 client_secret 交换 Token
78
+ ```
79
+
80
+ ### API 端点
81
+
82
+ | 端点 | URL |
83
+ |------|-----|
84
+ | 授权端点 | `https://sso.55387.xyz/api/v1/oauth2/authorize` |
85
+ | Token 端点 | `https://sso.55387.xyz/api/v1/oauth2/token` |
86
+ | 用户信息端点 | `https://sso.55387.xyz/api/v1/oauth2/userinfo` |
87
+
88
+ ### 实现示例(Hono)
89
+
90
+ ```typescript
91
+ import { Hono } from 'hono';
92
+ import { setCookie, getCookie } from 'hono/cookie';
93
+
94
+ const app = new Hono();
95
+
96
+ // 登录端点 - 重定向到 SSO
97
+ app.get('/api/auth/login', (c) => {
98
+ const origin = c.req.header('origin') || 'http://localhost:3000';
99
+ const redirectUri = `${origin}/api/auth/callback`;
100
+
101
+ const params = new URLSearchParams({
102
+ client_id: process.env.UNIAUTH_CLIENT_ID,
103
+ redirect_uri: redirectUri,
104
+ response_type: 'code',
105
+ scope: 'openid profile email phone',
106
+ state: generateRandomState(), // 生成随机 state 防止 CSRF
107
+ });
108
+
109
+ return c.redirect(`https://sso.55387.xyz/api/v1/oauth2/authorize?${params}`);
110
+ });
111
+
112
+ // 回调端点 - 交换 Token
113
+ app.get('/api/auth/callback', async (c) => {
114
+ const code = c.req.query('code');
115
+ const origin = c.req.header('referer')?.replace(/\/api\/auth\/callback.*$/, '') || 'http://localhost:3000';
116
+
117
+ // 用授权码交换 Token
118
+ const response = await fetch('https://sso.55387.xyz/api/v1/oauth2/token', {
119
+ method: 'POST',
120
+ headers: { 'Content-Type': 'application/json' },
121
+ body: JSON.stringify({
122
+ client_id: process.env.UNIAUTH_CLIENT_ID,
123
+ client_secret: process.env.UNIAUTH_CLIENT_SECRET,
124
+ code,
125
+ grant_type: 'authorization_code',
126
+ redirect_uri: `${origin}/api/auth/callback`,
127
+ }),
128
+ });
129
+
130
+ const { access_token, id_token } = await response.json();
131
+
132
+ // 将 Token 存储到 httpOnly Cookie
133
+ setCookie(c, 'auth_token', id_token, {
134
+ httpOnly: true,
135
+ secure: true,
136
+ sameSite: 'Lax',
137
+ maxAge: 60 * 60 * 24 * 7, // 7 天
138
+ });
139
+
140
+ return c.redirect('/');
141
+ });
142
+
143
+ // 检查登录状态
144
+ app.get('/api/auth/status', async (c) => {
145
+ const token = getCookie(c, 'auth_token');
146
+ if (!token) {
147
+ return c.json({ authenticated: false });
148
+ }
149
+
150
+ // 验证 Token
151
+ try {
152
+ const payload = await auth.verifyToken(token);
153
+ return c.json({ authenticated: true, userId: payload.sub });
154
+ } catch {
155
+ return c.json({ authenticated: false });
156
+ }
157
+ });
158
+ ```
159
+
160
+ ### 前端调用
161
+
162
+ ```typescript
163
+ // 触发登录
164
+ const handleLogin = () => {
165
+ window.location.href = '/api/auth/login';
166
+ };
167
+
168
+ // 检查登录状态
169
+ const checkAuth = async () => {
170
+ const response = await fetch('/api/auth/status', { credentials: 'include' });
171
+ const data = await response.json();
172
+ return data.authenticated;
173
+ };
174
+ ```
175
+
66
176
  ## OAuth2 Token Introspection (RFC 7662)
67
177
 
68
178
  ```typescript
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@55387.ai/uniauth-server",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "description": "UniAuth Server SDK - Token verification for Node.js backends",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",