binoauth 0.0.11 → 0.0.13

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 (111) hide show
  1. package/README.md +359 -165
  2. package/dist/core/src/admin/client.d.ts +203 -0
  3. package/dist/core/src/admin/client.d.ts.map +1 -0
  4. package/dist/core/src/admin/client.js +391 -0
  5. package/dist/core/src/admin/client.js.map +1 -0
  6. package/dist/core/src/admin/index.d.ts +6 -0
  7. package/dist/core/src/admin/index.d.ts.map +1 -0
  8. package/dist/core/src/admin/index.js +5 -0
  9. package/dist/core/src/admin/index.js.map +1 -0
  10. package/dist/core/src/admin/types.d.ts +412 -0
  11. package/dist/core/src/admin/types.d.ts.map +1 -0
  12. package/dist/core/src/admin/types.js +5 -0
  13. package/dist/core/src/admin/types.js.map +1 -0
  14. package/dist/core/src/auth/client.d.ts +330 -0
  15. package/dist/core/src/auth/client.d.ts.map +1 -0
  16. package/dist/core/src/auth/client.js +408 -0
  17. package/dist/core/src/auth/client.js.map +1 -0
  18. package/dist/core/src/auth/error.d.ts +113 -0
  19. package/dist/core/src/auth/error.d.ts.map +1 -0
  20. package/dist/core/src/auth/error.js +257 -0
  21. package/dist/core/src/auth/error.js.map +1 -0
  22. package/dist/core/src/auth/flows/base-flow.d.ts +98 -0
  23. package/dist/core/src/auth/flows/base-flow.d.ts.map +1 -0
  24. package/dist/core/src/auth/flows/base-flow.js +182 -0
  25. package/dist/core/src/auth/flows/base-flow.js.map +1 -0
  26. package/dist/core/src/auth/flows/magic-link.d.ts +175 -0
  27. package/dist/core/src/auth/flows/magic-link.d.ts.map +1 -0
  28. package/dist/core/src/auth/flows/magic-link.js +228 -0
  29. package/dist/core/src/auth/flows/magic-link.js.map +1 -0
  30. package/dist/core/src/auth/flows/mfa.d.ts +81 -0
  31. package/dist/core/src/auth/flows/mfa.d.ts.map +1 -0
  32. package/dist/core/src/auth/flows/mfa.js +103 -0
  33. package/dist/core/src/auth/flows/mfa.js.map +1 -0
  34. package/dist/core/src/auth/flows/otp.d.ts +172 -0
  35. package/dist/core/src/auth/flows/otp.d.ts.map +1 -0
  36. package/dist/core/src/auth/flows/otp.js +222 -0
  37. package/dist/core/src/auth/flows/otp.js.map +1 -0
  38. package/dist/core/src/auth/flows/password.d.ts +242 -0
  39. package/dist/core/src/auth/flows/password.d.ts.map +1 -0
  40. package/dist/core/src/auth/flows/password.js +344 -0
  41. package/dist/core/src/auth/flows/password.js.map +1 -0
  42. package/dist/core/src/auth/flows/social.d.ts +209 -0
  43. package/dist/core/src/auth/flows/social.d.ts.map +1 -0
  44. package/dist/core/src/auth/flows/social.js +284 -0
  45. package/dist/core/src/auth/flows/social.js.map +1 -0
  46. package/dist/core/src/auth/index.d.ts +19 -0
  47. package/dist/core/src/auth/index.d.ts.map +1 -0
  48. package/dist/core/src/auth/index.js +32 -0
  49. package/dist/core/src/auth/index.js.map +1 -0
  50. package/dist/core/src/auth/types.d.ts +151 -0
  51. package/dist/core/src/auth/types.d.ts.map +1 -0
  52. package/dist/core/src/auth/types.js +7 -0
  53. package/dist/core/src/auth/types.js.map +1 -0
  54. package/dist/core/src/index.d.ts +53 -49
  55. package/dist/core/src/index.d.ts.map +1 -1
  56. package/dist/core/src/index.js +61 -343
  57. package/dist/core/src/index.js.map +1 -1
  58. package/dist/core/src/oauth/client.d.ts +322 -0
  59. package/dist/core/src/oauth/client.d.ts.map +1 -0
  60. package/dist/core/src/oauth/client.js +491 -0
  61. package/dist/core/src/oauth/client.js.map +1 -0
  62. package/dist/core/src/oauth/error.d.ts +18 -0
  63. package/dist/core/src/oauth/error.d.ts.map +1 -0
  64. package/dist/core/src/oauth/error.js +24 -0
  65. package/dist/core/src/oauth/error.js.map +1 -0
  66. package/dist/core/src/oauth/flows/authorization-code.d.ts +122 -0
  67. package/dist/core/src/oauth/flows/authorization-code.d.ts.map +1 -0
  68. package/dist/core/src/oauth/flows/authorization-code.js +278 -0
  69. package/dist/core/src/oauth/flows/authorization-code.js.map +1 -0
  70. package/dist/core/src/oauth/flows/base-flow.d.ts +17 -0
  71. package/dist/core/src/oauth/flows/base-flow.d.ts.map +1 -0
  72. package/dist/core/src/oauth/flows/base-flow.js +107 -0
  73. package/dist/core/src/oauth/flows/base-flow.js.map +1 -0
  74. package/dist/core/src/oauth/flows/client-credentials.d.ts +72 -0
  75. package/dist/core/src/oauth/flows/client-credentials.d.ts.map +1 -0
  76. package/dist/core/src/oauth/flows/client-credentials.js +100 -0
  77. package/dist/core/src/oauth/flows/client-credentials.js.map +1 -0
  78. package/dist/core/src/oauth/flows/device-code.d.ts +108 -0
  79. package/dist/core/src/oauth/flows/device-code.d.ts.map +1 -0
  80. package/dist/core/src/oauth/flows/device-code.js +193 -0
  81. package/dist/core/src/oauth/flows/device-code.js.map +1 -0
  82. package/dist/core/src/oauth/flows/refresh-token.d.ts +59 -0
  83. package/dist/core/src/oauth/flows/refresh-token.d.ts.map +1 -0
  84. package/dist/core/src/oauth/flows/refresh-token.js +105 -0
  85. package/dist/core/src/oauth/flows/refresh-token.js.map +1 -0
  86. package/dist/core/src/oauth/index.d.ts +12 -0
  87. package/dist/core/src/oauth/index.d.ts.map +1 -0
  88. package/dist/core/src/oauth/index.js +11 -0
  89. package/dist/core/src/oauth/index.js.map +1 -0
  90. package/dist/core/src/oauth/storage/encryption.d.ts +12 -0
  91. package/dist/core/src/oauth/storage/encryption.d.ts.map +1 -0
  92. package/dist/core/src/oauth/storage/encryption.js +76 -0
  93. package/dist/core/src/oauth/storage/encryption.js.map +1 -0
  94. package/dist/core/src/oauth/storage/index.d.ts +201 -0
  95. package/dist/core/src/oauth/storage/index.d.ts.map +1 -0
  96. package/dist/core/src/oauth/storage/index.js +322 -0
  97. package/dist/core/src/oauth/storage/index.js.map +1 -0
  98. package/dist/core/src/oauth/storage/strategies.d.ts +34 -0
  99. package/dist/core/src/oauth/storage/strategies.d.ts.map +1 -0
  100. package/dist/core/src/oauth/storage/strategies.js +100 -0
  101. package/dist/core/src/oauth/storage/strategies.js.map +1 -0
  102. package/dist/core/src/oauth/types.d.ts +261 -0
  103. package/dist/core/src/oauth/types.d.ts.map +1 -0
  104. package/dist/core/src/oauth/types.js +39 -0
  105. package/dist/core/src/oauth/types.js.map +1 -0
  106. package/dist/core/src/oauth/utils.d.ts +56 -0
  107. package/dist/core/src/oauth/utils.d.ts.map +1 -0
  108. package/dist/core/src/oauth/utils.js +140 -0
  109. package/dist/core/src/oauth/utils.js.map +1 -0
  110. package/dist/tsconfig.tsbuildinfo +1 -1
  111. package/package.json +1 -1
