@authms/core 0.1.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/dist/index.d.mts +398 -0
- package/dist/index.d.ts +398 -0
- package/dist/index.js +1337 -0
- package/dist/index.mjs +1294 -0
- package/package.json +48 -0
- package/src/__tests__/api-client.test.ts +314 -0
- package/src/__tests__/auth-client.test.ts +412 -0
- package/src/__tests__/discovery.test.ts +129 -0
- package/src/__tests__/password-transmission.test.ts +131 -0
- package/src/__tests__/sync.test.ts +85 -0
- package/src/__tests__/token-manager.test.ts +104 -0
- package/src/api-client.ts +203 -0
- package/src/auth-client.ts +368 -0
- package/src/authms.ts +244 -0
- package/src/binding.ts +126 -0
- package/src/crypto/index.ts +6 -0
- package/src/crypto/password-transmission.ts +198 -0
- package/src/crypto/pow-solver.ts +41 -0
- package/src/discovery.ts +77 -0
- package/src/errors.ts +44 -0
- package/src/index.ts +39 -0
- package/src/platform/browser.ts +23 -0
- package/src/platform/index.ts +3 -0
- package/src/platform/memory.ts +19 -0
- package/src/platform/types.ts +21 -0
- package/src/plugin.ts +8 -0
- package/src/sync.ts +51 -0
- package/src/token-manager.ts +140 -0
- package/src/types.ts +113 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
interface StorageAdapter {
|
|
2
|
+
getItem(key: string): string | null | Promise<string | null>;
|
|
3
|
+
setItem(key: string, value: string): void | Promise<void>;
|
|
4
|
+
removeItem(key: string): void | Promise<void>;
|
|
5
|
+
keys?(): string[] | Promise<string[]>;
|
|
6
|
+
}
|
|
7
|
+
interface HttpAdapter {
|
|
8
|
+
request(input: string, init?: RequestInit): Promise<Response>;
|
|
9
|
+
}
|
|
10
|
+
interface CryptoAdapter {
|
|
11
|
+
generateCodeChallenge(verifier: string): Promise<string>;
|
|
12
|
+
generateRandomString(length: number): string;
|
|
13
|
+
}
|
|
14
|
+
interface AuthmsPlatform {
|
|
15
|
+
storage: StorageAdapter;
|
|
16
|
+
http: HttpAdapter;
|
|
17
|
+
crypto?: CryptoAdapter;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface User {
|
|
21
|
+
id: string;
|
|
22
|
+
username?: string;
|
|
23
|
+
email?: string;
|
|
24
|
+
phone?: string;
|
|
25
|
+
status?: string;
|
|
26
|
+
avatar?: string;
|
|
27
|
+
[key: string]: unknown;
|
|
28
|
+
}
|
|
29
|
+
interface AuthResult {
|
|
30
|
+
user: User;
|
|
31
|
+
accessToken: string;
|
|
32
|
+
refreshToken: string;
|
|
33
|
+
expiresIn: number;
|
|
34
|
+
tokenType: string;
|
|
35
|
+
}
|
|
36
|
+
interface LoginRequest {
|
|
37
|
+
email?: string;
|
|
38
|
+
phone?: string;
|
|
39
|
+
username?: string;
|
|
40
|
+
password: string;
|
|
41
|
+
tenantId?: string;
|
|
42
|
+
captchaToken?: string;
|
|
43
|
+
captchaProvider?: string;
|
|
44
|
+
captchaChallengeId?: string;
|
|
45
|
+
}
|
|
46
|
+
interface RegisterRequest {
|
|
47
|
+
email?: string;
|
|
48
|
+
phone?: string;
|
|
49
|
+
username?: string;
|
|
50
|
+
password: string;
|
|
51
|
+
tenantId?: string;
|
|
52
|
+
name?: string;
|
|
53
|
+
}
|
|
54
|
+
interface OAuthOptions {
|
|
55
|
+
provider: string;
|
|
56
|
+
redirectUri?: string;
|
|
57
|
+
}
|
|
58
|
+
interface TokenClaims {
|
|
59
|
+
sub?: string;
|
|
60
|
+
user_id?: string;
|
|
61
|
+
tenant_id?: string;
|
|
62
|
+
exp?: number;
|
|
63
|
+
iat?: number;
|
|
64
|
+
session_id?: string;
|
|
65
|
+
type?: string;
|
|
66
|
+
role?: string;
|
|
67
|
+
[key: string]: unknown;
|
|
68
|
+
}
|
|
69
|
+
type AuthmsEvent = 'READY' | 'USER_CHANGED' | 'TOKEN_CHANGED' | 'NOT_AUTHENTICATED' | 'LOGGED_OUT' | 'SECURITY_ALERT';
|
|
70
|
+
interface SecurityAlert {
|
|
71
|
+
reason: 'token_reuse' | 'suspicious_activity' | 'session_revoked';
|
|
72
|
+
message: string;
|
|
73
|
+
}
|
|
74
|
+
interface PasswordPolicyConfig {
|
|
75
|
+
mode: string;
|
|
76
|
+
minLength: number;
|
|
77
|
+
maxLength?: number;
|
|
78
|
+
requireUpper: boolean;
|
|
79
|
+
requireLower?: boolean;
|
|
80
|
+
requireDigit?: boolean;
|
|
81
|
+
requireSpecial?: boolean;
|
|
82
|
+
tenantId: string;
|
|
83
|
+
publicKey: string;
|
|
84
|
+
}
|
|
85
|
+
interface BrandingInfo {
|
|
86
|
+
logoUrl?: string;
|
|
87
|
+
primaryColor?: string;
|
|
88
|
+
companyName?: string;
|
|
89
|
+
loginPageTitle?: string;
|
|
90
|
+
}
|
|
91
|
+
interface TenantAuthConfig {
|
|
92
|
+
tenantId: string;
|
|
93
|
+
tenantName: string;
|
|
94
|
+
displayName: string;
|
|
95
|
+
membershipApproval: string;
|
|
96
|
+
loginMethods: string[];
|
|
97
|
+
oauthProviders: string[];
|
|
98
|
+
passwordPolicy: PasswordPolicyConfig;
|
|
99
|
+
captchaEnabled: boolean;
|
|
100
|
+
captchaProvider: string;
|
|
101
|
+
silentChallengeEnabled: boolean;
|
|
102
|
+
transmissionPublicKey: string;
|
|
103
|
+
oauthClientId: string;
|
|
104
|
+
passkeyEnabled: boolean;
|
|
105
|
+
magicLinkEnabled: boolean;
|
|
106
|
+
branding: BrandingInfo | null;
|
|
107
|
+
}
|
|
108
|
+
declare const ERROR_CODES: {
|
|
109
|
+
readonly CAPTCHA_REQUIRED: "CAPTCHA_REQUIRED";
|
|
110
|
+
readonly INVALID_CAPTCHA: "INVALID_CAPTCHA";
|
|
111
|
+
readonly TOKEN_REUSE: "TOKEN_REUSE";
|
|
112
|
+
readonly SESSION_EXPIRED: "SESSION_EXPIRED";
|
|
113
|
+
readonly REFRESH_FAILED: "REFRESH_FAILED";
|
|
114
|
+
readonly NOT_AUTHENTICATED: "NOT_AUTHENTICATED";
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
declare class TokenManager {
|
|
118
|
+
private storage;
|
|
119
|
+
private prefix;
|
|
120
|
+
private store;
|
|
121
|
+
private changeListeners;
|
|
122
|
+
constructor(storage: StorageAdapter, prefix?: string);
|
|
123
|
+
private initialStore;
|
|
124
|
+
private storageKey;
|
|
125
|
+
load(): Promise<void>;
|
|
126
|
+
persist(): Promise<void>;
|
|
127
|
+
getAccessToken(): string | null;
|
|
128
|
+
getRefreshToken(): string | null;
|
|
129
|
+
getUser(): Record<string, unknown> | null;
|
|
130
|
+
getTenantId(): string | null;
|
|
131
|
+
getExpiresAt(): number | null;
|
|
132
|
+
isAuthenticated(): boolean;
|
|
133
|
+
setTokens(accessToken: string, refreshToken: string, expiresIn: number): void;
|
|
134
|
+
setUser(user: Record<string, unknown>): void;
|
|
135
|
+
setTenantId(tenantId: string | null): void;
|
|
136
|
+
clear(): void;
|
|
137
|
+
onTokenChange(listener: (token: string | null) => void): () => void;
|
|
138
|
+
private notifyListeners;
|
|
139
|
+
decodeToken(token: string): TokenClaims | null;
|
|
140
|
+
isTokenExpired(token: string): boolean;
|
|
141
|
+
getTokenRemainingTime(token: string): number;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
interface ApiClientConfig {
|
|
145
|
+
baseUrl: string;
|
|
146
|
+
tokenManager: TokenManager;
|
|
147
|
+
http: HttpAdapter;
|
|
148
|
+
refreshTokenFn: () => Promise<void>;
|
|
149
|
+
onForceLogout?: () => void;
|
|
150
|
+
}
|
|
151
|
+
declare class ApiClient {
|
|
152
|
+
private baseUrl;
|
|
153
|
+
private tokenManager;
|
|
154
|
+
private http;
|
|
155
|
+
private refreshTokenFn;
|
|
156
|
+
private onForceLogout?;
|
|
157
|
+
private refreshPromise;
|
|
158
|
+
private redirectingToLogin;
|
|
159
|
+
constructor(config: ApiClientConfig);
|
|
160
|
+
get<T>(path: string, params?: Record<string, unknown>): Promise<T>;
|
|
161
|
+
post<T>(path: string, data?: unknown): Promise<T>;
|
|
162
|
+
put<T>(path: string, data?: unknown): Promise<T>;
|
|
163
|
+
delete<T>(path: string, params?: Record<string, unknown>): Promise<T>;
|
|
164
|
+
private buildUrl;
|
|
165
|
+
private request;
|
|
166
|
+
private handle401;
|
|
167
|
+
private handleResponse;
|
|
168
|
+
private handleErrorResponse;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
interface AuthmsPlugin {
|
|
172
|
+
name: string;
|
|
173
|
+
version: string;
|
|
174
|
+
install(core: AuthMS): void | Promise<void>;
|
|
175
|
+
uninstall?(): void | Promise<void>;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
interface AuthmsConfig {
|
|
179
|
+
appId: string;
|
|
180
|
+
issuer: string;
|
|
181
|
+
apiUrl?: string;
|
|
182
|
+
/** @deprecated 使用 issuer + apiUrl */
|
|
183
|
+
authUrl?: string;
|
|
184
|
+
platform: AuthmsPlatform;
|
|
185
|
+
storagePrefix?: string;
|
|
186
|
+
syncTabs?: boolean;
|
|
187
|
+
}
|
|
188
|
+
type EventHandler = (...args: unknown[]) => void;
|
|
189
|
+
declare class AuthMS {
|
|
190
|
+
private config;
|
|
191
|
+
tokenManager: TokenManager;
|
|
192
|
+
api: ApiClient;
|
|
193
|
+
private authClient;
|
|
194
|
+
private discovery;
|
|
195
|
+
private tabSync;
|
|
196
|
+
private eventHandlers;
|
|
197
|
+
private _ready;
|
|
198
|
+
private _userCache;
|
|
199
|
+
private _authConfig;
|
|
200
|
+
constructor(config: AuthmsConfig);
|
|
201
|
+
initialize(): Promise<void>;
|
|
202
|
+
isReady(): boolean;
|
|
203
|
+
get user(): User | null;
|
|
204
|
+
get authConfig(): Record<string, unknown> | null;
|
|
205
|
+
fetchAuthConfig(tenantId?: string): Promise<Record<string, unknown>>;
|
|
206
|
+
getAccessToken(): Promise<string | null>;
|
|
207
|
+
getRefreshToken(): string | null;
|
|
208
|
+
isAuthenticated(): boolean;
|
|
209
|
+
login(credentials: LoginRequest): Promise<AuthResult>;
|
|
210
|
+
loginWithOAuth(options: OAuthOptions): Promise<void>;
|
|
211
|
+
handleOAuthCallback(url: string): Promise<AuthResult>;
|
|
212
|
+
register(data: RegisterRequest): Promise<AuthResult>;
|
|
213
|
+
logout(): Promise<void>;
|
|
214
|
+
getProfile(): Promise<Record<string, unknown> | null>;
|
|
215
|
+
setTenantId(tenantId: string | null): void;
|
|
216
|
+
getTenantId(): string | null;
|
|
217
|
+
use(plugin: AuthmsPlugin): void;
|
|
218
|
+
on(event: AuthmsEvent, handler: EventHandler): () => void;
|
|
219
|
+
emit(event: AuthmsEvent, ...args: unknown[]): void;
|
|
220
|
+
dispose(): void;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* createPlatformBinding — 共享的 Core 绑定逻辑
|
|
225
|
+
*
|
|
226
|
+
* 用于各框架适配器,消除重复的 AuthMS 初始化/状态管理/事件订阅代码。
|
|
227
|
+
* 适配器只需将此 binding 包装成框架特定的组件/hook。
|
|
228
|
+
*/
|
|
229
|
+
|
|
230
|
+
interface BindingConfig {
|
|
231
|
+
appId: string;
|
|
232
|
+
issuer: string;
|
|
233
|
+
apiUrl?: string;
|
|
234
|
+
platform?: AuthmsPlatform;
|
|
235
|
+
storagePrefix?: string;
|
|
236
|
+
syncTabs?: boolean;
|
|
237
|
+
}
|
|
238
|
+
interface PlatformBinding {
|
|
239
|
+
authms: AuthMS;
|
|
240
|
+
/** 获取当前用户(由适配器调用) */
|
|
241
|
+
getUser(): Record<string, unknown> | null;
|
|
242
|
+
/** 获取 auth config(由适配器调用) */
|
|
243
|
+
getAuthConfig(): Record<string, unknown> | null;
|
|
244
|
+
/** 是否已就绪 */
|
|
245
|
+
isReady(): boolean;
|
|
246
|
+
/** 是否已认证 */
|
|
247
|
+
isAuthenticated(): boolean;
|
|
248
|
+
/** 注册状态变更回调,返回取消订阅函数 */
|
|
249
|
+
onChange(handler: () => void): () => void;
|
|
250
|
+
/** 登录 */
|
|
251
|
+
login(credentials: LoginRequest): Promise<AuthResult>;
|
|
252
|
+
/** OAuth 登录 */
|
|
253
|
+
loginWithOAuth(options: OAuthOptions): Promise<void>;
|
|
254
|
+
/** 注册 */
|
|
255
|
+
register(data: LoginRequest): Promise<AuthResult>;
|
|
256
|
+
/** 登出 */
|
|
257
|
+
logout(): Promise<void>;
|
|
258
|
+
/** 获取 access token */
|
|
259
|
+
getAccessToken(): Promise<string | null>;
|
|
260
|
+
/** 切换租户 */
|
|
261
|
+
setTenantId(tenantId: string | null): void;
|
|
262
|
+
/** 获取当前租户 */
|
|
263
|
+
getTenantId(): string | null;
|
|
264
|
+
/** 销毁 */
|
|
265
|
+
dispose(): void;
|
|
266
|
+
}
|
|
267
|
+
declare function createPlatformBinding(config: BindingConfig): PlatformBinding;
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* 密码传输安全模块
|
|
271
|
+
*
|
|
272
|
+
* 移植自 web/packages/shared/src/utils/password-transmission.ts
|
|
273
|
+
* 根据租户 password_transmission 策略在前端对密码进行预处理:
|
|
274
|
+
* plain — 不做处理,原始密码传输
|
|
275
|
+
* hash — SHA-256(password + tenantId)
|
|
276
|
+
* symmetric — ECDH 密钥交换 + AES-256-GCM
|
|
277
|
+
* asymmetric — RSA-OAEP 公钥加密
|
|
278
|
+
*/
|
|
279
|
+
|
|
280
|
+
interface TransmissionResult {
|
|
281
|
+
password: string;
|
|
282
|
+
passwordTransmission: string;
|
|
283
|
+
clientNonce?: string;
|
|
284
|
+
keyExchangeId?: string;
|
|
285
|
+
clientPubKey?: string;
|
|
286
|
+
}
|
|
287
|
+
interface KeyExchangeResult {
|
|
288
|
+
serverPubKey: string;
|
|
289
|
+
keyExchangeId: string;
|
|
290
|
+
}
|
|
291
|
+
type KeyExchangeFn = () => Promise<KeyExchangeResult>;
|
|
292
|
+
/**
|
|
293
|
+
* 根据传输模式预处理密码。
|
|
294
|
+
*/
|
|
295
|
+
declare function processPasswordForTransmission(rawPassword: string, policy: PasswordPolicyConfig, keyExchangeFn?: KeyExchangeFn): Promise<TransmissionResult>;
|
|
296
|
+
|
|
297
|
+
interface AuthClientConfig {
|
|
298
|
+
tokenManager: TokenManager;
|
|
299
|
+
http: AuthmsPlatform['http'];
|
|
300
|
+
baseUrl: string;
|
|
301
|
+
keyExchangeFn?: KeyExchangeFn;
|
|
302
|
+
}
|
|
303
|
+
declare class AuthClient {
|
|
304
|
+
private tokenManager;
|
|
305
|
+
private http;
|
|
306
|
+
private baseUrl;
|
|
307
|
+
private keyExchangeFn?;
|
|
308
|
+
private configCache;
|
|
309
|
+
constructor(config: AuthClientConfig);
|
|
310
|
+
fetchAuthConfig(tenantId?: string): Promise<TenantAuthConfig>;
|
|
311
|
+
clearConfigCache(): void;
|
|
312
|
+
login(credentials: LoginRequest): Promise<AuthResult>;
|
|
313
|
+
register(data: RegisterRequest): Promise<AuthResult>;
|
|
314
|
+
changePassword(currentPassword: string, newPassword: string): Promise<void>;
|
|
315
|
+
loginWithOAuth(options: OAuthOptions): Promise<void>;
|
|
316
|
+
handleOAuthCallback(url: string): Promise<AuthResult>;
|
|
317
|
+
refreshToken(): Promise<void>;
|
|
318
|
+
logout(): Promise<void>;
|
|
319
|
+
getProfile(): Promise<Record<string, unknown> | null>;
|
|
320
|
+
private buildLoginBody;
|
|
321
|
+
private solveCaptchaChallenge;
|
|
322
|
+
private handleAuthResponse;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
interface OIDCDiscoveryMetadata {
|
|
326
|
+
issuer: string;
|
|
327
|
+
authorization_endpoint: string;
|
|
328
|
+
token_endpoint: string;
|
|
329
|
+
userinfo_endpoint?: string;
|
|
330
|
+
jwks_uri: string;
|
|
331
|
+
end_session_endpoint?: string;
|
|
332
|
+
scopes_supported?: string[];
|
|
333
|
+
response_types_supported: string[];
|
|
334
|
+
grant_types_supported?: string[];
|
|
335
|
+
token_endpoint_auth_methods_supported?: string[];
|
|
336
|
+
[key: string]: unknown;
|
|
337
|
+
}
|
|
338
|
+
declare class Discovery {
|
|
339
|
+
private http;
|
|
340
|
+
private metadata;
|
|
341
|
+
private discoveryBaseUrl;
|
|
342
|
+
/**
|
|
343
|
+
* @param http HTTP adapter
|
|
344
|
+
* @param discoveryBaseUrl discovery 请求使用的基础 URL(proxy 模式用 apiUrl,否则留空用 issuer)
|
|
345
|
+
*/
|
|
346
|
+
constructor(http: HttpAdapter, discoveryBaseUrl?: string);
|
|
347
|
+
discover(issuer: string): Promise<OIDCDiscoveryMetadata>;
|
|
348
|
+
getAuthorizationEndpoint(): string | null;
|
|
349
|
+
getTokenEndpoint(): string | null;
|
|
350
|
+
getEndSessionEndpoint(): string | null;
|
|
351
|
+
getJWKSUri(): string | null;
|
|
352
|
+
getMetadata(): OIDCDiscoveryMetadata | null;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
type MessageType = 'LOGOUT' | 'TOKEN_REFRESHED' | 'LOGIN';
|
|
356
|
+
declare class TabSync {
|
|
357
|
+
private channel;
|
|
358
|
+
private onLogout;
|
|
359
|
+
private onTokenChange;
|
|
360
|
+
constructor(onLogout: () => void, onTokenChange: () => void);
|
|
361
|
+
listen(): void;
|
|
362
|
+
broadcast(type: MessageType): void;
|
|
363
|
+
close(): void;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
declare const browserPlatform: AuthmsPlatform;
|
|
367
|
+
|
|
368
|
+
declare function memoryPlatform(): AuthmsPlatform;
|
|
369
|
+
|
|
370
|
+
declare function solveProofOfWork(challenge: string, difficulty?: number, timeoutMs?: number): Promise<string>;
|
|
371
|
+
|
|
372
|
+
declare class AuthmsError extends Error {
|
|
373
|
+
code: string;
|
|
374
|
+
status: number;
|
|
375
|
+
detail?: string;
|
|
376
|
+
constructor(code: string, message: string, status: number, detail?: string);
|
|
377
|
+
}
|
|
378
|
+
declare class AuthmsAuthError extends AuthmsError {
|
|
379
|
+
constructor(code: string, message: string, status: number);
|
|
380
|
+
}
|
|
381
|
+
declare class AuthmsNetworkError extends AuthmsError {
|
|
382
|
+
constructor(message: string);
|
|
383
|
+
}
|
|
384
|
+
declare class AuthmsApiError extends AuthmsError {
|
|
385
|
+
violations?: Array<{
|
|
386
|
+
field: string;
|
|
387
|
+
message: string;
|
|
388
|
+
}>;
|
|
389
|
+
constructor(code: string, message: string, status: number, violations?: Array<{
|
|
390
|
+
field: string;
|
|
391
|
+
message: string;
|
|
392
|
+
}>);
|
|
393
|
+
}
|
|
394
|
+
declare class AuthmsConfigError extends AuthmsError {
|
|
395
|
+
constructor(message: string);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
export { ApiClient, AuthClient, AuthMS, type AuthResult, AuthmsApiError, AuthmsAuthError, type AuthmsConfig, AuthmsConfigError, AuthmsError, type AuthmsEvent, AuthmsNetworkError, type AuthmsPlatform, type AuthmsPlugin, type BindingConfig, type BrandingInfo, type CryptoAdapter, Discovery, ERROR_CODES, type HttpAdapter, type KeyExchangeFn, type LoginRequest, type OAuthOptions, type PasswordPolicyConfig, type PlatformBinding, type RegisterRequest, type SecurityAlert, type StorageAdapter, TabSync, type TenantAuthConfig, type TokenClaims, TokenManager, type TransmissionResult, type User, browserPlatform, createPlatformBinding, memoryPlatform, processPasswordForTransmission, solveProofOfWork };
|