@stapel/auth-react 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +56 -0
- package/LICENSE +21 -0
- package/MODULE.md +147 -0
- package/README.md +116 -0
- package/dist/api/authApi.d.ts +68 -0
- package/dist/api/authApi.d.ts.map +1 -0
- package/dist/api/authApi.js +90 -0
- package/dist/api/authApi.js.map +1 -0
- package/dist/api/types.d.ts +238 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +14 -0
- package/dist/api/types.js.map +1 -0
- package/dist/api/urls.d.ts +41 -0
- package/dist/api/urls.d.ts.map +1 -0
- package/dist/api/urls.js +86 -0
- package/dist/api/urls.js.map +1 -0
- package/dist/flows/anonymousFlow.d.ts +33 -0
- package/dist/flows/anonymousFlow.d.ts.map +1 -0
- package/dist/flows/anonymousFlow.js +26 -0
- package/dist/flows/anonymousFlow.js.map +1 -0
- package/dist/flows/authenticatorChangeFlow.d.ts +67 -0
- package/dist/flows/authenticatorChangeFlow.d.ts.map +1 -0
- package/dist/flows/authenticatorChangeFlow.js +79 -0
- package/dist/flows/authenticatorChangeFlow.js.map +1 -0
- package/dist/flows/createFlowMachine.d.ts +55 -0
- package/dist/flows/createFlowMachine.d.ts.map +1 -0
- package/dist/flows/createFlowMachine.js +56 -0
- package/dist/flows/createFlowMachine.js.map +1 -0
- package/dist/flows/errors.d.ts +15 -0
- package/dist/flows/errors.d.ts.map +1 -0
- package/dist/flows/errors.js +17 -0
- package/dist/flows/errors.js.map +1 -0
- package/dist/flows/magicLinkFlow.d.ts +41 -0
- package/dist/flows/magicLinkFlow.d.ts.map +1 -0
- package/dist/flows/magicLinkFlow.js +29 -0
- package/dist/flows/magicLinkFlow.js.map +1 -0
- package/dist/flows/oauthFlow.d.ts +58 -0
- package/dist/flows/oauthFlow.d.ts.map +1 -0
- package/dist/flows/oauthFlow.js +53 -0
- package/dist/flows/oauthFlow.js.map +1 -0
- package/dist/flows/otpFlow.d.ts +74 -0
- package/dist/flows/otpFlow.d.ts.map +1 -0
- package/dist/flows/otpFlow.js +68 -0
- package/dist/flows/otpFlow.js.map +1 -0
- package/dist/flows/passkeyFlow.d.ts +75 -0
- package/dist/flows/passkeyFlow.d.ts.map +1 -0
- package/dist/flows/passkeyFlow.js +100 -0
- package/dist/flows/passkeyFlow.js.map +1 -0
- package/dist/flows/passwordChangeFlow.d.ts +53 -0
- package/dist/flows/passwordChangeFlow.d.ts.map +1 -0
- package/dist/flows/passwordChangeFlow.js +51 -0
- package/dist/flows/passwordChangeFlow.js.map +1 -0
- package/dist/flows/passwordLoginFlow.d.ts +62 -0
- package/dist/flows/passwordLoginFlow.d.ts.map +1 -0
- package/dist/flows/passwordLoginFlow.js +55 -0
- package/dist/flows/passwordLoginFlow.js.map +1 -0
- package/dist/flows/passwordResetFlow.d.ts +56 -0
- package/dist/flows/passwordResetFlow.d.ts.map +1 -0
- package/dist/flows/passwordResetFlow.js +57 -0
- package/dist/flows/passwordResetFlow.js.map +1 -0
- package/dist/flows/qrLoginFlow.d.ts +55 -0
- package/dist/flows/qrLoginFlow.d.ts.map +1 -0
- package/dist/flows/qrLoginFlow.js +91 -0
- package/dist/flows/qrLoginFlow.js.map +1 -0
- package/dist/flows/ssoFlow.d.ts +46 -0
- package/dist/flows/ssoFlow.d.ts.map +1 -0
- package/dist/flows/ssoFlow.js +34 -0
- package/dist/flows/ssoFlow.js.map +1 -0
- package/dist/flows/totpSetupFlow.d.ts +49 -0
- package/dist/flows/totpSetupFlow.d.ts.map +1 -0
- package/dist/flows/totpSetupFlow.js +47 -0
- package/dist/flows/totpSetupFlow.js.map +1 -0
- package/dist/flows/useFlow.d.ts +9 -0
- package/dist/flows/useFlow.d.ts.map +1 -0
- package/dist/flows/useFlow.js +11 -0
- package/dist/flows/useFlow.js.map +1 -0
- package/dist/flows/verificationFlow.d.ts +108 -0
- package/dist/flows/verificationFlow.d.ts.map +1 -0
- package/dist/flows/verificationFlow.js +195 -0
- package/dist/flows/verificationFlow.js.map +1 -0
- package/dist/headless/AuthProvider.d.ts +18 -0
- package/dist/headless/AuthProvider.d.ts.map +1 -0
- package/dist/headless/AuthProvider.js +22 -0
- package/dist/headless/AuthProvider.js.map +1 -0
- package/dist/headless/Passkey.d.ts +31 -0
- package/dist/headless/Passkey.d.ts.map +1 -0
- package/dist/headless/Passkey.js +51 -0
- package/dist/headless/Passkey.js.map +1 -0
- package/dist/headless/PasswordChange.d.ts +20 -0
- package/dist/headless/PasswordChange.d.ts.map +1 -0
- package/dist/headless/PasswordChange.js +30 -0
- package/dist/headless/PasswordChange.js.map +1 -0
- package/dist/headless/PasswordLogin.d.ts +17 -0
- package/dist/headless/PasswordLogin.d.ts.map +1 -0
- package/dist/headless/PasswordLogin.js +31 -0
- package/dist/headless/PasswordLogin.js.map +1 -0
- package/dist/headless/PasswordReset.d.ts +19 -0
- package/dist/headless/PasswordReset.d.ts.map +1 -0
- package/dist/headless/PasswordReset.js +34 -0
- package/dist/headless/PasswordReset.js.map +1 -0
- package/dist/headless/PasswordlessLogin.d.ts +28 -0
- package/dist/headless/PasswordlessLogin.d.ts.map +1 -0
- package/dist/headless/PasswordlessLogin.js +42 -0
- package/dist/headless/PasswordlessLogin.js.map +1 -0
- package/dist/headless/QrLogin.d.ts +19 -0
- package/dist/headless/QrLogin.d.ts.map +1 -0
- package/dist/headless/QrLogin.js +32 -0
- package/dist/headless/QrLogin.js.map +1 -0
- package/dist/headless/TotpSetup.d.ts +17 -0
- package/dist/headless/TotpSetup.d.ts.map +1 -0
- package/dist/headless/TotpSetup.js +26 -0
- package/dist/headless/TotpSetup.js.map +1 -0
- package/dist/headless/VerificationChallenge.d.ts +37 -0
- package/dist/headless/VerificationChallenge.d.ts.map +1 -0
- package/dist/headless/VerificationChallenge.js +40 -0
- package/dist/headless/VerificationChallenge.js.map +1 -0
- package/dist/headless/misc.d.ts +47 -0
- package/dist/headless/misc.d.ts.map +1 -0
- package/dist/headless/misc.js +84 -0
- package/dist/headless/misc.js.map +1 -0
- package/dist/i18n/keys.d.ts +34 -0
- package/dist/i18n/keys.d.ts.map +1 -0
- package/dist/i18n/keys.js +83 -0
- package/dist/i18n/keys.js.map +1 -0
- package/dist/index.d.ts +73 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +48 -0
- package/dist/index.js.map +1 -0
- package/dist/model/context.d.ts +22 -0
- package/dist/model/context.d.ts.map +1 -0
- package/dist/model/context.js +34 -0
- package/dist/model/context.js.map +1 -0
- package/dist/model/mutations.d.ts +28 -0
- package/dist/model/mutations.d.ts.map +1 -0
- package/dist/model/mutations.js +108 -0
- package/dist/model/mutations.js.map +1 -0
- package/dist/model/queries.d.ts +30 -0
- package/dist/model/queries.d.ts.map +1 -0
- package/dist/model/queries.js +87 -0
- package/dist/model/queries.js.map +1 -0
- package/dist/model/queryKeys.d.ts +13 -0
- package/dist/model/queryKeys.d.ts.map +1 -0
- package/dist/model/queryKeys.js +21 -0
- package/dist/model/queryKeys.js.map +1 -0
- package/dist/model/runtime.d.ts +39 -0
- package/dist/model/runtime.d.ts.map +1 -0
- package/dist/model/runtime.js +44 -0
- package/dist/model/runtime.js.map +1 -0
- package/dist/model/session.d.ts +50 -0
- package/dist/model/session.d.ts.map +1 -0
- package/dist/model/session.js +124 -0
- package/dist/model/session.js.map +1 -0
- package/package.json +68 -0
- package/src/api/authApi.ts +332 -0
- package/src/api/types.ts +291 -0
- package/src/api/urls.ts +99 -0
- package/src/flows/anonymousFlow.ts +57 -0
- package/src/flows/authenticatorChangeFlow.ts +160 -0
- package/src/flows/createFlowMachine.ts +126 -0
- package/src/flows/errors.ts +29 -0
- package/src/flows/magicLinkFlow.ts +68 -0
- package/src/flows/oauthFlow.ts +114 -0
- package/src/flows/otpFlow.ts +156 -0
- package/src/flows/passkeyFlow.ts +191 -0
- package/src/flows/passwordChangeFlow.ts +114 -0
- package/src/flows/passwordLoginFlow.ts +122 -0
- package/src/flows/passwordResetFlow.ts +123 -0
- package/src/flows/qrLoginFlow.ts +158 -0
- package/src/flows/ssoFlow.ts +84 -0
- package/src/flows/totpSetupFlow.ts +96 -0
- package/src/flows/useFlow.ts +16 -0
- package/src/flows/verificationFlow.ts +341 -0
- package/src/headless/AuthProvider.tsx +30 -0
- package/src/headless/Passkey.tsx +97 -0
- package/src/headless/PasswordChange.tsx +46 -0
- package/src/headless/PasswordLogin.tsx +49 -0
- package/src/headless/PasswordReset.tsx +51 -0
- package/src/headless/PasswordlessLogin.tsx +60 -0
- package/src/headless/QrLogin.tsx +52 -0
- package/src/headless/TotpSetup.tsx +40 -0
- package/src/headless/VerificationChallenge.tsx +54 -0
- package/src/headless/misc.tsx +151 -0
- package/src/i18n/keys.ts +94 -0
- package/src/index.ts +229 -0
- package/src/model/context.tsx +51 -0
- package/src/model/mutations.ts +152 -0
- package/src/model/queries.ts +130 -0
- package/src/model/queryKeys.ts +32 -0
- package/src/model/runtime.ts +93 -0
- package/src/model/session.ts +188 -0
- package/tsconfig.json +26 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire types for the stapel-auth HTTP contract (auth-sa.md §1–18).
|
|
3
|
+
*
|
|
4
|
+
* These are hand-authored here because the auth backend does not yet publish
|
|
5
|
+
* an `openapi.json` artifact to this monorepo. When it does, this file is the
|
|
6
|
+
* codegen target (frontend-standard §2/§3): the shapes below are transcribed
|
|
7
|
+
* verbatim from auth-sa.md's documented request/response bodies so a future
|
|
8
|
+
* `regen` produces a compatible surface.
|
|
9
|
+
*/
|
|
10
|
+
/** Result status of any flow that ends in a session (auth-sa.md §"AuthResponse"). */
|
|
11
|
+
export type AuthStatus = "LOGGED_IN" | "REGISTERED" | "MERGED" | "MODIFIED";
|
|
12
|
+
/** The authenticated principal. Backend adds fields freely; kept open. */
|
|
13
|
+
export interface StapelUser {
|
|
14
|
+
readonly id: string;
|
|
15
|
+
readonly username?: string;
|
|
16
|
+
readonly email?: string | null;
|
|
17
|
+
readonly phone?: string | null;
|
|
18
|
+
readonly is_anonymous?: boolean;
|
|
19
|
+
readonly [extra: string]: unknown;
|
|
20
|
+
}
|
|
21
|
+
/** Access/refresh JWT pair returned in the body (also set as cookies). */
|
|
22
|
+
export interface AuthTokens {
|
|
23
|
+
readonly access: string;
|
|
24
|
+
readonly refresh: string;
|
|
25
|
+
}
|
|
26
|
+
/** Returned by every flow that results in a session. */
|
|
27
|
+
export interface AuthResponse {
|
|
28
|
+
readonly status: AuthStatus;
|
|
29
|
+
readonly user: StapelUser;
|
|
30
|
+
readonly tokens: AuthTokens;
|
|
31
|
+
}
|
|
32
|
+
/** Returned instead of `AuthResponse` when the account has TOTP enabled. */
|
|
33
|
+
export interface TOTPChallengeResponse {
|
|
34
|
+
readonly status: "TOTP_REQUIRED";
|
|
35
|
+
readonly challenge_token: string;
|
|
36
|
+
readonly expires_in: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The `oneOf` login union (discriminator: `status`). Narrow with
|
|
40
|
+
* `if (r.status === "TOTP_REQUIRED")`.
|
|
41
|
+
*/
|
|
42
|
+
export type LoginResponse = AuthResponse | TOTPChallengeResponse;
|
|
43
|
+
/** Narrowing helper for the login union. */
|
|
44
|
+
export declare function isTotpChallenge(r: LoginResponse): r is TOTPChallengeResponse;
|
|
45
|
+
/** `{ message, target }` — target is the masked destination to display. */
|
|
46
|
+
export interface OtpRequestResponse {
|
|
47
|
+
readonly message: string;
|
|
48
|
+
readonly target: string;
|
|
49
|
+
}
|
|
50
|
+
/** Simple status envelopes returned by several mutations. */
|
|
51
|
+
export interface StatusResponse {
|
|
52
|
+
readonly status: string;
|
|
53
|
+
}
|
|
54
|
+
export interface OAuthProviderInfo {
|
|
55
|
+
readonly id: string;
|
|
56
|
+
readonly name: string;
|
|
57
|
+
}
|
|
58
|
+
export interface RegistrationCapabilities {
|
|
59
|
+
readonly phone: boolean;
|
|
60
|
+
readonly email: boolean;
|
|
61
|
+
readonly password: boolean;
|
|
62
|
+
readonly oauth: readonly OAuthProviderInfo[];
|
|
63
|
+
readonly sso: boolean;
|
|
64
|
+
readonly anonymous: boolean;
|
|
65
|
+
}
|
|
66
|
+
export interface LoginCapabilities {
|
|
67
|
+
readonly phone: boolean;
|
|
68
|
+
readonly email: boolean;
|
|
69
|
+
readonly password: boolean;
|
|
70
|
+
readonly oauth: readonly OAuthProviderInfo[];
|
|
71
|
+
readonly sso: boolean;
|
|
72
|
+
readonly qr: boolean;
|
|
73
|
+
readonly passkey: boolean;
|
|
74
|
+
readonly magic_link: boolean;
|
|
75
|
+
}
|
|
76
|
+
export interface Capabilities {
|
|
77
|
+
readonly registration: RegistrationCapabilities;
|
|
78
|
+
readonly login: LoginCapabilities;
|
|
79
|
+
}
|
|
80
|
+
export type PasswordChangeMethod = "password" | "email" | "phone";
|
|
81
|
+
export interface PasswordMethodEntry {
|
|
82
|
+
readonly method: PasswordChangeMethod;
|
|
83
|
+
readonly target?: string;
|
|
84
|
+
}
|
|
85
|
+
export interface PasswordMethods {
|
|
86
|
+
readonly has_password: boolean;
|
|
87
|
+
readonly methods: readonly PasswordMethodEntry[];
|
|
88
|
+
}
|
|
89
|
+
export interface SecurityStatus {
|
|
90
|
+
readonly password: {
|
|
91
|
+
readonly is_set: boolean;
|
|
92
|
+
};
|
|
93
|
+
readonly totp: {
|
|
94
|
+
readonly is_enabled: boolean;
|
|
95
|
+
readonly backup_codes_remaining: number;
|
|
96
|
+
};
|
|
97
|
+
readonly email: {
|
|
98
|
+
readonly value: string | null;
|
|
99
|
+
readonly is_verified: boolean;
|
|
100
|
+
};
|
|
101
|
+
readonly phone: {
|
|
102
|
+
readonly value: string | null;
|
|
103
|
+
readonly is_verified: boolean;
|
|
104
|
+
};
|
|
105
|
+
readonly oauth: {
|
|
106
|
+
readonly connected_providers: readonly string[];
|
|
107
|
+
};
|
|
108
|
+
readonly sessions: {
|
|
109
|
+
readonly active_count: number;
|
|
110
|
+
};
|
|
111
|
+
readonly passkeys: {
|
|
112
|
+
readonly count: number;
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
export type SessionDeviceType = "phone" | "tablet" | "desktop" | "api" | "unknown";
|
|
116
|
+
export interface AuthSession {
|
|
117
|
+
readonly id: string;
|
|
118
|
+
readonly device_type: SessionDeviceType;
|
|
119
|
+
readonly device_name: string;
|
|
120
|
+
readonly device_details: string;
|
|
121
|
+
readonly ip_address: string;
|
|
122
|
+
readonly created_at: string;
|
|
123
|
+
readonly last_used_at: string;
|
|
124
|
+
readonly is_current: boolean;
|
|
125
|
+
readonly is_suspicious: boolean;
|
|
126
|
+
}
|
|
127
|
+
export interface TotpSetupResponse {
|
|
128
|
+
readonly secret: string;
|
|
129
|
+
readonly qr_uri: string;
|
|
130
|
+
readonly expires_in: number;
|
|
131
|
+
}
|
|
132
|
+
export interface TotpSetupConfirmResponse {
|
|
133
|
+
readonly backup_codes: readonly string[];
|
|
134
|
+
}
|
|
135
|
+
/** `oneOf` discriminated by `method` (auth-sa.md §"Disable TOTP"). */
|
|
136
|
+
export type TotpDisableRequest = {
|
|
137
|
+
readonly method: "totp";
|
|
138
|
+
readonly code: string;
|
|
139
|
+
} | {
|
|
140
|
+
readonly method: "backup";
|
|
141
|
+
readonly backup_code: string;
|
|
142
|
+
} | {
|
|
143
|
+
readonly method: "otp";
|
|
144
|
+
readonly otp_code: string;
|
|
145
|
+
};
|
|
146
|
+
export type VerificationFactorId = "otp_email" | "otp_phone" | "totp" | "passkey";
|
|
147
|
+
/** The `verification` object inside the 403 envelope. */
|
|
148
|
+
export interface VerificationEnvelope {
|
|
149
|
+
readonly challenge_id: string;
|
|
150
|
+
readonly scope: string;
|
|
151
|
+
readonly factors: readonly VerificationFactorId[];
|
|
152
|
+
readonly expires_at: number;
|
|
153
|
+
}
|
|
154
|
+
export interface VerificationInitiateResponse {
|
|
155
|
+
readonly factor: VerificationFactorId;
|
|
156
|
+
/** For otp_* — `{ target }`; for passkey — `{ session_key, options }`. */
|
|
157
|
+
readonly data: Record<string, unknown>;
|
|
158
|
+
}
|
|
159
|
+
export interface VerificationCompleteResponse {
|
|
160
|
+
readonly verified: boolean;
|
|
161
|
+
readonly verification_token: string;
|
|
162
|
+
}
|
|
163
|
+
export type QrType = "session_share" | "login_request";
|
|
164
|
+
export interface QrGenerateResponse {
|
|
165
|
+
readonly key: string;
|
|
166
|
+
readonly type: QrType;
|
|
167
|
+
readonly expires_in: number;
|
|
168
|
+
readonly scan_url: string;
|
|
169
|
+
}
|
|
170
|
+
export type QrStatusValue = "pending" | "fulfilled" | "expired" | "rejected";
|
|
171
|
+
export interface QrStatusResponse {
|
|
172
|
+
readonly status: QrStatusValue;
|
|
173
|
+
/** Present only on `login_request` fulfilment. */
|
|
174
|
+
readonly access_token?: string;
|
|
175
|
+
readonly refresh_token?: string;
|
|
176
|
+
}
|
|
177
|
+
export interface Passkey {
|
|
178
|
+
readonly id: string;
|
|
179
|
+
readonly device_name: string;
|
|
180
|
+
readonly aaguid: string;
|
|
181
|
+
readonly transports: readonly string[];
|
|
182
|
+
readonly created_at: string;
|
|
183
|
+
readonly last_used_at: string | null;
|
|
184
|
+
}
|
|
185
|
+
export interface PasskeyRegisterBeginResponse {
|
|
186
|
+
/** PublicKeyCredentialCreationOptions (JSON form). */
|
|
187
|
+
readonly options: Record<string, unknown>;
|
|
188
|
+
}
|
|
189
|
+
export interface PasskeyAuthenticateBeginResponse {
|
|
190
|
+
readonly session_key: string;
|
|
191
|
+
/** PublicKeyCredentialRequestOptions (JSON form). */
|
|
192
|
+
readonly options: Record<string, unknown>;
|
|
193
|
+
}
|
|
194
|
+
export interface ChangeOldVerifiedResponse {
|
|
195
|
+
readonly status: "OLD_VERIFIED";
|
|
196
|
+
readonly change_token: string;
|
|
197
|
+
readonly expires_at: string;
|
|
198
|
+
}
|
|
199
|
+
export interface DelayedChangeInitiatedResponse {
|
|
200
|
+
readonly status: "PENDING";
|
|
201
|
+
readonly change_request_id: string;
|
|
202
|
+
readonly scheduled_at: string;
|
|
203
|
+
readonly can_cancel_until: string;
|
|
204
|
+
}
|
|
205
|
+
export type DelayedChangeStatus = {
|
|
206
|
+
readonly has_pending_change: false;
|
|
207
|
+
} | {
|
|
208
|
+
readonly has_pending_change?: true;
|
|
209
|
+
readonly change_request_id: string;
|
|
210
|
+
readonly scheduled_at: string;
|
|
211
|
+
readonly can_cancel_until: string;
|
|
212
|
+
};
|
|
213
|
+
export interface SsoLookupResponse {
|
|
214
|
+
readonly sso_required: boolean;
|
|
215
|
+
readonly org_slug: string | null;
|
|
216
|
+
readonly protocol?: "saml" | "oidc";
|
|
217
|
+
}
|
|
218
|
+
export interface AuditEvent {
|
|
219
|
+
readonly id: string;
|
|
220
|
+
readonly event_type: string;
|
|
221
|
+
readonly ip_address: string;
|
|
222
|
+
readonly user_agent: string;
|
|
223
|
+
readonly metadata: Record<string, unknown>;
|
|
224
|
+
readonly created_at: string;
|
|
225
|
+
}
|
|
226
|
+
export interface AuditPage {
|
|
227
|
+
readonly results: readonly AuditEvent[];
|
|
228
|
+
readonly count: number;
|
|
229
|
+
readonly next: number | null;
|
|
230
|
+
}
|
|
231
|
+
/** `{ access, refresh }` from POST/GET /token/refresh/. */
|
|
232
|
+
export interface RefreshResponse {
|
|
233
|
+
readonly access: string;
|
|
234
|
+
readonly refresh: string;
|
|
235
|
+
}
|
|
236
|
+
/** Which identifier channel an OTP flow uses. */
|
|
237
|
+
export type OtpChannel = "email" | "phone";
|
|
238
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire types for the stapel-auth HTTP contract (auth-sa.md §1–18).
|
|
3
|
+
*
|
|
4
|
+
* These are hand-authored here because the auth backend does not yet publish
|
|
5
|
+
* an `openapi.json` artifact to this monorepo. When it does, this file is the
|
|
6
|
+
* codegen target (frontend-standard §2/§3): the shapes below are transcribed
|
|
7
|
+
* verbatim from auth-sa.md's documented request/response bodies so a future
|
|
8
|
+
* `regen` produces a compatible surface.
|
|
9
|
+
*/
|
|
10
|
+
/** Narrowing helper for the login union. */
|
|
11
|
+
export function isTotpChallenge(r) {
|
|
12
|
+
return r.status === "TOTP_REQUIRED";
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAyCH,4CAA4C;AAC5C,MAAM,UAAU,eAAe,CAAC,CAAgB;IAC9C,OAAO,CAAC,CAAC,MAAM,KAAK,eAAe,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL builders for the **browser-redirect** auth endpoints (auth-sa.md §7/§8/
|
|
3
|
+
* §15/§18). These must never be called with `fetch` — they are full-page
|
|
4
|
+
* navigations. Callers do `window.location.assign(authUrls(...).xyz)`.
|
|
5
|
+
*
|
|
6
|
+
* Plus the two open-redirect defence helpers of auth-sa.md §19.2. Every new
|
|
7
|
+
* `?somewhere=` parameter that ends up in `location.href`/`navigate()` must
|
|
8
|
+
* pass through one of these rather than trust raw input.
|
|
9
|
+
*/
|
|
10
|
+
export interface AuthUrls {
|
|
11
|
+
/** Server-side OAuth redirect (auth-sa.md §7 option A). */
|
|
12
|
+
oauthAuthorize(provider: string, redirectUri: string): string;
|
|
13
|
+
/** Enterprise SSO login redirect (auth-sa.md §18.1 step 2). */
|
|
14
|
+
ssoLogin(orgSlug: string): string;
|
|
15
|
+
/** The URL embedded in a QR image — opened by the scanner's browser only. */
|
|
16
|
+
qrScan(key: string): string;
|
|
17
|
+
/** SP metadata URL surfaced to a customer's IT admin (auth-sa.md §18.4). */
|
|
18
|
+
ssoSamlMetadata(orgSlug: string): string;
|
|
19
|
+
}
|
|
20
|
+
/** Build the browser-redirect URLs against a client base URL (e.g. `/auth/api`). */
|
|
21
|
+
export declare function authUrls(baseUrl: string): AuthUrls;
|
|
22
|
+
/**
|
|
23
|
+
* `redirect_url` for magic-link / QR generation must be a **relative** path
|
|
24
|
+
* starting with a single `/` (auth-sa.md §8/§15 — open-redirect defence).
|
|
25
|
+
* Returns the path unchanged when valid, else `null`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function validRedirectUrl(raw: string): string | null;
|
|
28
|
+
/**
|
|
29
|
+
* auth-sa.md §19.2 `safeNextPath`: accept a relative path (single leading `/`,
|
|
30
|
+
* not `//`) or a same-origin absolute URL reduced to `pathname+search+hash`.
|
|
31
|
+
* Anything cross-origin / unrecognised returns `null`; callers fall back to a
|
|
32
|
+
* safe default (e.g. `/app`).
|
|
33
|
+
*/
|
|
34
|
+
export declare function safeNextPath(raw: string | null | undefined, origin?: string): string | null;
|
|
35
|
+
/**
|
|
36
|
+
* auth-sa.md §19.2 `safeScanRedirect`: accept only same-origin URLs whose path
|
|
37
|
+
* starts with `/auth/api/qr/` (the QR scan-flow continuation). Used for
|
|
38
|
+
* `?redirect=` on `/sign-in`.
|
|
39
|
+
*/
|
|
40
|
+
export declare function safeScanRedirect(raw: string | null | undefined, origin?: string): string | null;
|
|
41
|
+
//# sourceMappingURL=urls.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"urls.d.ts","sourceRoot":"","sources":["../../src/api/urls.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,MAAM,WAAW,QAAQ;IACvB,2DAA2D;IAC3D,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9D,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IAClC,6EAA6E;IAC7E,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,4EAA4E;IAC5E,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;CAC1C;AAED,oFAAoF;AACpF,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,CAWlD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK3D;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC9B,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,GAAG,IAAI,CAcf;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC9B,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,GAAG,IAAI,CAcf"}
|
package/dist/api/urls.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL builders for the **browser-redirect** auth endpoints (auth-sa.md §7/§8/
|
|
3
|
+
* §15/§18). These must never be called with `fetch` — they are full-page
|
|
4
|
+
* navigations. Callers do `window.location.assign(authUrls(...).xyz)`.
|
|
5
|
+
*
|
|
6
|
+
* Plus the two open-redirect defence helpers of auth-sa.md §19.2. Every new
|
|
7
|
+
* `?somewhere=` parameter that ends up in `location.href`/`navigate()` must
|
|
8
|
+
* pass through one of these rather than trust raw input.
|
|
9
|
+
*/
|
|
10
|
+
function trimBase(baseUrl) {
|
|
11
|
+
return baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
|
|
12
|
+
}
|
|
13
|
+
/** Build the browser-redirect URLs against a client base URL (e.g. `/auth/api`). */
|
|
14
|
+
export function authUrls(baseUrl) {
|
|
15
|
+
const base = trimBase(baseUrl);
|
|
16
|
+
return {
|
|
17
|
+
oauthAuthorize: (provider, redirectUri) => `${base}/oauth/${provider}/authorize/?redirect_uri=${encodeURIComponent(redirectUri)}`,
|
|
18
|
+
ssoLogin: (orgSlug) => `${base}/sso/${orgSlug}/login/`,
|
|
19
|
+
qrScan: (key) => `${base}/qr/${key}/scan/`,
|
|
20
|
+
ssoSamlMetadata: (orgSlug) => `${base}/sso/${orgSlug}/saml/metadata/`,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* `redirect_url` for magic-link / QR generation must be a **relative** path
|
|
25
|
+
* starting with a single `/` (auth-sa.md §8/§15 — open-redirect defence).
|
|
26
|
+
* Returns the path unchanged when valid, else `null`.
|
|
27
|
+
*/
|
|
28
|
+
export function validRedirectUrl(raw) {
|
|
29
|
+
if (raw.length === 0)
|
|
30
|
+
return null;
|
|
31
|
+
if (!raw.startsWith("/"))
|
|
32
|
+
return null;
|
|
33
|
+
if (raw.startsWith("//"))
|
|
34
|
+
return null;
|
|
35
|
+
return raw;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* auth-sa.md §19.2 `safeNextPath`: accept a relative path (single leading `/`,
|
|
39
|
+
* not `//`) or a same-origin absolute URL reduced to `pathname+search+hash`.
|
|
40
|
+
* Anything cross-origin / unrecognised returns `null`; callers fall back to a
|
|
41
|
+
* safe default (e.g. `/app`).
|
|
42
|
+
*/
|
|
43
|
+
export function safeNextPath(raw, origin) {
|
|
44
|
+
if (raw == null || raw.length === 0)
|
|
45
|
+
return null;
|
|
46
|
+
if (raw.startsWith("/") && !raw.startsWith("//"))
|
|
47
|
+
return raw;
|
|
48
|
+
const selfOrigin = origin ??
|
|
49
|
+
(typeof window !== "undefined" ? window.location.origin : undefined);
|
|
50
|
+
if (selfOrigin === undefined)
|
|
51
|
+
return null;
|
|
52
|
+
try {
|
|
53
|
+
const url = new URL(raw, selfOrigin);
|
|
54
|
+
if (url.origin !== selfOrigin)
|
|
55
|
+
return null;
|
|
56
|
+
return `${url.pathname}${url.search}${url.hash}`;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* auth-sa.md §19.2 `safeScanRedirect`: accept only same-origin URLs whose path
|
|
64
|
+
* starts with `/auth/api/qr/` (the QR scan-flow continuation). Used for
|
|
65
|
+
* `?redirect=` on `/sign-in`.
|
|
66
|
+
*/
|
|
67
|
+
export function safeScanRedirect(raw, origin) {
|
|
68
|
+
if (raw == null || raw.length === 0)
|
|
69
|
+
return null;
|
|
70
|
+
const selfOrigin = origin ??
|
|
71
|
+
(typeof window !== "undefined" ? window.location.origin : undefined);
|
|
72
|
+
if (selfOrigin === undefined)
|
|
73
|
+
return null;
|
|
74
|
+
try {
|
|
75
|
+
const url = new URL(raw, selfOrigin);
|
|
76
|
+
if (url.origin !== selfOrigin)
|
|
77
|
+
return null;
|
|
78
|
+
if (!url.pathname.startsWith("/auth/api/qr/"))
|
|
79
|
+
return null;
|
|
80
|
+
return url.toString();
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=urls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"urls.js","sourceRoot":"","sources":["../../src/api/urls.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Analytics } from "@stapel/core";
|
|
2
|
+
import type { AuthApi } from "../api/authApi.js";
|
|
3
|
+
import type { AuthResponse } from "../api/types.js";
|
|
4
|
+
import type { FlowMachine } from "./createFlowMachine.js";
|
|
5
|
+
import type { FlowError } from "./errors.js";
|
|
6
|
+
/**
|
|
7
|
+
* Anonymous session for onboarding-before-signup (auth-sa.md §6). A single
|
|
8
|
+
* call; passing the same `device_id` within 60 s dedups to the same anonymous
|
|
9
|
+
* user. A later email/phone verify upgrades or merges this session.
|
|
10
|
+
*/
|
|
11
|
+
export type AnonymousState = {
|
|
12
|
+
readonly step: "idle";
|
|
13
|
+
} | {
|
|
14
|
+
readonly step: "creating";
|
|
15
|
+
} | {
|
|
16
|
+
readonly step: "authenticated";
|
|
17
|
+
readonly result: AuthResponse;
|
|
18
|
+
} | {
|
|
19
|
+
readonly step: "error";
|
|
20
|
+
readonly error: FlowError;
|
|
21
|
+
};
|
|
22
|
+
export interface AnonymousFlow {
|
|
23
|
+
readonly machine: FlowMachine<AnonymousState>;
|
|
24
|
+
create(deviceId?: string): Promise<void>;
|
|
25
|
+
reset(): void;
|
|
26
|
+
}
|
|
27
|
+
export interface AnonymousFlowDeps {
|
|
28
|
+
readonly api: AuthApi;
|
|
29
|
+
readonly analytics?: Analytics | null;
|
|
30
|
+
readonly onAuthenticated?: (result: AuthResponse) => void;
|
|
31
|
+
}
|
|
32
|
+
export declare function createAnonymousFlow(deps: AnonymousFlowDeps): AnonymousFlow;
|
|
33
|
+
//# sourceMappingURL=anonymousFlow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anonymousFlow.d.ts","sourceRoot":"","sources":["../../src/flows/anonymousFlow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C;;;;GAIG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;CAAE,GAC7B;IAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACjE;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;CAAE,CAAC;AAE1D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,cAAc,CAAC,CAAC;IAC9C,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,KAAK,IAAI,IAAI,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;CAC3D;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,GAAG,aAAa,CAyB1E"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createFlowMachine } from "./createFlowMachine.js";
|
|
2
|
+
import { toFlowError } from "./errors.js";
|
|
3
|
+
export function createAnonymousFlow(deps) {
|
|
4
|
+
const machine = createFlowMachine({
|
|
5
|
+
id: "auth.anonymous",
|
|
6
|
+
initial: { step: "idle" },
|
|
7
|
+
analytics: deps.analytics ?? null,
|
|
8
|
+
});
|
|
9
|
+
async function create(deviceId) {
|
|
10
|
+
await machine.run({ step: "creating" }, () => deps.api.anonymous(deviceId), {
|
|
11
|
+
resolve: (result) => {
|
|
12
|
+
deps.onAuthenticated?.(result);
|
|
13
|
+
return { step: "authenticated", result };
|
|
14
|
+
},
|
|
15
|
+
reject: (error) => ({
|
|
16
|
+
step: "error",
|
|
17
|
+
error: toFlowError(error),
|
|
18
|
+
}),
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
function reset() {
|
|
22
|
+
machine.to({ step: "idle" });
|
|
23
|
+
}
|
|
24
|
+
return { machine, create, reset };
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=anonymousFlow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anonymousFlow.js","sourceRoot":"","sources":["../../src/flows/anonymousFlow.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA0B1C,MAAM,UAAU,mBAAmB,CAAC,IAAuB;IACzD,MAAM,OAAO,GAAG,iBAAiB,CAAiB;QAChD,EAAE,EAAE,gBAAgB;QACpB,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;QACzB,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI;KAClC,CAAC,CAAC;IAEH,KAAK,UAAU,MAAM,CAAC,QAAiB;QACrC,MAAM,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE;YAC1E,OAAO,EAAE,CAAC,MAAM,EAAkB,EAAE;gBAClC,IAAI,CAAC,eAAe,EAAE,CAAC,MAAM,CAAC,CAAC;gBAC/B,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,CAAC;YAC3C,CAAC;YACD,MAAM,EAAE,CAAC,KAAK,EAAkB,EAAE,CAAC,CAAC;gBAClC,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC;aAC1B,CAAC;SACH,CAAC,CAAC;IACL,CAAC;IAED,SAAS,KAAK;QACZ,OAAO,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Analytics } from "@stapel/core";
|
|
2
|
+
import type { AuthApi } from "../api/authApi.js";
|
|
3
|
+
import type { AuthResponse, OtpChannel } from "../api/types.js";
|
|
4
|
+
import type { FlowMachine } from "./createFlowMachine.js";
|
|
5
|
+
import type { FlowError } from "./errors.js";
|
|
6
|
+
/**
|
|
7
|
+
* Authenticator (email/phone) change — INSTANT strategy (auth-sa.md §9). A
|
|
8
|
+
* four-hop human-wait chain proving the *old* value, then setting the *new*:
|
|
9
|
+
* request-old → verify-old (mints a `change_token`) → request-new → verify-new
|
|
10
|
+
* (→ `MODIFIED` session). The DELAYED strategy (14-day wait, no old access) is
|
|
11
|
+
* plain CRUD — use `api.changeDelayedInitiate/Status/Cancel` or the
|
|
12
|
+
* `useDelayedChangeStatus` model hook directly.
|
|
13
|
+
*/
|
|
14
|
+
export type AuthenticatorChangeState = {
|
|
15
|
+
readonly step: "idle";
|
|
16
|
+
} | {
|
|
17
|
+
readonly step: "requestingOld";
|
|
18
|
+
readonly channel: OtpChannel;
|
|
19
|
+
} | {
|
|
20
|
+
readonly step: "oldCodeSent";
|
|
21
|
+
readonly channel: OtpChannel;
|
|
22
|
+
readonly target: string;
|
|
23
|
+
} | {
|
|
24
|
+
readonly step: "verifyingOld";
|
|
25
|
+
readonly channel: OtpChannel;
|
|
26
|
+
} | {
|
|
27
|
+
readonly step: "oldVerified";
|
|
28
|
+
readonly channel: OtpChannel;
|
|
29
|
+
readonly changeToken: string;
|
|
30
|
+
} | {
|
|
31
|
+
readonly step: "requestingNew";
|
|
32
|
+
readonly channel: OtpChannel;
|
|
33
|
+
readonly changeToken: string;
|
|
34
|
+
readonly newValue: string;
|
|
35
|
+
} | {
|
|
36
|
+
readonly step: "newCodeSent";
|
|
37
|
+
readonly channel: OtpChannel;
|
|
38
|
+
readonly changeToken: string;
|
|
39
|
+
readonly newValue: string;
|
|
40
|
+
readonly target: string;
|
|
41
|
+
} | {
|
|
42
|
+
readonly step: "verifyingNew";
|
|
43
|
+
readonly channel: OtpChannel;
|
|
44
|
+
readonly changeToken: string;
|
|
45
|
+
readonly newValue: string;
|
|
46
|
+
} | {
|
|
47
|
+
readonly step: "changed";
|
|
48
|
+
readonly result: AuthResponse;
|
|
49
|
+
} | {
|
|
50
|
+
readonly step: "error";
|
|
51
|
+
readonly error: FlowError;
|
|
52
|
+
};
|
|
53
|
+
export interface AuthenticatorChangeFlow {
|
|
54
|
+
readonly machine: FlowMachine<AuthenticatorChangeState>;
|
|
55
|
+
startInstant(channel: OtpChannel): Promise<void>;
|
|
56
|
+
submitOldCode(code: string): Promise<void>;
|
|
57
|
+
requestNew(newValue: string): Promise<void>;
|
|
58
|
+
submitNewCode(code: string): Promise<void>;
|
|
59
|
+
reset(): void;
|
|
60
|
+
}
|
|
61
|
+
export interface AuthenticatorChangeFlowDeps {
|
|
62
|
+
readonly api: AuthApi;
|
|
63
|
+
readonly analytics?: Analytics | null;
|
|
64
|
+
readonly onAuthenticated?: (result: AuthResponse) => void;
|
|
65
|
+
}
|
|
66
|
+
export declare function createAuthenticatorChangeFlow(deps: AuthenticatorChangeFlowDeps): AuthenticatorChangeFlow;
|
|
67
|
+
//# sourceMappingURL=authenticatorChangeFlow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authenticatorChangeFlow.d.ts","sourceRoot":"","sources":["../../src/flows/authenticatorChangeFlow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEhE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C;;;;;;;GAOG;AACH,MAAM,MAAM,wBAAwB,GAChC;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB;IAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAA;CAAE,GAChE;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACvF;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAA;CAAE,GAC/D;IACE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GAC3D;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;CAAE,CAAC;AAE1D,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,wBAAwB,CAAC,CAAC;IACxD,YAAY,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,KAAK,IAAI,IAAI,CAAC;CACf;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;CAC3D;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,2BAA2B,GAChC,uBAAuB,CA8FzB"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { createFlowMachine } from "./createFlowMachine.js";
|
|
2
|
+
import { toFlowError } from "./errors.js";
|
|
3
|
+
export function createAuthenticatorChangeFlow(deps) {
|
|
4
|
+
const machine = createFlowMachine({
|
|
5
|
+
id: "auth.authenticator_change",
|
|
6
|
+
initial: { step: "idle" },
|
|
7
|
+
analytics: deps.analytics ?? null,
|
|
8
|
+
});
|
|
9
|
+
async function startInstant(channel) {
|
|
10
|
+
await machine.run({ step: "requestingOld", channel }, () => deps.api.changeInstantRequestOld(channel), {
|
|
11
|
+
resolve: (r) => ({
|
|
12
|
+
step: "oldCodeSent",
|
|
13
|
+
channel,
|
|
14
|
+
target: r.target,
|
|
15
|
+
}),
|
|
16
|
+
reject: (error) => ({
|
|
17
|
+
step: "error",
|
|
18
|
+
error: toFlowError(error),
|
|
19
|
+
}),
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
async function submitOldCode(code) {
|
|
23
|
+
const s = machine.getState();
|
|
24
|
+
if (s.step !== "oldCodeSent")
|
|
25
|
+
return;
|
|
26
|
+
const { channel } = s;
|
|
27
|
+
await machine.run({ step: "verifyingOld", channel }, () => deps.api.changeInstantVerifyOld(channel, code), {
|
|
28
|
+
resolve: (r) => ({
|
|
29
|
+
step: "oldVerified",
|
|
30
|
+
channel,
|
|
31
|
+
changeToken: r.change_token,
|
|
32
|
+
}),
|
|
33
|
+
reject: (error) => ({
|
|
34
|
+
step: "error",
|
|
35
|
+
error: toFlowError(error),
|
|
36
|
+
}),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
async function requestNew(newValue) {
|
|
40
|
+
const s = machine.getState();
|
|
41
|
+
if (s.step !== "oldVerified")
|
|
42
|
+
return;
|
|
43
|
+
const { channel, changeToken } = s;
|
|
44
|
+
await machine.run({ step: "requestingNew", channel, changeToken, newValue }, () => deps.api.changeInstantRequestNew(channel, newValue, changeToken), {
|
|
45
|
+
resolve: (r) => ({
|
|
46
|
+
step: "newCodeSent",
|
|
47
|
+
channel,
|
|
48
|
+
changeToken,
|
|
49
|
+
newValue,
|
|
50
|
+
target: r.target,
|
|
51
|
+
}),
|
|
52
|
+
reject: (error) => ({
|
|
53
|
+
step: "error",
|
|
54
|
+
error: toFlowError(error),
|
|
55
|
+
}),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
async function submitNewCode(code) {
|
|
59
|
+
const s = machine.getState();
|
|
60
|
+
if (s.step !== "newCodeSent")
|
|
61
|
+
return;
|
|
62
|
+
const { channel, changeToken, newValue } = s;
|
|
63
|
+
await machine.run({ step: "verifyingNew", channel, changeToken, newValue }, () => deps.api.changeInstantVerifyNew(channel, newValue, code, changeToken), {
|
|
64
|
+
resolve: (result) => {
|
|
65
|
+
deps.onAuthenticated?.(result);
|
|
66
|
+
return { step: "changed", result };
|
|
67
|
+
},
|
|
68
|
+
reject: (error) => ({
|
|
69
|
+
step: "error",
|
|
70
|
+
error: toFlowError(error),
|
|
71
|
+
}),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function reset() {
|
|
75
|
+
machine.to({ step: "idle" });
|
|
76
|
+
}
|
|
77
|
+
return { machine, startInstant, submitOldCode, requestNew, submitNewCode, reset };
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=authenticatorChangeFlow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authenticatorChangeFlow.js","sourceRoot":"","sources":["../../src/flows/authenticatorChangeFlow.ts"],"names":[],"mappings":"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"}
|