@@ -0,0 +1,491 @@
1
+ import { createAuthConfigFromIssuer } from "./types";
2
+ import { TokenStorage } from "./storage";
3
+ import { AuthorizationCodeFlow } from "./flows/authorization-code";
4
+ import { RefreshTokenFlow } from "./flows/refresh-token";
5
+ import { DeviceCodeFlow } from "./flows/device-code";
6
+ import { ClientCredentialsFlow } from "./flows/client-credentials";
7
+ import { isJWT } from "./utils";
8
+ import { AuthError, ErrorCode } from "./error";
9
+ import { Configuration } from "@binoauth/tenant-sdk";
10
+ /**
11
+ * BinoAuth OAuth 2.0 Client
12
+ *
13
+ * A comprehensive OAuth 2.0 client that supports multiple grant types
14
+ * including Authorization Code, Device Code, Client Credentials, and Refresh Token flows.
15
+ *
16
+ * Features:
17
+ * - Automatic token refresh and management
18
+ * - PKCE support for secure authentication
19
+ * - Device authorization for IoT and limited-input devices
20
+ * - Server-to-server authentication with client credentials
21
+ * - Secure token storage with encryption
22
+ * - Rate limiting and CSRF protection
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * import { BinoAuthOAuth, InMemoryTokenStorage } from 'binoauth';
27
+ *
28
+ * // Simple configuration using issuer
29
+ * const client = new BinoAuthOAuth({
30
+ * issuer: 'https://auth.binoauth.com',
31
+ * clientId: 'your_client_id',
32
+ * redirectUri: 'https://yourapp.com/callback',
33
+ * scope: 'openid profile email'
34
+ * }, {
35
+ * storage: new InMemoryTokenStorage(),
36
+ * clientId: 'your_client_id'
37
+ * });
38
+ *
39
+ * // Authorization Code Flow (for web/mobile apps)
40
+ * const loginUrl = await client.getLoginUrl();
41
+ * window.location.href = loginUrl;
42
+ *
43
+ * // Handle callback after user returns
44
+ * const urlParams = new URLSearchParams(window.location.search);
45
+ * await client.handleCallback(
46
+ * urlParams.get('code')!,
47
+ * urlParams.get('state')!
48
+ * );
49
+ *
50
+ * // Check authentication status
51
+ * const isLoggedIn = await client.isAuthenticated();
52
+ * if (isLoggedIn) {
53
+ * const userInfo = await client.getUserInfo();
54
+ * console.log('Logged in as:', userInfo.email);
55
+ * }
56
+ * ```
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * // Device Code Flow (for TVs, IoT devices, CLI tools)
61
+ * const deviceAuth = await client.requestDeviceCode();
62
+ * console.log(`Visit: ${deviceAuth.verification_uri}`);
63
+ * console.log(`Enter code: ${deviceAuth.user_code}`);
64
+ *
65
+ * // Poll for authorization
66
+ * const pollInterval = deviceAuth.interval * 1000;
67
+ * while (true) {
68
+ * try {
69
+ * await client.pollForToken(deviceAuth.device_code);
70
+ * console.log('Device authorized successfully!');
71
+ * break;
72
+ * } catch (error) {
73
+ * if (error.code === 'authorization_pending') {
74
+ * await new Promise(resolve => setTimeout(resolve, pollInterval));
75
+ * continue;
76
+ * }
77
+ * throw error;
78
+ * }
79
+ * }
80
+ * ```
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * // Client Credentials Flow (for server-to-server)
85
+ * client.initializeClientCredentials('your_client_secret');
86
+ * await client.getClientCredentialsTokens();
87
+ *
88
+ * // Use token for API calls
89
+ * const accessToken = await client.getAccessToken();
90
+ * const response = await fetch('/api/protected', {
91
+ * headers: { 'Authorization': `Bearer ${accessToken}` }
92
+ * });
93
+ * ```
94
+ */
95
+ export class BinoAuthOAuth {
96
+ config;
97
+ storage;
98
+ oauthApi;
99
+ authCodeFlow;
100
+ refreshFlow;
101
+ deviceFlow;
102
+ clientCredentialsFlow;
103
+ /**
104
+ * Creates a new BinoAuth OAuth client
105
+ *
106
+ * @param config - OAuth configuration (can use simplified BinoAuthConfig with issuer)
107
+ * @param storageConfig - Token storage configuration
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * // Simple configuration with issuer
112
+ * const client = new BinoAuthOAuth({
113
+ * issuer: 'https://auth.binoauth.com',
114
+ * clientId: 'your_client_id',
115
+ * redirectUri: 'https://yourapp.com/callback'
116
+ * }, {
117
+ * storage: new InMemoryTokenStorage(),
118
+ * clientId: 'your_client_id'
119
+ * });
120
+ *
121
+ * // Full configuration
122
+ * const client = new BinoAuthOAuth({
123
+ * clientId: 'your_client_id',
124
+ * redirectUri: 'https://yourapp.com/callback',
125
+ * authorizeEndpoint: 'https://auth.binoauth.com/api/v1/oauth/authorize',
126
+ * tokenEndpoint: 'https://auth.binoauth.com/api/v1/oauth/token',
127
+ * userInfoEndpoint: 'https://auth.binoauth.com/api/v1/oauth/userinfo'
128
+ * }, storageConfig);
129
+ * ```
130
+ */
131
+ constructor(config, storageConfig) {
132
+ // Convert BinoAuthConfig to AuthConfig if needed
133
+ this.config = 'issuer' in config ? createAuthConfigFromIssuer(config) : config;
134
+ this.storage = new TokenStorage({
135
+ ...storageConfig,
136
+ clientId: storageConfig.clientId || this.config.clientId,
137
+ });
138
+ // Create tenant-SDK OAuth API if we have issuer-based config
139
+ if ('issuer' in config) {
140
+ try {
141
+ const { OAuth2Api } = require("@binoauth/tenant-sdk");
142
+ const tenantConfig = new Configuration({
143
+ basePath: config.issuer,
144
+ });
145
+ this.oauthApi = new OAuth2Api(tenantConfig);
146
+ }
147
+ catch (error) {
148
+ console.warn("Failed to initialize tenant-SDK OAuth API:", error);
149
+ }
150
+ }
151
+ this.authCodeFlow = new AuthorizationCodeFlow(this.config, this.storage, this.oauthApi);
152
+ this.refreshFlow = new RefreshTokenFlow(this.config, this.storage, this.oauthApi);
153
+ this.deviceFlow = new DeviceCodeFlow(this.config, this.storage, this.oauthApi);
154
+ }
155
+ /**
156
+ * Initializes client credentials flow for server-to-server authentication
157
+ *
158
+ * @param clientSecret - The client secret for authentication
159
+ *
160
+ * @example
161
+ * ```typescript
162
+ * client.initializeClientCredentials('your_client_secret');
163
+ * await client.getClientCredentialsTokens();
164
+ * ```
165
+ */
166
+ initializeClientCredentials(clientSecret) {
167
+ this.clientCredentialsFlow = new ClientCredentialsFlow({ ...this.config, clientSecret }, this.storage, this.oauthApi);
168
+ }
169
+ /**
170
+ * Updates the token storage instance
171
+ *
172
+ * @param tokenStorage - New token storage instance
173
+ */
174
+ setTokenStorage(tokenStorage) {
175
+ this.storage = tokenStorage;
176
+ }
177
+ /**
178
+ * Gets the current token storage instance
179
+ *
180
+ * @returns The current token storage
181
+ */
182
+ getTokenStorage() {
183
+ return this.storage;
184
+ }
185
+ // Authorization Code Flow methods
186
+ /**
187
+ * Generates the authorization URL for the OAuth flow
188
+ *
189
+ * @returns Promise resolving to the authorization URL
190
+ *
191
+ * @example
192
+ * ```typescript
193
+ * const loginUrl = await client.getLoginUrl();
194
+ * window.location.href = loginUrl; // Redirect user to BinoAuth
195
+ * ```
196
+ */
197
+ async getLoginUrl() {
198
+ return this.authCodeFlow.getLoginUrl();
199
+ }
200
+ /**
201
+ * Handles the OAuth callback and exchanges code for tokens
202
+ *
203
+ * @param code - Authorization code from callback
204
+ * @param state - State parameter from callback
205
+ *
206
+ * @example
207
+ * ```typescript
208
+ * const urlParams = new URLSearchParams(window.location.search);
209
+ * await client.handleCallback(
210
+ * urlParams.get('code')!,
211
+ * urlParams.get('state')!
212
+ * );
213
+ * ```
214
+ */
215
+ async handleCallback(code, state) {
216
+ return this.authCodeFlow.handleCallback(code, state);
217
+ }
218
+ /**
219
+ * Generates the logout URL
220
+ *
221
+ * @returns Promise resolving to the logout URL
222
+ */
223
+ async getLogoutUrl() {
224
+ return this.authCodeFlow.getLogoutUrl();
225
+ }
226
+ /**
227
+ * Generates the logout page URL with optional return URL
228
+ *
229
+ * @param returnTo - Optional URL to redirect to after logout
230
+ * @returns Promise resolving to the logout page URL
231
+ */
232
+ async getLogoutPageUrl(returnTo) {
233
+ return this.authCodeFlow.getLogoutPageUrl(returnTo);
234
+ }
235
+ // Device Code Flow methods
236
+ /**
237
+ * Initiates device authorization flow
238
+ *
239
+ * @returns Promise resolving to device authorization response
240
+ *
241
+ * @example
242
+ * ```typescript
243
+ * const deviceAuth = await client.requestDeviceCode();
244
+ * console.log(`Visit: ${deviceAuth.verification_uri}`);
245
+ * console.log(`Enter code: ${deviceAuth.user_code}`);
246
+ * ```
247
+ */
248
+ async requestDeviceCode() {
249
+ return this.deviceFlow.requestDeviceCode();
250
+ }
251
+ /**
252
+ * Polls for token using device code
253
+ *
254
+ * @param deviceCode - Device code from requestDeviceCode()
255
+ *
256
+ * @example
257
+ * ```typescript
258
+ * try {
259
+ * await client.pollForToken(deviceAuth.device_code);
260
+ * console.log('Device authorized!');
261
+ * } catch (error) {
262
+ * if (error.code === 'authorization_pending') {
263
+ * // User hasn't entered code yet, continue polling
264
+ * }
265
+ * }
266
+ * ```
267
+ */
268
+ async pollForToken(deviceCode) {
269
+ return this.deviceFlow.pollForToken(deviceCode);
270
+ }
271
+ // Client Credentials Flow methods
272
+ /**
273
+ * Requests tokens using client credentials flow
274
+ *
275
+ * @example
276
+ * ```typescript
277
+ * client.initializeClientCredentials('your_client_secret');
278
+ * await client.getClientCredentialsTokens();
279
+ *
280
+ * const accessToken = await client.getAccessToken();
281
+ * // Use token for server-to-server API calls
282
+ * ```
283
+ *
284
+ * @throws {AuthError} When client credentials flow is not initialized
285
+ */
286
+ async getClientCredentialsTokens() {
287
+ if (!this.clientCredentialsFlow) {
288
+ throw new AuthError("Client credentials flow not initialized. Call initializeClientCredentials() first.", ErrorCode.InvalidConfig);
289
+ }
290
+ return this.clientCredentialsFlow.getTokens();
291
+ }
292
+ // Token management
293
+ /**
294
+ * Gets a valid access token, automatically refreshing if needed
295
+ *
296
+ * @returns Promise resolving to access token or null if not authenticated
297
+ *
298
+ * @example
299
+ * ```typescript
300
+ * const accessToken = await client.getAccessToken();
301
+ * if (accessToken) {
302
+ * const response = await fetch('/api/protected', {
303
+ * headers: { 'Authorization': `Bearer ${accessToken}` }
304
+ * });
305
+ * }
306
+ * ```
307
+ */
308
+ async getAccessToken() {
309
+ const token = await this.storage.getAccessToken();
310
+ if (!token || this.storage.isTokenExpired(token)) {
311
+ const refreshToken = await this.storage.getRefreshToken();
312
+ if (refreshToken && !this.storage.isTokenExpired(refreshToken)) {
313
+ try {
314
+ await this.refreshFlow.refreshTokens();
315
+ const newToken = await this.storage.getAccessToken();
316
+ return newToken?.value || null;
317
+ }
318
+ catch {
319
+ return null;
320
+ }
321
+ }
322
+ return null;
323
+ }
324
+ return token.value;
325
+ }
326
+ /**
327
+ * Manually refreshes access tokens using refresh token
328
+ *
329
+ * @example
330
+ * ```typescript
331
+ * try {
332
+ * await client.refreshTokens();
333
+ * console.log('Tokens refreshed successfully');
334
+ * } catch (error) {
335
+ * console.log('Token refresh failed:', error.message);
336
+ * }
337
+ * ```
338
+ */
339
+ async refreshTokens() {
340
+ return this.refreshFlow.refreshTokens();
341
+ }
342
+ // User information
343
+ /**
344
+ * Fetches authenticated user information
345
+ *
346
+ * @returns Promise resolving to user info or null if not authenticated
347
+ *
348
+ * @example
349
+ * ```typescript
350
+ * const userInfo = await client.getUserInfo();
351
+ * if (userInfo) {
352
+ * console.log(`Welcome, ${userInfo.name}!`);
353
+ * console.log(`Email: ${userInfo.email}`);
354
+ * }
355
+ * ```
356
+ *
357
+ * @throws {AuthError} When userInfoEndpoint is missing from config
358
+ */
359
+ async getUserInfo() {
360
+ if (!this.config.userInfoEndpoint) {
361
+ throw new AuthError("Missing userInfoEndpoint in config", ErrorCode.InvalidConfig);
362
+ }
363
+ let token = await this.storage.getAccessToken();
364
+ if (!token || this.storage.isTokenExpired(token)) {
365
+ const refreshToken = await this.storage.getRefreshToken();
366
+ if (refreshToken && !this.storage.isTokenExpired(refreshToken)) {
367
+ try {
368
+ await this.refreshFlow.refreshTokens();
369
+ const newToken = await this.storage.getAccessToken();
370
+ if (!newToken || this.storage.isTokenExpired(newToken)) {
371
+ return null;
372
+ }
373
+ token = newToken;
374
+ }
375
+ catch (e) {
376
+ return null;
377
+ }
378
+ }
379
+ else {
380
+ return null;
381
+ }
382
+ }
383
+ if (!isJWT(token.value)) {
384
+ return null;
385
+ }
386
+ const response = await fetch(this.config.userInfoEndpoint, {
387
+ headers: {
388
+ Authorization: `Bearer ${token.value}`,
389
+ },
390
+ credentials: "include",
391
+ });
392
+ if (response.ok)
393
+ return response.json();
394
+ return null;
395
+ }
396
+ // Authentication status
397
+ /**
398
+ * Checks if the user is currently authenticated
399
+ *
400
+ * Automatically attempts token refresh if access token is expired
401
+ * but refresh token is still valid.
402
+ *
403
+ * @returns Promise resolving to true if authenticated, false otherwise
404
+ *
405
+ * @example
406
+ * ```typescript
407
+ * if (await client.isAuthenticated()) {
408
+ * // User is logged in, show authenticated content
409
+ * const userInfo = await client.getUserInfo();
410
+ * } else {
411
+ * // User needs to log in
412
+ * const loginUrl = await client.getLoginUrl();
413
+ * window.location.href = loginUrl;
414
+ * }
415
+ * ```
416
+ */
417
+ async isAuthenticated() {
418
+ const token = await this.storage.getAccessToken();
419
+ if (!token || this.storage.isTokenExpired(token) || !isJWT(token.value)) {
420
+ const refreshToken = await this.storage.getRefreshToken();
421
+ if (refreshToken && !this.storage.isTokenExpired(refreshToken)) {
422
+ if (!isJWT(refreshToken.value)) {
423
+ return false;
424
+ }
425
+ try {
426
+ await this.refreshFlow.refreshTokens();
427
+ return true;
428
+ }
429
+ catch {
430
+ return false;
431
+ }
432
+ }
433
+ return false;
434
+ }
435
+ return true;
436
+ }
437
+ // Logout
438
+ /**
439
+ * Logs out the user and revokes tokens
440
+ *
441
+ * Attempts to revoke tokens on the server if revoke endpoint is configured,
442
+ * then clears local token storage.
443
+ *
444
+ * @example
445
+ * ```typescript
446
+ * await client.logout();
447
+ * console.log('User logged out successfully');
448
+ *
449
+ * // Redirect to login page
450
+ * const loginUrl = await client.getLoginUrl();
451
+ * window.location.href = loginUrl;
452
+ * ```
453
+ */
454
+ async logout() {
455
+ if (!this.config.revokeEndpoint) {
456
+ this.storage.clearTokens();
457
+ return;
458
+ }
459
+ const accessToken = await this.storage.getAccessToken();
460
+ const refreshToken = await this.storage.getRefreshToken();
461
+ const accessTokenValue = accessToken?.value;
462
+ const refreshTokenValue = refreshToken?.value;
463
+ try {
464
+ if (accessTokenValue && isJWT(accessTokenValue)) {
465
+ const body = JSON.stringify({
466
+ client_id: this.config.clientId,
467
+ access_token: accessTokenValue,
468
+ refresh_token: refreshTokenValue,
469
+ });
470
+ const response = await fetch(this.config.revokeEndpoint, {
471
+ method: "POST",
472
+ headers: {
473
+ "Content-Type": "application/json",
474
+ Authorization: `Bearer ${accessTokenValue}`,
475
+ },
476
+ body,
477
+ });
478
+ if (!response.ok) {
479
+ console.debug("Token revocation returned non-OK response:", await response.text());
480
+ }
481
+ }
482
+ }
483
+ catch (e) {
484
+ console.debug("Failed to revoke tokens:", e);
485
+ }
486
+ finally {
487
+ this.storage.clearTokens();
488
+ }
489
+ }
490
+ }
491
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../../src/oauth/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export declare enum ErrorCode {
2
+ InvalidConfig = "invalid_config",
3
+ InvalidState = "invalid_state",
4
+ MissingVerifier = "missing_verifier",
5
+ TokenExchangeFailed = "token_exchange_failed",
6
+ TokenRefreshFailed = "token_refresh_failed",
7
+ MissingRefreshToken = "missing_refresh_token",
8
+ RateLimitExceeded = "rate_limit_exceeded",
9
+ InvalidToken = "invalid_token",
10
+ NetworkError = "network_error",
11
+ UnknownError = "unknown_error"
12
+ }
13
+ export declare class AuthError extends Error {
14
+ code: ErrorCode;
15
+ description?: string;
16
+ constructor(message: string, code: ErrorCode, description?: string);
17
+ }
18
+ //# sourceMappingURL=error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../../../src/oauth/error.ts"],"names":[],"mappings":"AAAA,oBAAY,SAAS;IACnB,aAAa,mBAAmB;IAChC,YAAY,kBAAkB;IAC9B,eAAe,qBAAqB;IACpC,mBAAmB,0BAA0B;IAC7C,kBAAkB,yBAAyB;IAC3C,mBAAmB,0BAA0B;IAC7C,iBAAiB,wBAAwB;IACzC,YAAY,kBAAkB;IAC9B,YAAY,kBAAkB;IAC9B,YAAY,kBAAkB;CAC/B;AAED,qBAAa,SAAU,SAAQ,KAAK;IAClC,IAAI,EAAE,SAAS,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;gBAET,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE,MAAM;CAMnE"}
@@ -0,0 +1,24 @@
1
+ export var ErrorCode;
2
+ (function (ErrorCode) {
3
+ ErrorCode["InvalidConfig"] = "invalid_config";
4
+ ErrorCode["InvalidState"] = "invalid_state";
5
+ ErrorCode["MissingVerifier"] = "missing_verifier";
6
+ ErrorCode["TokenExchangeFailed"] = "token_exchange_failed";
7
+ ErrorCode["TokenRefreshFailed"] = "token_refresh_failed";
8
+ ErrorCode["MissingRefreshToken"] = "missing_refresh_token";
9
+ ErrorCode["RateLimitExceeded"] = "rate_limit_exceeded";
10
+ ErrorCode["InvalidToken"] = "invalid_token";
11
+ ErrorCode["NetworkError"] = "network_error";
12
+ ErrorCode["UnknownError"] = "unknown_error";
13
+ })(ErrorCode || (ErrorCode = {}));
14
+ export class AuthError extends Error {
15
+ code;
16
+ description;
17
+ constructor(message, code, description) {
18
+ super(message);
19
+ this.name = "AuthError";
20
+ this.code = code;
21
+ this.description = description;
22
+ }
23
+ }
24
+ //# sourceMappingURL=error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.js","sourceRoot":"","sources":["../../../../src/oauth/error.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,SAWX;AAXD,WAAY,SAAS;IACnB,6CAAgC,CAAA;IAChC,2CAA8B,CAAA;IAC9B,iDAAoC,CAAA;IACpC,0DAA6C,CAAA;IAC7C,wDAA2C,CAAA;IAC3C,0DAA6C,CAAA;IAC7C,sDAAyC,CAAA;IACzC,2CAA8B,CAAA;IAC9B,2CAA8B,CAAA;IAC9B,2CAA8B,CAAA;AAChC,CAAC,EAXW,SAAS,KAAT,SAAS,QAWpB;AAED,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClC,IAAI,CAAY;IAChB,WAAW,CAAU;IAErB,YAAY,OAAe,EAAE,IAAe,EAAE,WAAoB;QAChE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;CACF"}
@@ -0,0 +1,122 @@
1
+ import type { AuthConfig } from "../types";
2
+ import { TokenStorage } from "../storage";
3
+ import { BaseFlow } from "./base-flow";
4
+ import type { OAuth2Api } from "@binoauth/tenant-sdk";
5
+ /**
6
+ * OAuth 2.0 Authorization Code Flow with PKCE support
7
+ *
8
+ * This flow is designed for browser-based applications (SPAs) and mobile apps
9
+ * where the client cannot securely store a client secret. It uses PKCE
10
+ * (Proof Key for Code Exchange) for enhanced security.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const flow = new AuthorizationCodeFlow(config, storage, oauthApi);
15
+ *
16
+ * // Step 1: Get authorization URL
17
+ * const loginUrl = await flow.getLoginUrl();
18
+ * window.location.href = loginUrl; // Redirect user to BinoAuth
19
+ *
20
+ * // Step 2: Handle callback (after user returns from BinoAuth)
21
+ * const urlParams = new URLSearchParams(window.location.search);
22
+ * const code = urlParams.get('code');
23
+ * const state = urlParams.get('state');
24
+ *
25
+ * if (code && state) {
26
+ * await flow.handleCallback(code, state);
27
+ * // User is now authenticated, tokens are stored
28
+ * }
29
+ * ```
30
+ */
31
+ export declare class AuthorizationCodeFlow extends BaseFlow {
32
+ private loginUrlGenerationInProgress;
33
+ constructor(config: AuthConfig, storage: TokenStorage, oauthApi?: OAuth2Api);
34
+ /**
35
+ * Generates the authorization URL for initiating the OAuth flow
36
+ *
37
+ * This method creates a secure authorization URL with PKCE parameters
38
+ * and stores the necessary state and verifier tokens for later validation.
39
+ *
40
+ * @returns Promise resolving to the authorization URL
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * const loginUrl = await flow.getLoginUrl();
45
+ * // Returns: "https://auth.binoauth.com/api/v1/oauth/authorize?response_type=code&client_id=..."
46
+ *
47
+ * // Redirect user to the authorization server
48
+ * window.location.href = loginUrl;
49
+ * ```
50
+ *
51
+ * @throws {AuthError} When authorization endpoint is missing from config
52
+ */
53
+ getLoginUrl(): Promise<string>;
54
+ /**
55
+ * Handles the OAuth callback and exchanges the authorization code for tokens
56
+ *
57
+ * This method validates the state parameter for CSRF protection, then exchanges
58
+ * the authorization code for access and refresh tokens using PKCE verification.
59
+ *
60
+ * @param code - The authorization code returned from the authorization server
61
+ * @param state - The state parameter returned from the authorization server
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * // Extract parameters from callback URL
66
+ * const urlParams = new URLSearchParams(window.location.search);
67
+ * const code = urlParams.get('code')!;
68
+ * const state = urlParams.get('state')!;
69
+ *
70
+ * // Exchange code for tokens
71
+ * await flow.handleCallback(code, state);
72
+ *
73
+ * // Tokens are now stored and user is authenticated
74
+ * const accessToken = await storage.getAccessToken();
75
+ * ```
76
+ *
77
+ * @throws {AuthError} When state validation fails (CSRF protection)
78
+ * @throws {AuthError} When state or verifier tokens are missing/expired
79
+ * @throws {AuthError} When token exchange fails
80
+ */
81
+ handleCallback(code: string, state: string): Promise<void>;
82
+ /**
83
+ * Generates the logout URL for ending the OAuth session
84
+ *
85
+ * @returns Promise resolving to the logout URL
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * const logoutUrl = await flow.getLogoutUrl();
90
+ * // Returns: "https://auth.binoauth.com/api/v1/oauth/logout?client_id=..."
91
+ *
92
+ * window.location.href = logoutUrl; // Redirect to logout
93
+ * ```
94
+ *
95
+ * @throws {AuthError} When logout endpoint is missing from config
96
+ */
97
+ getLogoutUrl(): Promise<string>;
98
+ /**
99
+ * Generates the logout page URL with optional return URL
100
+ *
101
+ * This URL points to the BinoAuth logout page where the user can
102
+ * terminate their session and optionally be redirected back.
103
+ *
104
+ * @param returnTo - Optional URL to redirect to after logout
105
+ * @returns Promise resolving to the logout page URL
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * // Simple logout
110
+ * const logoutPageUrl = await flow.getLogoutPageUrl();
111
+ * // Returns: "https://auth.binoauth.com/auth/logout?client_id=..."
112
+ *
113
+ * // Logout with return URL
114
+ * const logoutPageUrl = await flow.getLogoutPageUrl('https://myapp.com/goodbye');
115
+ * // Returns: "https://auth.binoauth.com/auth/logout?client_id=...&return_to=..."
116
+ *
117
+ * window.location.href = logoutPageUrl;
118
+ * ```
119
+ */
120
+ getLogoutPageUrl(returnTo?: string): Promise<string>;
121
+ }
122
+ //# sourceMappingURL=authorization-code.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorization-code.d.ts","sourceRoot":"","sources":["../../../../../src/oauth/flows/authorization-code.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAY,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,qBAAsB,SAAQ,QAAQ;IACjD,OAAO,CAAC,4BAA4B,CAAS;gBAEjC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,SAAS;IAkB3E;;;;;;;;;;;;;;;;;;OAkBG;IACG,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;IA6DpC;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACG,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgHhE;;;;;;;;;;;;;;OAcG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAgBrC;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,gBAAgB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAQ3D"}