@nihplod/sso-sdk 1.0.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.
package/README.md ADDED
@@ -0,0 +1,360 @@
1
+ # @nihplod/sso-sdk
2
+
3
+ NIHPLOD SSO 子项目接入 SDK — OAuth 2.0 授权码 + PKCE 客户端封装。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ npm install @nihplod/sso-sdk
9
+ ```
10
+
11
+ ## 快速开始
12
+
13
+ ```typescript
14
+ import { SsoClient } from "@nihplod/sso-sdk";
15
+
16
+ const sso = new SsoClient({
17
+ clientId: "your-client-id",
18
+ redirectUri: "https://yourapp.com/callback",
19
+ ssoBaseUrl: "https://nihplod.cn",
20
+ });
21
+
22
+ // 1. 发起登录
23
+ await sso.login();
24
+
25
+ // 2. 处理回调(在回调页面中)
26
+ const token = await sso.handleCallback(window.location.href);
27
+
28
+ // 3. 获取用户信息
29
+ const user = await sso.getUserInfo();
30
+
31
+ // 4. 登出
32
+ await sso.logout();
33
+ ```
34
+
35
+ ---
36
+
37
+ ## API 参考
38
+
39
+ ### `new SsoClient(config)`
40
+
41
+ 创建 SSO 客户端实例。
42
+
43
+ | 参数 | 类型 | 必填 | 说明 |
44
+ |------|------|------|------|
45
+ | `clientId` | `string` | ✅ | OAuth Client ID |
46
+ | `redirectUri` | `string` | ✅ | 回调 URL,须与注册时一致 |
47
+ | `ssoBaseUrl` | `string` | ✅ | SSO 中心地址,如 `https://nihplod.cn` |
48
+ | `scopes` | `string` | ❌ | 空格分隔的 scope,默认 `"openid profile"` |
49
+ | `clientSecret` | `string` | ❌ | **仅 Confidential Client 需要**。浏览器端 SPA(Public Client)请勿传入,避免密钥泄露。BFF / Next.js Route Handler 可传入 |
50
+
51
+ ### `sso.login(returnUrl?)`
52
+
53
+ 发起 SSO 登录。生成 PKCE 参数后 302 跳转到 SSO 登录页。
54
+
55
+ | 参数 | 类型 | 说明 |
56
+ |------|------|------|
57
+ | `returnUrl` | `string` | 登录成功后的返回地址(可选) |
58
+
59
+ ### `sso.getLoginUrl(returnUrl?)`
60
+
61
+ 构建登录 URL 字符串,不执行跳转。返回 `Promise<string>`。
62
+
63
+ ### `sso.handleCallback(callbackUrl)`
64
+
65
+ 处理 OAuth 回调。解析 URL 中的 `code` 和 `state`,校验 state 后用 code 换取 token。
66
+
67
+ | 参数 | 类型 | 说明 |
68
+ |------|------|------|
69
+ | `callbackUrl` | `string` | 完整的回调 URL(`window.location.href`) |
70
+
71
+ 返回 `Promise<TokenData>`。
72
+
73
+ ### `sso.refreshToken()`
74
+
75
+ 使用 refresh_token 刷新 access_token。采用互斥锁防止并发刷新。
76
+
77
+ 返回 `Promise<TokenData>`。
78
+
79
+ ### `sso.getUserInfo()`
80
+
81
+ 获取当前用户信息。若 access_token 已过期则自动刷新。
82
+
83
+ 返回 `Promise<SsoUser>`。
84
+
85
+ ```typescript
86
+ interface SsoUser {
87
+ sub: string;
88
+ nickname?: string;
89
+ avatar?: string;
90
+ phone?: string; // 脱敏手机号
91
+ membership_level?: string;
92
+ total_points?: number;
93
+ }
94
+ ```
95
+
96
+ ### `sso.getAccessToken()`
97
+
98
+ 获取当前有效的 access_token。若已过期则自动刷新。
99
+
100
+ 返回 `Promise<string | null>`。
101
+
102
+ ### `sso.isAuthenticated()`
103
+
104
+ 检查是否已认证(仅本地检查,不发起网络请求)。
105
+
106
+ 返回 `boolean`。
107
+
108
+ ### `sso.logout(redirectToSso?)`
109
+
110
+ 清除本地 token 数据,并尝试撤销服务端 refresh_token。
111
+
112
+ | 参数 | 类型 | 默认 | 说明 |
113
+ |------|------|------|------|
114
+ | `redirectToSso` | `boolean` | `false` | 是否重定向到 SSO 登出页(OIDC RP-Initiated Logout) |
115
+
116
+ 当 `redirectToSso=true` 时,会跳转到 `/logout?client_id=...&post_logout_redirect_uri=...`,
117
+ 由主站完成会话清除后回到子项目回调地址。
118
+
119
+ ### `sso.getDiscovery()`
120
+
121
+ 获取 OIDC Discovery 文档。
122
+
123
+ 返回 `Promise<OidcDiscovery>`。
124
+
125
+ ---
126
+
127
+ ## TypeScript 类型
128
+
129
+ ```typescript
130
+ // SsoClient 配置
131
+ interface SsoClientConfig {
132
+ clientId: string;
133
+ redirectUri: string;
134
+ ssoBaseUrl: string;
135
+ scopes?: string;
136
+ clientSecret?: string; // 仅 Confidential Client 需要
137
+ }
138
+
139
+ // Token 数据
140
+ interface TokenData {
141
+ access_token: string;
142
+ token_type: string;
143
+ expires_in: number;
144
+ refresh_token: string;
145
+ id_token?: string;
146
+ issued_at: number;
147
+ expires_at: number;
148
+ }
149
+
150
+ // 用户信息
151
+ interface SsoUser {
152
+ sub: string;
153
+ nickname?: string;
154
+ avatar?: string;
155
+ phone?: string;
156
+ membership_level?: string;
157
+ total_points?: number;
158
+ }
159
+
160
+ // OIDC Discovery
161
+ interface OidcDiscovery {
162
+ issuer: string;
163
+ authorization_endpoint: string;
164
+ token_endpoint: string;
165
+ userinfo_endpoint: string;
166
+ jwks_uri: string;
167
+ introspection_endpoint: string;
168
+ revocation_endpoint?: string;
169
+ end_session_endpoint?: string;
170
+ scopes_supported: string[];
171
+ response_types_supported: string[];
172
+ grant_types_supported: string[];
173
+ code_challenge_methods_supported: string[];
174
+ }
175
+ ```
176
+
177
+ ---
178
+
179
+ ## React 绑定
180
+
181
+ ### `<SsoProvider>`
182
+
183
+ ```tsx
184
+ import { SsoProvider } from "@nihplod/sso-sdk/react";
185
+
186
+ <SsoProvider
187
+ config={{
188
+ clientId: "...",
189
+ redirectUri: "...",
190
+ ssoBaseUrl: "...",
191
+ scopes: "openid profile",
192
+ }}
193
+ refreshThreshold={60} // 过期前 60s 自动刷新
194
+ >
195
+ <App />
196
+ </SsoProvider>
197
+ ```
198
+
199
+ ### `useSso()`
200
+
201
+ ```tsx
202
+ import { useSso } from "@nihplod/sso-sdk/react";
203
+
204
+ const {
205
+ user, // SsoUser | null
206
+ isAuthenticated, // boolean
207
+ isLoading, // boolean
208
+ login, // (returnUrl?: string) => Promise<void>
209
+ logout, // (redirectToSso?: boolean) => Promise<void>
210
+ refreshUser, // () => Promise<void>
211
+ getAccessToken, // () => Promise<string | null>
212
+ client, // SsoClient 实例
213
+ } = useSso();
214
+ ```
215
+
216
+ ### `<RequireAuth>`
217
+
218
+ ```tsx
219
+ import { RequireAuth } from "@nihplod/sso-sdk/react";
220
+
221
+ <RequireAuth>
222
+ <ProtectedContent />
223
+ </RequireAuth>
224
+ ```
225
+
226
+ ### `withAuth(Component)`
227
+
228
+ ```tsx
229
+ import { withAuth } from "@nihplod/sso-sdk/react";
230
+
231
+ function DashboardPage() { return <div>Dashboard</div>; }
232
+ export default withAuth(DashboardPage);
233
+ ```
234
+
235
+ ### `<CallbackPage>`
236
+
237
+ ```tsx
238
+ import { CallbackPage } from "@nihplod/sso-sdk/react";
239
+
240
+ // 在回调路由中渲染此组件即可
241
+ export default function AuthCallback() {
242
+ return <CallbackPage />;
243
+ }
244
+ ```
245
+
246
+ ---
247
+
248
+ ## Next.js 绑定
249
+
250
+ Next.js 推荐采用 **Middleware + Route Handler** 的 BFF 模式,token 存放在
251
+ `httpOnly` Cookie 中,JavaScript 无法读取,安全性最高。
252
+
253
+ ```typescript
254
+ // src/middleware.ts
255
+ import { createSsoMiddleware } from "@nihplod/sso-sdk/next";
256
+
257
+ export const middleware = createSsoMiddleware({
258
+ clientId: "...",
259
+ ssoBaseUrl: "https://nihplod.cn",
260
+ redirectUri: "https://yourapp.com/api/auth/callback",
261
+ scopes: "openid profile",
262
+ publicPaths: ["/", "/public"],
263
+ // Confidential Client(BFF)可传入 clientSecret
264
+ // clientSecret: process.env.SSO_CLIENT_SECRET,
265
+ });
266
+
267
+ export const config = {
268
+ matcher: ["/((?!_next|favicon.ico).*)"],
269
+ };
270
+ ```
271
+
272
+ ```typescript
273
+ // src/app/api/auth/callback/route.ts
274
+ import { createCallbackRouteHandler } from "@nihplod/sso-sdk/next";
275
+
276
+ export const GET = createCallbackRouteHandler({
277
+ clientId: "...",
278
+ ssoBaseUrl: "https://nihplod.cn",
279
+ redirectUri: "https://yourapp.com/api/auth/callback",
280
+ defaultReturnPath: "/dashboard",
281
+ // 与 middleware 一致,Confidential Client 可传入 clientSecret
282
+ });
283
+ ```
284
+
285
+ ```typescript
286
+ // src/app/api/auth/logout/route.ts
287
+ import { createLogoutRouteHandler } from "@nihplod/sso-sdk/next";
288
+
289
+ export const GET = createLogoutRouteHandler({
290
+ clientId: "...",
291
+ ssoBaseUrl: "https://nihplod.cn",
292
+ redirectUri: "https://yourapp.com/api/auth/callback",
293
+ postLogoutRedirectUri: "https://yourapp.com/",
294
+ redirectToSso: true,
295
+ });
296
+ ```
297
+
298
+ 页面中使用标准 `<a>` 跳转登出端点即可:
299
+
300
+ ```tsx
301
+ <a href="/api/auth/logout">退出登录</a>
302
+ ```
303
+
304
+ ### Cookie 配置
305
+
306
+ 默认 Cookie 名称:
307
+
308
+ | Cookie | 默认名称 | 说明 |
309
+ |--------|----------|------|
310
+ | access_token | `__Host-nihplod_sso_at` | 要求 Secure + Path=/ + 无 Domain |
311
+ | refresh_token | `__Host-nihplod_sso_rt` | 要求 Secure + Path=/ + 无 Domain |
312
+ | state | `__Host-nihplod_sso_state` | 要求 Secure + Path=/ + 无 Domain |
313
+ | return_url | `__Host-nihplod_sso_return` | 要求 Secure + Path=/ + 无 Domain |
314
+ | verifier | `__Secure-nihplod_sso_verifier` | 要求 Secure + 无 Domain;Path 为回调路径,因此使用 `__Secure-` 前缀 |
315
+
316
+ > 本地开发若使用 `http://localhost`,浏览器会拒绝 `Secure` Cookie。此时可仅在本地关闭 `secure`,生产环境必须启用 HTTPS。
317
+
318
+ ---
319
+
320
+ ## 安全建议与 Token 存储
321
+
322
+ SDK 默认将 token 保存在**内存**中,Public Client(SPA/移动端/桌面端)在浏览器中不应把 `refresh_token` 写入 `localStorage`,以防止 XSS 窃取长期凭证。
323
+
324
+ 如果子项目是 **Next.js BFF / Confidential Client**,可以将 token 保存在 `localStorage` 以便多 Tab 共享:
325
+
326
+ ```typescript
327
+ import { setTokenStorage, createSecureStorage } from "@nihplod/sso-sdk";
328
+
329
+ setTokenStorage(createSecureStorage({ persist: true }));
330
+ ```
331
+
332
+ 生产环境更推荐通过 Service Worker 或 HTTP-only Cookie 封装 refresh token,前端只持有 access token 短期凭证。
333
+
334
+ ---
335
+
336
+ ## 工具函数
337
+
338
+ ```typescript
339
+ import {
340
+ generateCodeVerifier,
341
+ generateCodeChallenge,
342
+ generateState,
343
+ setTokenStorage,
344
+ createSecureStorage,
345
+ getTokenData,
346
+ saveTokenData,
347
+ removeTokenData,
348
+ clearAllSsoData,
349
+ } from "@nihplod/sso-sdk";
350
+
351
+ // PKCE
352
+ const verifier = generateCodeVerifier(64);
353
+ const challenge = await generateCodeChallenge(verifier);
354
+
355
+ // State
356
+ const state = generateState();
357
+
358
+ // 自定义 Token 存储(默认内存存储)
359
+ setTokenStorage(createSecureStorage({ persist: false }));
360
+ ```
@@ -0,0 +1,272 @@
1
+ /**
2
+ * Token 存储抽象层
3
+ *
4
+ * 默认使用 localStorage,以支持多 Tab 间自动同步 token 并避免并发刷新。
5
+ * 对 XSS 敏感的子项目可通过 setTokenStorage() 注入更安全的自定义实现
6
+ *(如内存存储、Service Worker 封装、或带加密的 storage)。
7
+ *
8
+ * 多 client 隔离:
9
+ * - token / state / return_url 均支持按 clientId 隔离 key
10
+ * - 不传 clientId 时使用全局 key,保持向后兼容
11
+ */
12
+ /** Token 数据 */
13
+ interface TokenData {
14
+ access_token: string;
15
+ token_type: string;
16
+ expires_in: number;
17
+ refresh_token: string;
18
+ id_token?: string;
19
+ /** Token 签发时间(epoch ms),用于计算过期 */
20
+ issued_at: number;
21
+ /** 访问令牌实际过期时间(epoch ms)= issued_at + expires_in * 1000 */
22
+ expires_at: number;
23
+ }
24
+ /** 存储接口 */
25
+ interface TokenStorage {
26
+ get(key: string): string | null;
27
+ set(key: string, value: string): void;
28
+ remove(key: string): void;
29
+ }
30
+ /**
31
+ * 设置自定义存储实现
32
+ */
33
+ declare function setTokenStorage(storage: TokenStorage): void;
34
+ /**
35
+ * 获取当前存储实现
36
+ */
37
+ declare function getTokenStorage(): TokenStorage;
38
+ declare function saveTokenData(data: TokenData, clientId?: string): void;
39
+ declare function getTokenData(clientId?: string): TokenData | null;
40
+ declare function removeTokenData(clientId?: string): void;
41
+ declare function savePkceVerifier(clientId: string, verifier: string): void;
42
+ declare function getPkceVerifier(clientId: string): string | null;
43
+ declare function removePkceVerifier(clientId: string): void;
44
+ declare function saveOAuthState(state: string, clientId?: string): void;
45
+ declare function getOAuthState(clientId?: string): string | null;
46
+ declare function removeOAuthState(clientId?: string): void;
47
+ declare function saveReturnUrl(url: string, clientId?: string): void;
48
+ declare function getReturnUrl(clientId?: string): string | null;
49
+ declare function removeReturnUrl(clientId?: string): void;
50
+ declare function clearAllSsoData(clientId?: string): void;
51
+ /**
52
+ * 清理指定 clientId 列表的 PKCE verifier
53
+ *
54
+ * 适用于非浏览器环境或已知 clientId 场景。
55
+ */
56
+ declare function clearVerifiersForClients(clientIds: string[]): void;
57
+
58
+ /**
59
+ * SSO Client 核心类
60
+ *
61
+ * 封装完整的 OAuth 2.0 授权码 + PKCE S256 流程:
62
+ * - login(): 发起授权请求
63
+ * - handleCallback(): 处理回调,交换 token
64
+ * - refreshToken(): 刷新 access token(原子轮换)
65
+ * - getUserInfo(): 获取用户信息
66
+ * - logout(): 登出
67
+ * - isAuthenticated(): 检查认证状态
68
+ */
69
+
70
+ /** SSO 客户端配置 */
71
+ interface SsoClientConfig {
72
+ /** OAuth Client ID(从管理后台获取) */
73
+ clientId: string;
74
+ /** OAuth Client Secret(从管理后台获取)
75
+ *
76
+ * ⚠️ 安全提醒:client_secret 不应暴露在前端代码中。
77
+ * 对于浏览器端 SPA(Public Client),应省略此字段;SDK 会使用 PKCE 完成授权,
78
+ * 且 token 端点不会发送 client_secret。
79
+ * 对于 BFF/Next.js 等 Confidential Client,可传入 client_secret。
80
+ */
81
+ clientSecret?: string;
82
+ /** 回调 URL(必须与注册的 redirect_uri 完全一致) */
83
+ redirectUri: string;
84
+ /** SSO 中心地址,如 "https://nihplod.cn" */
85
+ ssoBaseUrl: string;
86
+ /** 请求的 scope(空格分隔),如 "openid profile phone" */
87
+ scopes?: string;
88
+ }
89
+ /** 用户信息 */
90
+ interface SsoUser {
91
+ sub: string;
92
+ nickname?: string;
93
+ avatar?: string;
94
+ phone?: string;
95
+ membership_level?: string;
96
+ total_points?: number;
97
+ }
98
+ /** Token 响应 */
99
+ interface TokenResponse {
100
+ access_token: string;
101
+ token_type: string;
102
+ expires_in: number;
103
+ refresh_token: string;
104
+ id_token?: string;
105
+ }
106
+ /** OIDC Discovery 文档 */
107
+ interface OidcDiscovery {
108
+ issuer: string;
109
+ authorization_endpoint: string;
110
+ token_endpoint: string;
111
+ userinfo_endpoint: string;
112
+ jwks_uri: string;
113
+ introspection_endpoint: string;
114
+ revocation_endpoint?: string;
115
+ end_session_endpoint?: string;
116
+ scopes_supported: string[];
117
+ response_types_supported: string[];
118
+ grant_types_supported: string[];
119
+ code_challenge_methods_supported: string[];
120
+ }
121
+ declare class SsoClient {
122
+ readonly config: SsoClientConfig;
123
+ private _discovery;
124
+ private _discoveryFetchedAt;
125
+ private _refreshLock;
126
+ /** Discovery 文档缓存 TTL(5 分钟) */
127
+ private static readonly DISCOVERY_TTL_MS;
128
+ /** Discovery fetch 超时(10 秒) */
129
+ private static readonly DISCOVERY_TIMEOUT_MS;
130
+ constructor(config: SsoClientConfig);
131
+ /**
132
+ * 获取 OIDC Discovery 文档(带缓存 + 超时)
133
+ *
134
+ * 缓存 5 分钟,超时 10 秒。
135
+ * 失败时返回 null(上层调用方回退到硬编码默认端点)。
136
+ */
137
+ private _getDiscovery;
138
+ /** 获取 authorize 端点 URL(优先 Discovery,回退默认) */
139
+ private _getAuthorizeEndpoint;
140
+ /** 获取 token 端点 URL(优先 Discovery,回退默认) */
141
+ private _getTokenEndpoint;
142
+ /** 获取 userinfo 端点 URL(优先 Discovery,回退默认) */
143
+ private _getUserinfoEndpoint;
144
+ /**
145
+ * 发起 SSO 登录
146
+ *
147
+ * 生成 PKCE code_verifier/code_challenge 和 state 参数,
148
+ * 构建 authorize URL,通过 302 跳转到 SSO 登录页。
149
+ *
150
+ * @param returnUrl - 登录成功后的返回地址(可选,保存到 sessionStorage)
151
+ */
152
+ login(returnUrl?: string): Promise<void>;
153
+ /**
154
+ * 构建登录 URL(不跳转,返回 URL 字符串)
155
+ *
156
+ * 适用于需要手动处理跳转的场景。
157
+ */
158
+ getLoginUrl(returnUrl?: string): Promise<string>;
159
+ /**
160
+ * 处理 OAuth 回调
161
+ *
162
+ * 解析回调 URL,校验 state 参数,用授权码交换 token。
163
+ * 成功后 token 自动保存到 sessionStorage。
164
+ *
165
+ * @param callbackUrl - 完整的回调 URL(window.location.href)
166
+ * @returns TokenData 或 null
167
+ */
168
+ handleCallback(callbackUrl: string): Promise<TokenData>;
169
+ /**
170
+ * 刷新 Access Token
171
+ *
172
+ * 使用 refresh_token 换取新的 access_token。
173
+ * 采用互斥锁防止并发刷新。
174
+ * 支持 Refresh Token 原子轮换。
175
+ */
176
+ refreshToken(): Promise<TokenData>;
177
+ private _doRefreshToken;
178
+ /**
179
+ * 获取用户信息
180
+ *
181
+ * 若 access_token 已过期则自动刷新后再请求。
182
+ */
183
+ getUserInfo(): Promise<SsoUser>;
184
+ /**
185
+ * 获取当前 access_token
186
+ *
187
+ * 若已过期则自动刷新。用于子项目自行发起 API 请求时获取 Bearer token。
188
+ * 若无 token 返回 null;若刷新失败则抛出错误(与 getUserInfo 行为一致)。
189
+ */
190
+ getAccessToken(): Promise<string | null>;
191
+ /**
192
+ * 检查是否已认证(不发起网络请求)
193
+ *
194
+ * 仅检查本地是否存在未过期的 access_token。
195
+ */
196
+ isAuthenticated(): boolean;
197
+ /**
198
+ * 登出
199
+ *
200
+ * 清除本地所有 token 和临时数据,并尝试撤销服务端 refresh_token。
201
+ * @param redirectToSso - 是否重定向到 SSO 登出页(默认 false)
202
+ */
203
+ logout(redirectToSso?: boolean): Promise<void>;
204
+ /**
205
+ * 获取 OIDC Discovery 文档
206
+ *
207
+ * 用于调试和获取 SSO 中心完整配置。
208
+ * 可能返回 null(当 Discovery 端点不可达且无缓存时)。
209
+ */
210
+ getDiscovery(): Promise<OidcDiscovery | null>;
211
+ }
212
+
213
+ /**
214
+ * PKCE (Proof Key for Code Exchange) 工具函数
215
+ *
216
+ * 实现 RFC 7636 规范:
217
+ * - code_verifier: 43-128 字符的随机字符串
218
+ * - code_challenge: SHA-256(code_verifier) 的 base64url 编码
219
+ *
220
+ * 仅支持 S256 模式,不提供 plain 模式。
221
+ */
222
+ /**
223
+ * 生成 code_verifier
224
+ *
225
+ * 生成 43-128 字符之间的安全随机字符串,
226
+ * 使用 `crypto.getRandomValues` 保证密码学安全性。
227
+ *
228
+ * @param length - 长度(默认 64),范围 43-128
229
+ */
230
+ declare function generateCodeVerifier(length?: number): string;
231
+ /**
232
+ * 计算 code_challenge (S256)
233
+ *
234
+ * 对 code_verifier 进行 SHA-256 哈希,然后进行 base64url 编码。
235
+ *
236
+ * @param codeVerifier - PKCE code_verifier
237
+ */
238
+ declare function generateCodeChallenge(codeVerifier: string): Promise<string>;
239
+ /**
240
+ * 生成 state 参数
241
+ *
242
+ * 32 字节 hex 随机字符串,用于 CSRF 防护。
243
+ */
244
+ declare function generateState(): string;
245
+
246
+ /**
247
+ * SSO SDK 错误类型
248
+ */
249
+ /** SSO 错误码 */
250
+ type SsoErrorCode = "invalid_config" | "state_mismatch" | "pkce_required" | "token_request_failed" | "session_expired" | "no_refresh_token" | "userinfo_failed" | "not_authenticated" | "sso_server_error" | "network_error" | "id_token_invalid" | "id_token_unsupported_alg" | "id_token_missing_secret" | "id_token_invalid_signature" | "id_token_issuer_mismatch" | "id_token_audience_mismatch" | "id_token_expired" | "id_token_missing_sub" | "id_token_at_hash_mismatch";
251
+ /** OAuth 2.0 标准错误码 */
252
+ type OAuthErrorCode = "invalid_request" | "invalid_client" | "invalid_grant" | "unauthorized_client" | "unsupported_grant_type" | "invalid_scope" | "access_denied" | "server_error" | "rate_limited";
253
+ /**
254
+ * SSO SDK 自定义错误
255
+ */
256
+ declare class SsoError extends Error {
257
+ readonly code: SsoErrorCode;
258
+ readonly description: string;
259
+ readonly cause?: unknown;
260
+ constructor(code: SsoErrorCode, description: string, cause?: unknown);
261
+ }
262
+ /**
263
+ * OAuth 2.0 服务端返回的错误
264
+ */
265
+ declare class OAuthError extends Error {
266
+ readonly code: OAuthErrorCode;
267
+ readonly description: string;
268
+ readonly uri?: string;
269
+ constructor(code: OAuthErrorCode, description: string, uri?: string);
270
+ }
271
+
272
+ export { OAuthError, type OAuthErrorCode, type OidcDiscovery, SsoClient, type SsoClientConfig, SsoError, type SsoErrorCode, type SsoUser, type TokenData, type TokenResponse, type TokenStorage, clearAllSsoData, clearVerifiersForClients, generateCodeChallenge, generateCodeVerifier, generateState, getOAuthState, getPkceVerifier, getReturnUrl, getTokenData, getTokenStorage, removeOAuthState, removePkceVerifier, removeReturnUrl, removeTokenData, saveOAuthState, savePkceVerifier, saveReturnUrl, saveTokenData, setTokenStorage };