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.
- package/README.md +359 -165
- package/dist/core/src/admin/client.d.ts +203 -0
- package/dist/core/src/admin/client.d.ts.map +1 -0
- package/dist/core/src/admin/client.js +391 -0
- package/dist/core/src/admin/client.js.map +1 -0
- package/dist/core/src/admin/index.d.ts +6 -0
- package/dist/core/src/admin/index.d.ts.map +1 -0
- package/dist/core/src/admin/index.js +5 -0
- package/dist/core/src/admin/index.js.map +1 -0
- package/dist/core/src/admin/types.d.ts +412 -0
- package/dist/core/src/admin/types.d.ts.map +1 -0
- package/dist/core/src/admin/types.js +5 -0
- package/dist/core/src/admin/types.js.map +1 -0
- package/dist/core/src/auth/client.d.ts +330 -0
- package/dist/core/src/auth/client.d.ts.map +1 -0
- package/dist/core/src/auth/client.js +408 -0
- package/dist/core/src/auth/client.js.map +1 -0
- package/dist/core/src/auth/error.d.ts +113 -0
- package/dist/core/src/auth/error.d.ts.map +1 -0
- package/dist/core/src/auth/error.js +257 -0
- package/dist/core/src/auth/error.js.map +1 -0
- package/dist/core/src/auth/flows/base-flow.d.ts +98 -0
- package/dist/core/src/auth/flows/base-flow.d.ts.map +1 -0
- package/dist/core/src/auth/flows/base-flow.js +182 -0
- package/dist/core/src/auth/flows/base-flow.js.map +1 -0
- package/dist/core/src/auth/flows/magic-link.d.ts +175 -0
- package/dist/core/src/auth/flows/magic-link.d.ts.map +1 -0
- package/dist/core/src/auth/flows/magic-link.js +228 -0
- package/dist/core/src/auth/flows/magic-link.js.map +1 -0
- package/dist/core/src/auth/flows/mfa.d.ts +81 -0
- package/dist/core/src/auth/flows/mfa.d.ts.map +1 -0
- package/dist/core/src/auth/flows/mfa.js +103 -0
- package/dist/core/src/auth/flows/mfa.js.map +1 -0
- package/dist/core/src/auth/flows/otp.d.ts +172 -0
- package/dist/core/src/auth/flows/otp.d.ts.map +1 -0
- package/dist/core/src/auth/flows/otp.js +222 -0
- package/dist/core/src/auth/flows/otp.js.map +1 -0
- package/dist/core/src/auth/flows/password.d.ts +242 -0
- package/dist/core/src/auth/flows/password.d.ts.map +1 -0
- package/dist/core/src/auth/flows/password.js +344 -0
- package/dist/core/src/auth/flows/password.js.map +1 -0
- package/dist/core/src/auth/flows/social.d.ts +209 -0
- package/dist/core/src/auth/flows/social.d.ts.map +1 -0
- package/dist/core/src/auth/flows/social.js +284 -0
- package/dist/core/src/auth/flows/social.js.map +1 -0
- package/dist/core/src/auth/index.d.ts +19 -0
- package/dist/core/src/auth/index.d.ts.map +1 -0
- package/dist/core/src/auth/index.js +32 -0
- package/dist/core/src/auth/index.js.map +1 -0
- package/dist/core/src/auth/types.d.ts +151 -0
- package/dist/core/src/auth/types.d.ts.map +1 -0
- package/dist/core/src/auth/types.js +7 -0
- package/dist/core/src/auth/types.js.map +1 -0
- package/dist/core/src/index.d.ts +53 -49
- package/dist/core/src/index.d.ts.map +1 -1
- package/dist/core/src/index.js +61 -343
- package/dist/core/src/index.js.map +1 -1
- package/dist/core/src/oauth/client.d.ts +322 -0
- package/dist/core/src/oauth/client.d.ts.map +1 -0
- package/dist/core/src/oauth/client.js +491 -0
- package/dist/core/src/oauth/client.js.map +1 -0
- package/dist/core/src/oauth/error.d.ts +18 -0
- package/dist/core/src/oauth/error.d.ts.map +1 -0
- package/dist/core/src/oauth/error.js +24 -0
- package/dist/core/src/oauth/error.js.map +1 -0
- package/dist/core/src/oauth/flows/authorization-code.d.ts +122 -0
- package/dist/core/src/oauth/flows/authorization-code.d.ts.map +1 -0
- package/dist/core/src/oauth/flows/authorization-code.js +278 -0
- package/dist/core/src/oauth/flows/authorization-code.js.map +1 -0
- package/dist/core/src/oauth/flows/base-flow.d.ts +17 -0
- package/dist/core/src/oauth/flows/base-flow.d.ts.map +1 -0
- package/dist/core/src/oauth/flows/base-flow.js +107 -0
- package/dist/core/src/oauth/flows/base-flow.js.map +1 -0
- package/dist/core/src/oauth/flows/client-credentials.d.ts +72 -0
- package/dist/core/src/oauth/flows/client-credentials.d.ts.map +1 -0
- package/dist/core/src/oauth/flows/client-credentials.js +100 -0
- package/dist/core/src/oauth/flows/client-credentials.js.map +1 -0
- package/dist/core/src/oauth/flows/device-code.d.ts +108 -0
- package/dist/core/src/oauth/flows/device-code.d.ts.map +1 -0
- package/dist/core/src/oauth/flows/device-code.js +193 -0
- package/dist/core/src/oauth/flows/device-code.js.map +1 -0
- package/dist/core/src/oauth/flows/refresh-token.d.ts +59 -0
- package/dist/core/src/oauth/flows/refresh-token.d.ts.map +1 -0
- package/dist/core/src/oauth/flows/refresh-token.js +105 -0
- package/dist/core/src/oauth/flows/refresh-token.js.map +1 -0
- package/dist/core/src/oauth/index.d.ts +12 -0
- package/dist/core/src/oauth/index.d.ts.map +1 -0
- package/dist/core/src/oauth/index.js +11 -0
- package/dist/core/src/oauth/index.js.map +1 -0
- package/dist/core/src/oauth/storage/encryption.d.ts +12 -0
- package/dist/core/src/oauth/storage/encryption.d.ts.map +1 -0
- package/dist/core/src/oauth/storage/encryption.js +76 -0
- package/dist/core/src/oauth/storage/encryption.js.map +1 -0
- package/dist/core/src/oauth/storage/index.d.ts +201 -0
- package/dist/core/src/oauth/storage/index.d.ts.map +1 -0
- package/dist/core/src/oauth/storage/index.js +322 -0
- package/dist/core/src/oauth/storage/index.js.map +1 -0
- package/dist/core/src/oauth/storage/strategies.d.ts +34 -0
- package/dist/core/src/oauth/storage/strategies.d.ts.map +1 -0
- package/dist/core/src/oauth/storage/strategies.js +100 -0
- package/dist/core/src/oauth/storage/strategies.js.map +1 -0
- package/dist/core/src/oauth/types.d.ts +261 -0
- package/dist/core/src/oauth/types.d.ts.map +1 -0
- package/dist/core/src/oauth/types.js +39 -0
- package/dist/core/src/oauth/types.js.map +1 -0
- package/dist/core/src/oauth/utils.d.ts +56 -0
- package/dist/core/src/oauth/utils.d.ts.map +1 -0
- package/dist/core/src/oauth/utils.js +140 -0
- package/dist/core/src/oauth/utils.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
@@ -0,0 +1,175 @@
|
|
1
|
+
/**
|
2
|
+
* Magic link authentication flow
|
3
|
+
*
|
4
|
+
* Handles passwordless authentication via email magic links using actual tenant-sdk APIs.
|
5
|
+
*/
|
6
|
+
import type { MagicLinkRequest, AuthResult, BinoAuthConfig } from "../types";
|
7
|
+
import { BaseAuthFlow } from "./base-flow";
|
8
|
+
/**
|
9
|
+
* Magic link authentication flow
|
10
|
+
*
|
11
|
+
* Provides passwordless authentication by sending magic links to users' email addresses
|
12
|
+
* using the actual tenant-sdk AuthenticationApi methods.
|
13
|
+
*
|
14
|
+
* @example
|
15
|
+
* ```typescript
|
16
|
+
* const magicLinkFlow = new MagicLinkFlow(config);
|
17
|
+
*
|
18
|
+
* // Send magic link to user's email
|
19
|
+
* await magicLinkFlow.sendMagicLink({
|
20
|
+
* email: 'user@example.com',
|
21
|
+
* returnTo: 'https://myapp.com/dashboard'
|
22
|
+
* });
|
23
|
+
*
|
24
|
+
* // User clicks link in email, which redirects to your app with a token
|
25
|
+
* // Extract token from URL and verify it
|
26
|
+
* const urlParams = new URLSearchParams(window.location.search);
|
27
|
+
* const token = urlParams.get('token');
|
28
|
+
*
|
29
|
+
* if (token) {
|
30
|
+
* const result = await magicLinkFlow.verifyMagicLink(token);
|
31
|
+
* if (result.success) {
|
32
|
+
* console.log('Authentication successful:', result.user);
|
33
|
+
* }
|
34
|
+
* }
|
35
|
+
* ```
|
36
|
+
*/
|
37
|
+
export declare class MagicLinkFlow extends BaseAuthFlow {
|
38
|
+
constructor(config: BinoAuthConfig);
|
39
|
+
/**
|
40
|
+
* Sends a magic link to the user's email address using tenant-sdk AuthenticationApi.requestMagicLinkApiV1AuthMlPost
|
41
|
+
*
|
42
|
+
* @param request - Magic link request with email and optional return URL
|
43
|
+
* @returns Promise resolving when magic link is sent
|
44
|
+
*
|
45
|
+
* @example
|
46
|
+
* ```typescript
|
47
|
+
* // Basic magic link
|
48
|
+
* await magicLinkFlow.sendMagicLink({
|
49
|
+
* email: 'user@example.com',
|
50
|
+
* returnTo: 'https://myapp.com/dashboard'
|
51
|
+
* });
|
52
|
+
*
|
53
|
+
* console.log('Magic link sent! Check your email.');
|
54
|
+
* ```
|
55
|
+
*
|
56
|
+
* @throws {AuthError} When sending magic link fails
|
57
|
+
*/
|
58
|
+
sendMagicLink(request: MagicLinkRequest): Promise<void>;
|
59
|
+
/**
|
60
|
+
* Sends a magic link to an email address (convenience method)
|
61
|
+
*
|
62
|
+
* @param email - User's email address
|
63
|
+
* @param returnTo - Optional URL to redirect to after authentication
|
64
|
+
* @returns Promise resolving when magic link is sent
|
65
|
+
*
|
66
|
+
* @example
|
67
|
+
* ```typescript
|
68
|
+
* await magicLinkFlow.sendMagicLinkToEmail(
|
69
|
+
* 'user@example.com',
|
70
|
+
* 'https://myapp.com/dashboard'
|
71
|
+
* );
|
72
|
+
* ```
|
73
|
+
*/
|
74
|
+
sendMagicLinkToEmail(email: string, returnTo: string): Promise<void>;
|
75
|
+
/**
|
76
|
+
* Verifies a magic link token and authenticates the user using tenant-sdk AuthenticationApi.verifyMagicLinkApiV1AuthMlVerifyPost
|
77
|
+
*
|
78
|
+
* @param token - Magic link token (usually from URL parameter)
|
79
|
+
* @returns Promise resolving to authentication result
|
80
|
+
*
|
81
|
+
* @example
|
82
|
+
* ```typescript
|
83
|
+
* // Extract token from URL
|
84
|
+
* const urlParams = new URLSearchParams(window.location.search);
|
85
|
+
* const token = urlParams.get('token');
|
86
|
+
*
|
87
|
+
* if (token) {
|
88
|
+
* try {
|
89
|
+
* const result = await magicLinkFlow.verifyMagicLink(token);
|
90
|
+
* if (result.success) {
|
91
|
+
* console.log('Welcome,', result.user.name);
|
92
|
+
* localStorage.setItem('accessToken', result.accessToken);
|
93
|
+
*
|
94
|
+
* // Redirect to dashboard or intended page
|
95
|
+
* window.location.href = '/dashboard';
|
96
|
+
* }
|
97
|
+
* } catch (error) {
|
98
|
+
* if (error.code === AuthErrorCode.EXPIRED_TOKEN) {
|
99
|
+
* console.log('Magic link has expired. Please request a new one.');
|
100
|
+
* } else if (error.code === AuthErrorCode.INVALID_TOKEN) {
|
101
|
+
* console.log('Invalid magic link. Please try again.');
|
102
|
+
* }
|
103
|
+
* }
|
104
|
+
* }
|
105
|
+
* ```
|
106
|
+
*
|
107
|
+
* @throws {AuthError} When token verification fails
|
108
|
+
*/
|
109
|
+
verifyMagicLink(token: string): Promise<AuthResult>;
|
110
|
+
/**
|
111
|
+
* Checks if a magic link token is valid without completing authentication
|
112
|
+
*
|
113
|
+
* @param token - Magic link token to validate
|
114
|
+
* @returns Promise resolving to true if token is valid, false otherwise
|
115
|
+
*
|
116
|
+
* @example
|
117
|
+
* ```typescript
|
118
|
+
* const token = urlParams.get('token');
|
119
|
+
*
|
120
|
+
* if (await magicLinkFlow.validateMagicLinkToken(token)) {
|
121
|
+
* console.log('Token is valid, proceeding with authentication...');
|
122
|
+
* const result = await magicLinkFlow.verifyMagicLink(token);
|
123
|
+
* } else {
|
124
|
+
* console.log('Invalid or expired token');
|
125
|
+
* }
|
126
|
+
* ```
|
127
|
+
*/
|
128
|
+
validateMagicLinkToken(token: string): Promise<boolean>;
|
129
|
+
/**
|
130
|
+
* Resends a magic link to the same email address
|
131
|
+
*
|
132
|
+
* @param email - Email address to resend magic link to
|
133
|
+
* @param returnTo - Optional return URL
|
134
|
+
* @returns Promise resolving when magic link is resent
|
135
|
+
*
|
136
|
+
* @example
|
137
|
+
* ```typescript
|
138
|
+
* // User clicks "Resend magic link" button
|
139
|
+
* await magicLinkFlow.resendMagicLink('user@example.com', 'https://myapp.com/dashboard');
|
140
|
+
* console.log('Magic link resent! Check your email again.');
|
141
|
+
* ```
|
142
|
+
*
|
143
|
+
* @throws {AuthError} When resending fails
|
144
|
+
*/
|
145
|
+
resendMagicLink(email: string, returnTo: string): Promise<void>;
|
146
|
+
/**
|
147
|
+
* Sends a magic link for a specific purpose (password reset, email verification, etc.)
|
148
|
+
*
|
149
|
+
* This method uses the same tenant-sdk endpoint but is semantically different
|
150
|
+
* for different use cases.
|
151
|
+
*
|
152
|
+
* @param email - User's email address
|
153
|
+
* @param returnTo - URL to redirect to after authentication
|
154
|
+
* @returns Promise resolving when magic link is sent
|
155
|
+
*
|
156
|
+
* @example
|
157
|
+
* ```typescript
|
158
|
+
* // For password reset
|
159
|
+
* await magicLinkFlow.sendMagicLinkForPurpose(
|
160
|
+
* 'user@example.com',
|
161
|
+
* 'https://myapp.com/password-reset-complete'
|
162
|
+
* );
|
163
|
+
*
|
164
|
+
* // For email verification
|
165
|
+
* await magicLinkFlow.sendMagicLinkForPurpose(
|
166
|
+
* 'user@example.com',
|
167
|
+
* 'https://myapp.com/email-verified'
|
168
|
+
* );
|
169
|
+
* ```
|
170
|
+
*
|
171
|
+
* @throws {AuthError} When link sending fails
|
172
|
+
*/
|
173
|
+
sendMagicLinkForPurpose(email: string, returnTo: string): Promise<void>;
|
174
|
+
}
|
175
|
+
//# sourceMappingURL=magic-link.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"magic-link.d.ts","sourceRoot":"","sources":["../../../../../src/auth/flows/magic-link.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE7E,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,aAAc,SAAQ,YAAY;gBAEjC,MAAM,EAAE,cAAc;IAIlC;;;;;;;;;;;;;;;;;;OAkBG;IACG,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAc7D;;;;;;;;;;;;;;OAcG;IACG,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACG,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAoBzD;;;;;;;;;;;;;;;;;OAiBG;IACG,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAc7D;;;;;;;;;;;;;;;OAeG;IACG,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrE;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACG,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAa9E"}
|
@@ -0,0 +1,228 @@
|
|
1
|
+
/**
|
2
|
+
* Magic link authentication flow
|
3
|
+
*
|
4
|
+
* Handles passwordless authentication via email magic links using actual tenant-sdk APIs.
|
5
|
+
*/
|
6
|
+
import { AuthError, AuthErrorCode } from "../error";
|
7
|
+
import { BaseAuthFlow } from "./base-flow";
|
8
|
+
/**
|
9
|
+
* Magic link authentication flow
|
10
|
+
*
|
11
|
+
* Provides passwordless authentication by sending magic links to users' email addresses
|
12
|
+
* using the actual tenant-sdk AuthenticationApi methods.
|
13
|
+
*
|
14
|
+
* @example
|
15
|
+
* ```typescript
|
16
|
+
* const magicLinkFlow = new MagicLinkFlow(config);
|
17
|
+
*
|
18
|
+
* // Send magic link to user's email
|
19
|
+
* await magicLinkFlow.sendMagicLink({
|
20
|
+
* email: 'user@example.com',
|
21
|
+
* returnTo: 'https://myapp.com/dashboard'
|
22
|
+
* });
|
23
|
+
*
|
24
|
+
* // User clicks link in email, which redirects to your app with a token
|
25
|
+
* // Extract token from URL and verify it
|
26
|
+
* const urlParams = new URLSearchParams(window.location.search);
|
27
|
+
* const token = urlParams.get('token');
|
28
|
+
*
|
29
|
+
* if (token) {
|
30
|
+
* const result = await magicLinkFlow.verifyMagicLink(token);
|
31
|
+
* if (result.success) {
|
32
|
+
* console.log('Authentication successful:', result.user);
|
33
|
+
* }
|
34
|
+
* }
|
35
|
+
* ```
|
36
|
+
*/
|
37
|
+
export class MagicLinkFlow extends BaseAuthFlow {
|
38
|
+
constructor(config) {
|
39
|
+
super(config);
|
40
|
+
}
|
41
|
+
/**
|
42
|
+
* Sends a magic link to the user's email address using tenant-sdk AuthenticationApi.requestMagicLinkApiV1AuthMlPost
|
43
|
+
*
|
44
|
+
* @param request - Magic link request with email and optional return URL
|
45
|
+
* @returns Promise resolving when magic link is sent
|
46
|
+
*
|
47
|
+
* @example
|
48
|
+
* ```typescript
|
49
|
+
* // Basic magic link
|
50
|
+
* await magicLinkFlow.sendMagicLink({
|
51
|
+
* email: 'user@example.com',
|
52
|
+
* returnTo: 'https://myapp.com/dashboard'
|
53
|
+
* });
|
54
|
+
*
|
55
|
+
* console.log('Magic link sent! Check your email.');
|
56
|
+
* ```
|
57
|
+
*
|
58
|
+
* @throws {AuthError} When sending magic link fails
|
59
|
+
*/
|
60
|
+
async sendMagicLink(request) {
|
61
|
+
this.validateEmail(request.email);
|
62
|
+
await this.safeApiCall(async () => {
|
63
|
+
// Use the actual tenant-sdk AuthenticationApi.requestMagicLinkApiV1AuthMlPost method
|
64
|
+
await this.authApi.requestMagicLinkApiV1AuthMlPost({
|
65
|
+
magicLinkRequest: {
|
66
|
+
email: request.email,
|
67
|
+
returnTo: request.returnTo,
|
68
|
+
},
|
69
|
+
});
|
70
|
+
}, AuthErrorCode.ACCOUNT_NOT_FOUND);
|
71
|
+
}
|
72
|
+
/**
|
73
|
+
* Sends a magic link to an email address (convenience method)
|
74
|
+
*
|
75
|
+
* @param email - User's email address
|
76
|
+
* @param returnTo - Optional URL to redirect to after authentication
|
77
|
+
* @returns Promise resolving when magic link is sent
|
78
|
+
*
|
79
|
+
* @example
|
80
|
+
* ```typescript
|
81
|
+
* await magicLinkFlow.sendMagicLinkToEmail(
|
82
|
+
* 'user@example.com',
|
83
|
+
* 'https://myapp.com/dashboard'
|
84
|
+
* );
|
85
|
+
* ```
|
86
|
+
*/
|
87
|
+
async sendMagicLinkToEmail(email, returnTo) {
|
88
|
+
return this.sendMagicLink({ email, returnTo });
|
89
|
+
}
|
90
|
+
/**
|
91
|
+
* Verifies a magic link token and authenticates the user using tenant-sdk AuthenticationApi.verifyMagicLinkApiV1AuthMlVerifyPost
|
92
|
+
*
|
93
|
+
* @param token - Magic link token (usually from URL parameter)
|
94
|
+
* @returns Promise resolving to authentication result
|
95
|
+
*
|
96
|
+
* @example
|
97
|
+
* ```typescript
|
98
|
+
* // Extract token from URL
|
99
|
+
* const urlParams = new URLSearchParams(window.location.search);
|
100
|
+
* const token = urlParams.get('token');
|
101
|
+
*
|
102
|
+
* if (token) {
|
103
|
+
* try {
|
104
|
+
* const result = await magicLinkFlow.verifyMagicLink(token);
|
105
|
+
* if (result.success) {
|
106
|
+
* console.log('Welcome,', result.user.name);
|
107
|
+
* localStorage.setItem('accessToken', result.accessToken);
|
108
|
+
*
|
109
|
+
* // Redirect to dashboard or intended page
|
110
|
+
* window.location.href = '/dashboard';
|
111
|
+
* }
|
112
|
+
* } catch (error) {
|
113
|
+
* if (error.code === AuthErrorCode.EXPIRED_TOKEN) {
|
114
|
+
* console.log('Magic link has expired. Please request a new one.');
|
115
|
+
* } else if (error.code === AuthErrorCode.INVALID_TOKEN) {
|
116
|
+
* console.log('Invalid magic link. Please try again.');
|
117
|
+
* }
|
118
|
+
* }
|
119
|
+
* }
|
120
|
+
* ```
|
121
|
+
*
|
122
|
+
* @throws {AuthError} When token verification fails
|
123
|
+
*/
|
124
|
+
async verifyMagicLink(token) {
|
125
|
+
if (!token) {
|
126
|
+
throw new AuthError(AuthErrorCode.MISSING_REQUIRED_FIELD, 'Magic link token is required');
|
127
|
+
}
|
128
|
+
return this.safeApiCall(async () => {
|
129
|
+
// Use the actual tenant-sdk AuthenticationApi.verifyMagicLinkApiV1AuthMlVerifyPost method
|
130
|
+
const response = await this.authApi.verifyMagicLinkApiV1AuthMlVerifyPost({
|
131
|
+
verifyMagicLinkTokenRequest: {
|
132
|
+
token,
|
133
|
+
},
|
134
|
+
});
|
135
|
+
return this.processAuthResponse(response);
|
136
|
+
}, AuthErrorCode.INVALID_TOKEN);
|
137
|
+
}
|
138
|
+
/**
|
139
|
+
* Checks if a magic link token is valid without completing authentication
|
140
|
+
*
|
141
|
+
* @param token - Magic link token to validate
|
142
|
+
* @returns Promise resolving to true if token is valid, false otherwise
|
143
|
+
*
|
144
|
+
* @example
|
145
|
+
* ```typescript
|
146
|
+
* const token = urlParams.get('token');
|
147
|
+
*
|
148
|
+
* if (await magicLinkFlow.validateMagicLinkToken(token)) {
|
149
|
+
* console.log('Token is valid, proceeding with authentication...');
|
150
|
+
* const result = await magicLinkFlow.verifyMagicLink(token);
|
151
|
+
* } else {
|
152
|
+
* console.log('Invalid or expired token');
|
153
|
+
* }
|
154
|
+
* ```
|
155
|
+
*/
|
156
|
+
async validateMagicLinkToken(token) {
|
157
|
+
if (!token) {
|
158
|
+
return false;
|
159
|
+
}
|
160
|
+
try {
|
161
|
+
// Try to verify the magic link to check if it's valid
|
162
|
+
await this.verifyMagicLink(token);
|
163
|
+
return true;
|
164
|
+
}
|
165
|
+
catch (error) {
|
166
|
+
return false;
|
167
|
+
}
|
168
|
+
}
|
169
|
+
/**
|
170
|
+
* Resends a magic link to the same email address
|
171
|
+
*
|
172
|
+
* @param email - Email address to resend magic link to
|
173
|
+
* @param returnTo - Optional return URL
|
174
|
+
* @returns Promise resolving when magic link is resent
|
175
|
+
*
|
176
|
+
* @example
|
177
|
+
* ```typescript
|
178
|
+
* // User clicks "Resend magic link" button
|
179
|
+
* await magicLinkFlow.resendMagicLink('user@example.com', 'https://myapp.com/dashboard');
|
180
|
+
* console.log('Magic link resent! Check your email again.');
|
181
|
+
* ```
|
182
|
+
*
|
183
|
+
* @throws {AuthError} When resending fails
|
184
|
+
*/
|
185
|
+
async resendMagicLink(email, returnTo) {
|
186
|
+
return this.sendMagicLink({ email, returnTo });
|
187
|
+
}
|
188
|
+
/**
|
189
|
+
* Sends a magic link for a specific purpose (password reset, email verification, etc.)
|
190
|
+
*
|
191
|
+
* This method uses the same tenant-sdk endpoint but is semantically different
|
192
|
+
* for different use cases.
|
193
|
+
*
|
194
|
+
* @param email - User's email address
|
195
|
+
* @param returnTo - URL to redirect to after authentication
|
196
|
+
* @returns Promise resolving when magic link is sent
|
197
|
+
*
|
198
|
+
* @example
|
199
|
+
* ```typescript
|
200
|
+
* // For password reset
|
201
|
+
* await magicLinkFlow.sendMagicLinkForPurpose(
|
202
|
+
* 'user@example.com',
|
203
|
+
* 'https://myapp.com/password-reset-complete'
|
204
|
+
* );
|
205
|
+
*
|
206
|
+
* // For email verification
|
207
|
+
* await magicLinkFlow.sendMagicLinkForPurpose(
|
208
|
+
* 'user@example.com',
|
209
|
+
* 'https://myapp.com/email-verified'
|
210
|
+
* );
|
211
|
+
* ```
|
212
|
+
*
|
213
|
+
* @throws {AuthError} When link sending fails
|
214
|
+
*/
|
215
|
+
async sendMagicLinkForPurpose(email, returnTo) {
|
216
|
+
this.validateEmail(email);
|
217
|
+
return this.safeApiCall(async () => {
|
218
|
+
// Use the same tenant-sdk API method - the backend determines the purpose
|
219
|
+
await this.authApi.requestMagicLinkApiV1AuthMlPost({
|
220
|
+
magicLinkRequest: {
|
221
|
+
email,
|
222
|
+
returnTo,
|
223
|
+
},
|
224
|
+
});
|
225
|
+
}, AuthErrorCode.SERVER_ERROR);
|
226
|
+
}
|
227
|
+
}
|
228
|
+
//# sourceMappingURL=magic-link.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"magic-link.js","sourceRoot":"","sources":["../../../../../src/auth/flows/magic-link.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,OAAO,aAAc,SAAQ,YAAY;IAE7C,YAAY,MAAsB;QAChC,KAAK,CAAC,MAAM,CAAC,CAAC;IAChB,CAAC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,KAAK,CAAC,aAAa,CAAC,OAAyB;QAC3C,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAElC,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,IAAI,EAAE;YAChC,qFAAqF;YACrF,MAAM,IAAI,CAAC,OAAO,CAAC,+BAA+B,CAAC;gBACjD,gBAAgB,EAAE;oBAChB,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,QAAQ,EAAE,OAAO,CAAC,QAAQ;iBAC3B;aACF,CAAC,CAAC;QACL,CAAC,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAC;IACtC,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,oBAAoB,CAAC,KAAa,EAAE,QAAgB;QACxD,OAAO,IAAI,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACjD,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACH,KAAK,CAAC,eAAe,CAAC,KAAa;QACjC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,SAAS,CACjB,aAAa,CAAC,sBAAsB,EACpC,8BAA8B,CAC/B,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,IAAI,EAAE;YACjC,0FAA0F;YAC1F,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,oCAAoC,CAAC;gBACvE,2BAA2B,EAAE;oBAC3B,KAAK;iBACN;aACF,CAAC,CAAC;YAEH,OAAO,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QAC5C,CAAC,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IAClC,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,CAAC,sBAAsB,CAAC,KAAa;QACxC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,CAAC;YACH,sDAAsD;YACtD,MAAM,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;YAClC,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,eAAe,CAAC,KAAa,EAAE,QAAgB;QACnD,OAAO,IAAI,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACjD,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,KAAK,CAAC,uBAAuB,CAAC,KAAa,EAAE,QAAgB;QAC3D,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAE1B,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,IAAI,EAAE;YACjC,0EAA0E;YAC1E,MAAM,IAAI,CAAC,OAAO,CAAC,+BAA+B,CAAC;gBACjD,gBAAgB,EAAE;oBAChB,KAAK;oBACL,QAAQ;iBACT;aACF,CAAC,CAAC;QACL,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACjC,CAAC;CACF"}
|
@@ -0,0 +1,81 @@
|
|
1
|
+
/**
|
2
|
+
* Multi-Factor Authentication (MFA) flow
|
3
|
+
*
|
4
|
+
* Handles MFA verification using the actual tenant-sdk AuthenticationApi.verifyMfaApiV1AuthMfaVerifyPost method.
|
5
|
+
* Provides TOTP setup and management functionality.
|
6
|
+
*/
|
7
|
+
import type { AuthResult, BinoAuthConfig } from "../types";
|
8
|
+
import { BaseAuthFlow } from "./base-flow";
|
9
|
+
/**
|
10
|
+
* Multi-Factor Authentication flow
|
11
|
+
*
|
12
|
+
* Provides MFA verification using actual tenant-sdk APIs.
|
13
|
+
* Uses AuthenticationApi.verifyMfaApiV1AuthMfaVerifyPost for MFA verification.
|
14
|
+
*
|
15
|
+
* @example
|
16
|
+
* ```typescript
|
17
|
+
* const mfaFlow = new MFAFlow(config);
|
18
|
+
*
|
19
|
+
* // After initial login, if MFA is required
|
20
|
+
* try {
|
21
|
+
* const loginResult = await passwordFlow.login(email, password);
|
22
|
+
* } catch (error) {
|
23
|
+
* if (error.code === AuthErrorCode.MFA_REQUIRED) {
|
24
|
+
* const sessionId = error.details.sessionId;
|
25
|
+
*
|
26
|
+
* // User enters TOTP code from authenticator app
|
27
|
+
* const mfaResult = await mfaFlow.verifyMFA('123456', sessionId);
|
28
|
+
*
|
29
|
+
* if (mfaResult.success) {
|
30
|
+
* console.log('MFA successful:', mfaResult.user);
|
31
|
+
* }
|
32
|
+
* }
|
33
|
+
* }
|
34
|
+
* ```
|
35
|
+
*/
|
36
|
+
export declare class MFAFlow extends BaseAuthFlow {
|
37
|
+
constructor(config: BinoAuthConfig);
|
38
|
+
/**
|
39
|
+
* Verifies MFA using tenant-sdk AuthenticationApi.verifyMfaApiV1AuthMfaVerifyPost
|
40
|
+
*
|
41
|
+
* @param code - MFA verification code (typically from TOTP app)
|
42
|
+
* @param sessionId - Session identifier from initial login attempt
|
43
|
+
* @returns Promise resolving to authentication result
|
44
|
+
*
|
45
|
+
* @example
|
46
|
+
* ```typescript
|
47
|
+
* try {
|
48
|
+
* const result = await mfaFlow.verifyMFA('123456', 'session_id_from_login');
|
49
|
+
* if (result.success) {
|
50
|
+
* console.log('MFA verification successful!');
|
51
|
+
* localStorage.setItem('accessToken', result.accessToken);
|
52
|
+
* }
|
53
|
+
* } catch (error) {
|
54
|
+
* if (error.code === AuthErrorCode.INVALID_OTP) {
|
55
|
+
* console.log('Invalid MFA code');
|
56
|
+
* } else if (error.code === AuthErrorCode.MFA_CHALLENGE_EXPIRED) {
|
57
|
+
* console.log('Session expired, please log in again');
|
58
|
+
* }
|
59
|
+
* }
|
60
|
+
* ```
|
61
|
+
*
|
62
|
+
* @throws {AuthError} When MFA verification fails
|
63
|
+
*/
|
64
|
+
verifyMFA(code: string, sessionId: string): Promise<AuthResult>;
|
65
|
+
/**
|
66
|
+
* Convenience method for verifying TOTP (Time-based One-Time Password)
|
67
|
+
*
|
68
|
+
* @param totpCode - 6-digit TOTP code from authenticator app
|
69
|
+
* @param sessionId - Session identifier from initial login attempt
|
70
|
+
* @returns Promise resolving to authentication result
|
71
|
+
*
|
72
|
+
* @example
|
73
|
+
* ```typescript
|
74
|
+
* // User enters code from Google Authenticator, Authy, etc.
|
75
|
+
* const totpCode = '123456';
|
76
|
+
* const result = await mfaFlow.verifyTOTP(totpCode, 'session_id');
|
77
|
+
* ```
|
78
|
+
*/
|
79
|
+
verifyTOTP(totpCode: string, sessionId: string): Promise<AuthResult>;
|
80
|
+
}
|
81
|
+
//# sourceMappingURL=mfa.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"mfa.d.ts","sourceRoot":"","sources":["../../../../../src/auth/flows/mfa.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAuC,UAAU,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAEhG,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,OAAQ,SAAQ,YAAY;gBAE3B,MAAM,EAAE,cAAc;IAIlC;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACG,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IA8BrE;;;;;;;;;;;;;OAaG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;CA8C3E"}
|
@@ -0,0 +1,103 @@
|
|
1
|
+
/**
|
2
|
+
* Multi-Factor Authentication (MFA) flow
|
3
|
+
*
|
4
|
+
* Handles MFA verification using the actual tenant-sdk AuthenticationApi.verifyMfaApiV1AuthMfaVerifyPost method.
|
5
|
+
* Provides TOTP setup and management functionality.
|
6
|
+
*/
|
7
|
+
import { AuthError, AuthErrorCode } from "../error";
|
8
|
+
import { BaseAuthFlow } from "./base-flow";
|
9
|
+
/**
|
10
|
+
* Multi-Factor Authentication flow
|
11
|
+
*
|
12
|
+
* Provides MFA verification using actual tenant-sdk APIs.
|
13
|
+
* Uses AuthenticationApi.verifyMfaApiV1AuthMfaVerifyPost for MFA verification.
|
14
|
+
*
|
15
|
+
* @example
|
16
|
+
* ```typescript
|
17
|
+
* const mfaFlow = new MFAFlow(config);
|
18
|
+
*
|
19
|
+
* // After initial login, if MFA is required
|
20
|
+
* try {
|
21
|
+
* const loginResult = await passwordFlow.login(email, password);
|
22
|
+
* } catch (error) {
|
23
|
+
* if (error.code === AuthErrorCode.MFA_REQUIRED) {
|
24
|
+
* const sessionId = error.details.sessionId;
|
25
|
+
*
|
26
|
+
* // User enters TOTP code from authenticator app
|
27
|
+
* const mfaResult = await mfaFlow.verifyMFA('123456', sessionId);
|
28
|
+
*
|
29
|
+
* if (mfaResult.success) {
|
30
|
+
* console.log('MFA successful:', mfaResult.user);
|
31
|
+
* }
|
32
|
+
* }
|
33
|
+
* }
|
34
|
+
* ```
|
35
|
+
*/
|
36
|
+
export class MFAFlow extends BaseAuthFlow {
|
37
|
+
constructor(config) {
|
38
|
+
super(config);
|
39
|
+
}
|
40
|
+
/**
|
41
|
+
* Verifies MFA using tenant-sdk AuthenticationApi.verifyMfaApiV1AuthMfaVerifyPost
|
42
|
+
*
|
43
|
+
* @param code - MFA verification code (typically from TOTP app)
|
44
|
+
* @param sessionId - Session identifier from initial login attempt
|
45
|
+
* @returns Promise resolving to authentication result
|
46
|
+
*
|
47
|
+
* @example
|
48
|
+
* ```typescript
|
49
|
+
* try {
|
50
|
+
* const result = await mfaFlow.verifyMFA('123456', 'session_id_from_login');
|
51
|
+
* if (result.success) {
|
52
|
+
* console.log('MFA verification successful!');
|
53
|
+
* localStorage.setItem('accessToken', result.accessToken);
|
54
|
+
* }
|
55
|
+
* } catch (error) {
|
56
|
+
* if (error.code === AuthErrorCode.INVALID_OTP) {
|
57
|
+
* console.log('Invalid MFA code');
|
58
|
+
* } else if (error.code === AuthErrorCode.MFA_CHALLENGE_EXPIRED) {
|
59
|
+
* console.log('Session expired, please log in again');
|
60
|
+
* }
|
61
|
+
* }
|
62
|
+
* ```
|
63
|
+
*
|
64
|
+
* @throws {AuthError} When MFA verification fails
|
65
|
+
*/
|
66
|
+
async verifyMFA(code, sessionId) {
|
67
|
+
if (!code) {
|
68
|
+
throw new AuthError(AuthErrorCode.MISSING_REQUIRED_FIELD, 'MFA code is required');
|
69
|
+
}
|
70
|
+
if (!sessionId) {
|
71
|
+
throw new AuthError(AuthErrorCode.MISSING_REQUIRED_FIELD, 'Session ID is required');
|
72
|
+
}
|
73
|
+
const normalizedCode = code.replace(/\s+/g, '').toString();
|
74
|
+
return this.safeApiCall(async () => {
|
75
|
+
// Use the actual tenant-sdk AuthenticationApi.verifyMfaApiV1AuthMfaVerifyPost method
|
76
|
+
const response = await this.authApi.verifyMfaApiV1AuthMfaVerifyPost({
|
77
|
+
mFARequest: {
|
78
|
+
code: normalizedCode,
|
79
|
+
sessionId,
|
80
|
+
},
|
81
|
+
});
|
82
|
+
return this.processAuthResponse(response);
|
83
|
+
}, AuthErrorCode.INVALID_OTP);
|
84
|
+
}
|
85
|
+
/**
|
86
|
+
* Convenience method for verifying TOTP (Time-based One-Time Password)
|
87
|
+
*
|
88
|
+
* @param totpCode - 6-digit TOTP code from authenticator app
|
89
|
+
* @param sessionId - Session identifier from initial login attempt
|
90
|
+
* @returns Promise resolving to authentication result
|
91
|
+
*
|
92
|
+
* @example
|
93
|
+
* ```typescript
|
94
|
+
* // User enters code from Google Authenticator, Authy, etc.
|
95
|
+
* const totpCode = '123456';
|
96
|
+
* const result = await mfaFlow.verifyTOTP(totpCode, 'session_id');
|
97
|
+
* ```
|
98
|
+
*/
|
99
|
+
async verifyTOTP(totpCode, sessionId) {
|
100
|
+
return this.verifyMFA(totpCode, sessionId);
|
101
|
+
}
|
102
|
+
}
|
103
|
+
//# sourceMappingURL=mfa.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"mfa.js","sourceRoot":"","sources":["../../../../../src/auth/flows/mfa.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,OAAO,OAAQ,SAAQ,YAAY;IAEvC,YAAY,MAAsB;QAChC,KAAK,CAAC,MAAM,CAAC,CAAC;IAChB,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,KAAK,CAAC,SAAS,CAAC,IAAY,EAAE,SAAiB;QAC7C,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,SAAS,CACjB,aAAa,CAAC,sBAAsB,EACpC,sBAAsB,CACvB,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,SAAS,CACjB,aAAa,CAAC,sBAAsB,EACpC,wBAAwB,CACzB,CAAC;QACJ,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;QAE3D,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,IAAI,EAAE;YACjC,qFAAqF;YACrF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,+BAA+B,CAAC;gBAClE,UAAU,EAAE;oBACV,IAAI,EAAE,cAAc;oBACpB,SAAS;iBACV;aACF,CAAC,CAAC;YAEH,OAAO,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QAC5C,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IAChC,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,UAAU,CAAC,QAAgB,EAAE,SAAiB;QAClD,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC7C,CAAC;CA4CF"}
|