@qlover/oauth-wrapper 0.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.
- package/CHANGELOG.md +27 -0
- package/README.md +313 -0
- package/README_EN.md +313 -0
- package/dist/client.cjs +835 -0
- package/dist/client.d.ts +341 -0
- package/dist/client.js +791 -0
- package/dist/core.cjs +301 -0
- package/dist/core.d.ts +460 -0
- package/dist/core.js +250 -0
- package/dist/index.cjs +1043 -0
- package/dist/index.d.ts +194 -0
- package/dist/index.js +977 -0
- package/package.json +72 -0
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import { StorageInterface, RequestExecutorInterface, RequestAdapterConfig } from '@qlover/fe-corekit';
|
|
2
|
+
import { LoggerInterface } from '@qlover/logger';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
|
|
5
|
+
interface OAuthGatewayAuthorizeParams {
|
|
6
|
+
/**
|
|
7
|
+
* 服务端 URL
|
|
8
|
+
*/
|
|
9
|
+
readonly serverUrl: string;
|
|
10
|
+
/**
|
|
11
|
+
* 服务端鉴权用的客户端 ID
|
|
12
|
+
*/
|
|
13
|
+
readonly clientId: string;
|
|
14
|
+
/**
|
|
15
|
+
* 鉴权范围
|
|
16
|
+
*
|
|
17
|
+
* @default `'openid profile email'`
|
|
18
|
+
*/
|
|
19
|
+
readonly scope?: string;
|
|
20
|
+
/**
|
|
21
|
+
* 鉴权成功后回调地址, 会接收的鉴权回调参数
|
|
22
|
+
*
|
|
23
|
+
* @default `'oauth/callback'`
|
|
24
|
+
*/
|
|
25
|
+
readonly redirectPath?: string;
|
|
26
|
+
/**
|
|
27
|
+
* 跳转目标
|
|
28
|
+
* - _self: 当前窗口
|
|
29
|
+
* - _blank: 新窗口
|
|
30
|
+
*
|
|
31
|
+
* @default _self
|
|
32
|
+
*/
|
|
33
|
+
readonly target?: '_self' | '_blank';
|
|
34
|
+
}
|
|
35
|
+
type OAuthGatewayTokenRequest = {
|
|
36
|
+
readonly grant_type: 'authorization_code' | 'refresh_token';
|
|
37
|
+
readonly code: string;
|
|
38
|
+
readonly redirect_uri: string;
|
|
39
|
+
readonly client_id: string;
|
|
40
|
+
readonly code_verifier: string;
|
|
41
|
+
};
|
|
42
|
+
type OAuthGatewayTokenResult = {
|
|
43
|
+
access_token: string;
|
|
44
|
+
refresh_token?: string;
|
|
45
|
+
expires_in?: number;
|
|
46
|
+
scope?: string;
|
|
47
|
+
};
|
|
48
|
+
type OAuthGatewayUserinfoResult = {
|
|
49
|
+
sub: string;
|
|
50
|
+
email: string;
|
|
51
|
+
name: string;
|
|
52
|
+
roles?: string[] | undefined;
|
|
53
|
+
};
|
|
54
|
+
type OAuthGatewayCallbackParams = {
|
|
55
|
+
code?: string;
|
|
56
|
+
state?: string;
|
|
57
|
+
error?: string;
|
|
58
|
+
error_description?: string;
|
|
59
|
+
};
|
|
60
|
+
interface OAuthGatwayInterface {
|
|
61
|
+
/**
|
|
62
|
+
* 开始鉴权
|
|
63
|
+
*
|
|
64
|
+
* - 跳转 OAuth 授权页面
|
|
65
|
+
*/
|
|
66
|
+
authorize(params: OAuthGatewayAuthorizeParams): Promise<void>;
|
|
67
|
+
authorize(authorizeUrl: string): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* 获取令牌
|
|
70
|
+
*
|
|
71
|
+
* - 请求服务端获取令牌
|
|
72
|
+
*/
|
|
73
|
+
getToken(request: OAuthGatewayTokenRequest): Promise<OAuthGatewayTokenResult>;
|
|
74
|
+
/**
|
|
75
|
+
* 获取用户信息
|
|
76
|
+
*
|
|
77
|
+
* - 请求服务端获取用户信息
|
|
78
|
+
*/
|
|
79
|
+
getUserInfo(accessToken: string): Promise<OAuthGatewayUserinfoResult>;
|
|
80
|
+
/**
|
|
81
|
+
* 处理 OAuth 回调
|
|
82
|
+
*
|
|
83
|
+
* 你可以在回调页面直接调用该方法即可
|
|
84
|
+
*
|
|
85
|
+
* 回调页面见 {@link authorize} {@link OAuthGatewayAuthorizeParams}
|
|
86
|
+
*
|
|
87
|
+
* - 处理 OAuth 回调参数
|
|
88
|
+
*/
|
|
89
|
+
oAuthWrapperCallback(params?: OAuthGatewayCallbackParams | URLSearchParams): Promise<unknown>;
|
|
90
|
+
/**
|
|
91
|
+
* RFC 7009 — revoke the refresh token on the authorization server when provided.
|
|
92
|
+
*/
|
|
93
|
+
revokeToken(options?: {
|
|
94
|
+
refreshToken?: string;
|
|
95
|
+
}): Promise<void>;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
interface OAuthClientInterface {
|
|
99
|
+
/**
|
|
100
|
+
* 是否已配置
|
|
101
|
+
*/
|
|
102
|
+
isConfigured(): boolean;
|
|
103
|
+
/**
|
|
104
|
+
* 开始鉴权
|
|
105
|
+
*
|
|
106
|
+
* @param params
|
|
107
|
+
*/
|
|
108
|
+
startOAuthLogin(params?: OAuthGatewayAuthorizeParams): Promise<void>;
|
|
109
|
+
/**
|
|
110
|
+
* RFC 7009 — revoke the refresh token on the authorization server when provided.
|
|
111
|
+
*/
|
|
112
|
+
revokeToken(refreshToken?: string | null): Promise<void>;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
declare const OAuthWrapperEndpoints: {
|
|
116
|
+
readonly authorize: "/oauth/authorize";
|
|
117
|
+
readonly token: "/oauth/token";
|
|
118
|
+
readonly revoke: "/oauth/revoke";
|
|
119
|
+
readonly userinfo: "/userinfo";
|
|
120
|
+
};
|
|
121
|
+
declare const DEFAULT_OAUTH_AUTHORIZE_PATH: "/oauth/authorize";
|
|
122
|
+
type OAuthAuthorizationConfig = {
|
|
123
|
+
serverUrl: string;
|
|
124
|
+
clientId: string;
|
|
125
|
+
/**
|
|
126
|
+
* @default 'openid profile email'
|
|
127
|
+
*/
|
|
128
|
+
scope?: string;
|
|
129
|
+
/**
|
|
130
|
+
* @default 'oauth/callback'
|
|
131
|
+
*/
|
|
132
|
+
redirectPath?: string;
|
|
133
|
+
};
|
|
134
|
+
declare const DEFAULT_PKCE_STORAGE_KEY = "oauth-wrapper-pkcesession";
|
|
135
|
+
type OAuthLocaleIn = 'path' | 'query' | 'header' | 'none';
|
|
136
|
+
type OAuthLocaleOptions = {
|
|
137
|
+
/** Locale value; omit when locale is not used */
|
|
138
|
+
locale?: string;
|
|
139
|
+
/**
|
|
140
|
+
* Where locale is applied.
|
|
141
|
+
* Defaults to `path` when `locale` is set, otherwise `none`.
|
|
142
|
+
*/
|
|
143
|
+
localeIn?: OAuthLocaleIn;
|
|
144
|
+
/** Query param name when `localeIn` is `query`. @default `'locale'` */
|
|
145
|
+
localeQueryParam?: string;
|
|
146
|
+
/** Header name for token/userinfo requests. @default `'Accept-Language'` */
|
|
147
|
+
localeHeader?: string;
|
|
148
|
+
};
|
|
149
|
+
type OAuthUrlOptions = {
|
|
150
|
+
origin?: string;
|
|
151
|
+
routerPrefix?: string;
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* Static OAuth browser client configuration (not reactive / not persisted as async state).
|
|
155
|
+
*/
|
|
156
|
+
type OAuthClientConfig = OAuthAuthorizationConfig & OAuthUrlOptions & OAuthLocaleOptions;
|
|
157
|
+
declare const defaultOAuthClientConfig: OAuthClientConfig;
|
|
158
|
+
declare function resolveOAuthClientConfig(partial?: Partial<OAuthClientConfig>): OAuthClientConfig;
|
|
159
|
+
|
|
160
|
+
declare const OAuthUserInfoSchema: z.ZodObject<{
|
|
161
|
+
sub: z.ZodString;
|
|
162
|
+
email: z.ZodEmail;
|
|
163
|
+
name: z.ZodString;
|
|
164
|
+
roles: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
165
|
+
}, z.core.$strip>;
|
|
166
|
+
type OAuthUserInfo = z.infer<typeof OAuthUserInfoSchema>;
|
|
167
|
+
declare const OAuthTokenResponseSchema: z.ZodObject<{
|
|
168
|
+
access_token: z.ZodString;
|
|
169
|
+
token_type: z.ZodOptional<z.ZodLiteral<"Bearer">>;
|
|
170
|
+
expires_in: z.ZodOptional<z.ZodNumber>;
|
|
171
|
+
refresh_token: z.ZodOptional<z.ZodString>;
|
|
172
|
+
scope: z.ZodOptional<z.ZodString>;
|
|
173
|
+
}, z.core.$strip>;
|
|
174
|
+
type OAuthTokenResponse = z.infer<typeof OAuthTokenResponseSchema>;
|
|
175
|
+
declare const OAuthTokenErrorSchema: z.ZodObject<{
|
|
176
|
+
error: z.ZodString;
|
|
177
|
+
error_description: z.ZodOptional<z.ZodString>;
|
|
178
|
+
error_id: z.ZodOptional<z.ZodString>;
|
|
179
|
+
}, z.core.$strip>;
|
|
180
|
+
type OAuthCallbackParams = {
|
|
181
|
+
code?: string;
|
|
182
|
+
state?: string;
|
|
183
|
+
error?: string;
|
|
184
|
+
error_description?: string;
|
|
185
|
+
};
|
|
186
|
+
type OAuthUserMapper = (userinfo: OAuthUserInfo, accessToken: string, refreshToken?: string) => unknown | Promise<unknown>;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* PKCE session persisted across the authorize redirect.
|
|
190
|
+
*/
|
|
191
|
+
type PKCESession = {
|
|
192
|
+
readonly state: string;
|
|
193
|
+
readonly codeVerifier: string;
|
|
194
|
+
readonly locale?: string;
|
|
195
|
+
};
|
|
196
|
+
type OAuthClientStoreOptions = {
|
|
197
|
+
pkceStorage?: StorageInterface<string, PKCESession>;
|
|
198
|
+
/**
|
|
199
|
+
* @default {@link DEFAULT_PKCE_STORAGE_KEY}
|
|
200
|
+
*/
|
|
201
|
+
pkceStorageKey?: string;
|
|
202
|
+
};
|
|
203
|
+
/**
|
|
204
|
+
* Session-scoped PKCE storage for the authorization code flow.
|
|
205
|
+
*/
|
|
206
|
+
declare class PKCESessionStore {
|
|
207
|
+
private readonly pkceStorage;
|
|
208
|
+
private readonly pkceStorageKey;
|
|
209
|
+
constructor(options?: OAuthClientStoreOptions);
|
|
210
|
+
savePkceSession(session: PKCESession): void;
|
|
211
|
+
loadPkceSession(): PKCESession | null;
|
|
212
|
+
clearPkceSession(): void;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
type OAuthGatewayRequestConfig = RequestAdapterConfig<string>;
|
|
216
|
+
type OAuthGatewayOptions = {
|
|
217
|
+
store: PKCESessionStore;
|
|
218
|
+
config: OAuthAuthorizationConfig | null;
|
|
219
|
+
mapUser: OAuthUserMapper;
|
|
220
|
+
/** When provided, token/userinfo requests go through the executor; otherwise uses fetch */
|
|
221
|
+
requester?: RequestExecutorInterface<OAuthGatewayRequestConfig>;
|
|
222
|
+
} & OAuthUrlOptions & OAuthLocaleOptions & {
|
|
223
|
+
authorizePath?: string;
|
|
224
|
+
};
|
|
225
|
+
declare class OAuthGateway<T = unknown> implements OAuthGatwayInterface {
|
|
226
|
+
private readonly options;
|
|
227
|
+
private readonly callbackInflight;
|
|
228
|
+
constructor(options: OAuthGatewayOptions);
|
|
229
|
+
private get localeOptions();
|
|
230
|
+
private get authorizePath();
|
|
231
|
+
private get urlOptions();
|
|
232
|
+
private getServerUrl;
|
|
233
|
+
private buildRequestHeaders;
|
|
234
|
+
private requestJson;
|
|
235
|
+
/**
|
|
236
|
+
* @override
|
|
237
|
+
*/
|
|
238
|
+
authorize(params: OAuthGatewayAuthorizeParams): Promise<void>;
|
|
239
|
+
/**
|
|
240
|
+
* @override
|
|
241
|
+
*/
|
|
242
|
+
authorize(authorizeUrl: string): Promise<void>;
|
|
243
|
+
/**
|
|
244
|
+
* @override
|
|
245
|
+
*/
|
|
246
|
+
getToken(request: OAuthGatewayTokenRequest): Promise<OAuthGatewayTokenResult>;
|
|
247
|
+
/**
|
|
248
|
+
* @override
|
|
249
|
+
*/
|
|
250
|
+
getUserInfo(accessToken: string): Promise<OAuthGatewayUserinfoResult>;
|
|
251
|
+
/**
|
|
252
|
+
* @override
|
|
253
|
+
*/
|
|
254
|
+
oAuthWrapperCallback(params?: OAuthGatewayCallbackParams | URLSearchParams): Promise<T>;
|
|
255
|
+
private runOAuthWrapperCallback;
|
|
256
|
+
/**
|
|
257
|
+
* @override
|
|
258
|
+
*/
|
|
259
|
+
revokeToken(options?: {
|
|
260
|
+
refreshToken?: string;
|
|
261
|
+
}): Promise<void>;
|
|
262
|
+
private postRevokeToken;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
type OAuthClientInfrastructureOptions<T extends OAuthUserInfo> = {
|
|
266
|
+
serviceName?: string | symbol;
|
|
267
|
+
gateway?: OAuthGateway<T>;
|
|
268
|
+
mapUser?: OAuthUserMapper;
|
|
269
|
+
requester?: RequestExecutorInterface<RequestAdapterConfig<string>>;
|
|
270
|
+
logger?: LoggerInterface;
|
|
271
|
+
authorizePath?: string;
|
|
272
|
+
};
|
|
273
|
+
type OAuthClientOptions<T extends OAuthUserInfo = OAuthUserInfo> = OAuthClientInfrastructureOptions<T> & OAuthClientStoreOptions & {
|
|
274
|
+
config?: Partial<OAuthClientConfig>;
|
|
275
|
+
} & Partial<OAuthClientConfig>;
|
|
276
|
+
declare class OAuthClient<T extends OAuthUserInfo = OAuthUserInfo> implements OAuthClientInterface {
|
|
277
|
+
readonly serviceName: string | symbol;
|
|
278
|
+
readonly config: OAuthClientConfig;
|
|
279
|
+
protected readonly authorizePath: string;
|
|
280
|
+
protected readonly mapUser?: OAuthUserMapper;
|
|
281
|
+
protected readonly requester?: RequestExecutorInterface<RequestAdapterConfig<string>>;
|
|
282
|
+
protected readonly logger?: LoggerInterface;
|
|
283
|
+
protected readonly pkceStore: PKCESessionStore;
|
|
284
|
+
protected readonly gateway: OAuthGateway<T>;
|
|
285
|
+
constructor(options: OAuthClientOptions<T>);
|
|
286
|
+
patchConfig(config: Partial<OAuthClientConfig>): void;
|
|
287
|
+
protected get authorizationConfig(): OAuthAuthorizationConfig | null;
|
|
288
|
+
protected get urlOptions(): OAuthUrlOptions;
|
|
289
|
+
protected get localeOptions(): OAuthLocaleOptions;
|
|
290
|
+
getGateway(): OAuthGateway<T>;
|
|
291
|
+
getLogger(): LoggerInterface | undefined;
|
|
292
|
+
/**
|
|
293
|
+
* @override
|
|
294
|
+
*/
|
|
295
|
+
isConfigured(): boolean;
|
|
296
|
+
/**
|
|
297
|
+
* @override
|
|
298
|
+
*/
|
|
299
|
+
startOAuthLogin(params?: OAuthGatewayAuthorizeParams): Promise<void>;
|
|
300
|
+
completeOAuthCallback(params?: Parameters<OAuthGateway<T>['oAuthWrapperCallback']>[0]): Promise<T>;
|
|
301
|
+
parseOAuthCallbackSearchParams(searchParams: URLSearchParams): Parameters<OAuthGateway<T>['oAuthWrapperCallback']>[0];
|
|
302
|
+
/**
|
|
303
|
+
* @override
|
|
304
|
+
*/
|
|
305
|
+
revokeToken(refreshToken?: string | null): Promise<void>;
|
|
306
|
+
/**
|
|
307
|
+
* Fetch user profile from the OAuth userinfo endpoint and map it via {@link mapUser}.
|
|
308
|
+
*/
|
|
309
|
+
fetchUserInfo(accessToken: string, refreshToken?: string): Promise<T>;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
type ResolvedOAuthAuthorizationConfig = OAuthAuthorizationConfig & {
|
|
313
|
+
scope: string;
|
|
314
|
+
redirectPath: string;
|
|
315
|
+
};
|
|
316
|
+
declare function buildAuthorizeSearchParams(input: {
|
|
317
|
+
clientId: string;
|
|
318
|
+
redirectUri: string;
|
|
319
|
+
scope: string;
|
|
320
|
+
state: string;
|
|
321
|
+
codeChallenge: string;
|
|
322
|
+
}): URLSearchParams;
|
|
323
|
+
declare function mergeOAuthAuthorizationConfig(params: Partial<OAuthGatewayAuthorizeParams> | undefined, baseConfig: OAuthAuthorizationConfig | null | undefined): ResolvedOAuthAuthorizationConfig | null;
|
|
324
|
+
declare function buildOAuthRedirectUri(redirectPath: string, options?: OAuthUrlOptions & OAuthLocaleOptions): string;
|
|
325
|
+
declare function formatOAuthAuthorizeUrl(serverUrl: string, authorizePath: string, searchParams: URLSearchParams, localeOptions?: OAuthLocaleOptions): string;
|
|
326
|
+
type BuildOAuthAuthorizeUrlInput = {
|
|
327
|
+
config: ResolvedOAuthAuthorizationConfig;
|
|
328
|
+
authorizePath: string;
|
|
329
|
+
state: string;
|
|
330
|
+
codeChallenge: string;
|
|
331
|
+
redirectPath?: string;
|
|
332
|
+
scope?: string;
|
|
333
|
+
} & OAuthUrlOptions & OAuthLocaleOptions;
|
|
334
|
+
declare function buildOAuthAuthorizeUrl(input: BuildOAuthAuthorizeUrlInput): string;
|
|
335
|
+
declare function buildOAuthLocaleHeaders(options?: OAuthLocaleOptions): Record<string, string>;
|
|
336
|
+
|
|
337
|
+
declare function parseOAuthTokenResponse(json: unknown): OAuthTokenResponse;
|
|
338
|
+
declare function parseOAuthTokenError(json: unknown, fallback: string): string;
|
|
339
|
+
declare function parseOAuthUserInfoResponse(json: unknown): OAuthUserInfo;
|
|
340
|
+
|
|
341
|
+
export { type BuildOAuthAuthorizeUrlInput, DEFAULT_OAUTH_AUTHORIZE_PATH, DEFAULT_PKCE_STORAGE_KEY, type OAuthAuthorizationConfig, type OAuthCallbackParams, OAuthClient, type OAuthClientConfig, type OAuthClientInterface, type OAuthClientOptions, type OAuthClientStoreOptions, OAuthGateway, type OAuthGatewayAuthorizeParams, type OAuthGatewayCallbackParams, type OAuthGatewayOptions, type OAuthGatewayRequestConfig, type OAuthGatewayTokenRequest, type OAuthGatewayTokenResult, type OAuthGatewayUserinfoResult, type OAuthGatwayInterface, type OAuthLocaleIn, type OAuthLocaleOptions, OAuthTokenErrorSchema, type OAuthTokenResponse, OAuthTokenResponseSchema, type OAuthUrlOptions, type OAuthUserInfo, OAuthUserInfoSchema, type OAuthUserMapper, OAuthWrapperEndpoints, type PKCESession, PKCESessionStore, type ResolvedOAuthAuthorizationConfig, buildAuthorizeSearchParams, buildOAuthAuthorizeUrl, buildOAuthLocaleHeaders, buildOAuthRedirectUri, defaultOAuthClientConfig, formatOAuthAuthorizeUrl, mergeOAuthAuthorizationConfig, parseOAuthTokenError, parseOAuthTokenResponse, parseOAuthUserInfoResponse, resolveOAuthClientConfig };
|