@stackframe/stack 2.6.12 → 2.6.15
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 +28 -0
- package/dist/components/passkey-button.d.mts +7 -0
- package/dist/components/passkey-button.d.ts +7 -0
- package/dist/components/passkey-button.js +58 -0
- package/dist/components/passkey-button.js.map +1 -0
- package/dist/components-page/account-settings.js +58 -1
- package/dist/components-page/account-settings.js.map +1 -1
- package/dist/components-page/auth-page.d.mts +1 -0
- package/dist/components-page/auth-page.d.ts +1 -0
- package/dist/components-page/auth-page.js +5 -1
- package/dist/components-page/auth-page.js.map +1 -1
- package/dist/esm/components/passkey-button.js +34 -0
- package/dist/esm/components/passkey-button.js.map +1 -0
- package/dist/esm/components-page/account-settings.js +58 -1
- package/dist/esm/components-page/account-settings.js.map +1 -1
- package/dist/esm/components-page/auth-page.js +5 -1
- package/dist/esm/components-page/auth-page.js.map +1 -1
- package/dist/esm/generated/quetzal-translations.js +2244 -2124
- package/dist/esm/generated/quetzal-translations.js.map +1 -1
- package/dist/esm/lib/stack-app.js +67 -4
- package/dist/esm/lib/stack-app.js.map +1 -1
- package/dist/generated/quetzal-translations.d.mts +2 -2
- package/dist/generated/quetzal-translations.d.ts +2 -2
- package/dist/generated/quetzal-translations.js +2244 -2124
- package/dist/generated/quetzal-translations.js.map +1 -1
- package/dist/lib/stack-app.d.mts +9 -2
- package/dist/lib/stack-app.d.ts +9 -2
- package/dist/lib/stack-app.js +67 -4
- package/dist/lib/stack-app.js.map +1 -1
- package/package.json +5 -4
package/dist/lib/stack-app.d.mts
CHANGED
|
@@ -176,6 +176,7 @@ type Auth = {
|
|
|
176
176
|
accessToken: string | null;
|
|
177
177
|
refreshToken: string | null;
|
|
178
178
|
}>;
|
|
179
|
+
registerPasskey(): Promise<Result<undefined, KnownErrors["PasskeyRegistrationFailed"] | KnownErrors["PasskeyWebAuthnError"]>>;
|
|
179
180
|
};
|
|
180
181
|
/**
|
|
181
182
|
* ```
|
|
@@ -218,6 +219,7 @@ type BaseUser = {
|
|
|
218
219
|
*/
|
|
219
220
|
readonly hasPassword: boolean;
|
|
220
221
|
readonly otpAuthEnabled: boolean;
|
|
222
|
+
readonly passkeyAuthEnabled: boolean;
|
|
221
223
|
readonly isMultiFactorRequired: boolean;
|
|
222
224
|
/**
|
|
223
225
|
* A shorthand method to update multiple fields of the user at once.
|
|
@@ -297,6 +299,7 @@ type UserUpdateOptions = {
|
|
|
297
299
|
totpMultiFactorSecret?: Uint8Array | null;
|
|
298
300
|
profileImageUrl?: string | null;
|
|
299
301
|
otpAuthEnabled?: boolean;
|
|
302
|
+
passkeyAuthEnabled?: boolean;
|
|
300
303
|
};
|
|
301
304
|
type ServerBaseUser = {
|
|
302
305
|
setPrimaryEmail(email: string, options?: {
|
|
@@ -380,6 +383,7 @@ type ProjectConfig = {
|
|
|
380
383
|
readonly signUpEnabled: boolean;
|
|
381
384
|
readonly credentialEnabled: boolean;
|
|
382
385
|
readonly magicLinkEnabled: boolean;
|
|
386
|
+
readonly passkeyEnabled: boolean;
|
|
383
387
|
readonly clientTeamCreationEnabled: boolean;
|
|
384
388
|
readonly clientUserDeletionEnabled: boolean;
|
|
385
389
|
readonly oauthProviders: OAuthProviderConfig[];
|
|
@@ -392,6 +396,7 @@ type AdminProjectConfig = {
|
|
|
392
396
|
readonly signUpEnabled: boolean;
|
|
393
397
|
readonly credentialEnabled: boolean;
|
|
394
398
|
readonly magicLinkEnabled: boolean;
|
|
399
|
+
readonly passkeyEnabled: boolean;
|
|
395
400
|
readonly clientTeamCreationEnabled: boolean;
|
|
396
401
|
readonly clientUserDeletionEnabled: boolean;
|
|
397
402
|
readonly legacyGlobalJwtSigning: boolean;
|
|
@@ -439,6 +444,7 @@ type AdminProjectConfigUpdateOptions = {
|
|
|
439
444
|
signUpEnabled?: boolean;
|
|
440
445
|
credentialEnabled?: boolean;
|
|
441
446
|
magicLinkEnabled?: boolean;
|
|
447
|
+
passkeyEnabled?: boolean;
|
|
442
448
|
clientTeamCreationEnabled?: boolean;
|
|
443
449
|
clientUserDeletionEnabled?: boolean;
|
|
444
450
|
allowLocalhost?: boolean;
|
|
@@ -509,7 +515,7 @@ type Team = {
|
|
|
509
515
|
clientReadOnlyMetadata: any;
|
|
510
516
|
inviteUser(options: {
|
|
511
517
|
email: string;
|
|
512
|
-
}): Promise<
|
|
518
|
+
}): Promise<void>;
|
|
513
519
|
listUsers(): Promise<TeamUser[]>;
|
|
514
520
|
useUsers(): TeamUser[];
|
|
515
521
|
update(update: TeamUpdateOptions): Promise<void>;
|
|
@@ -537,7 +543,7 @@ type ServerTeam = {
|
|
|
537
543
|
addUser(userId: string): Promise<void>;
|
|
538
544
|
inviteUser(options: {
|
|
539
545
|
email: string;
|
|
540
|
-
}): Promise<
|
|
546
|
+
}): Promise<void>;
|
|
541
547
|
removeUser(userId: string): Promise<void>;
|
|
542
548
|
} & Team;
|
|
543
549
|
type ServerTeamCreateOptions = TeamCreateOptions;
|
|
@@ -600,6 +606,7 @@ type StackClientApp<HasTokenStore extends boolean = boolean, ProjectId extends s
|
|
|
600
606
|
password: string;
|
|
601
607
|
noRedirect?: boolean;
|
|
602
608
|
}): Promise<Result<undefined, KnownErrors["UserEmailAlreadyExists"] | KnownErrors["PasswordRequirementsNotMet"]>>;
|
|
609
|
+
signInWithPasskey(): Promise<Result<undefined, KnownErrors["PasskeyAuthenticationFailed"] | KnownErrors["InvalidTotpCode"] | KnownErrors["PasskeyWebAuthnError"]>>;
|
|
603
610
|
callOAuthCallback(): Promise<boolean>;
|
|
604
611
|
sendForgotPasswordEmail(email: string): Promise<Result<undefined, KnownErrors["UserNotFound"]>>;
|
|
605
612
|
sendMagicLinkEmail(email: string): Promise<Result<{
|
package/dist/lib/stack-app.d.ts
CHANGED
|
@@ -176,6 +176,7 @@ type Auth = {
|
|
|
176
176
|
accessToken: string | null;
|
|
177
177
|
refreshToken: string | null;
|
|
178
178
|
}>;
|
|
179
|
+
registerPasskey(): Promise<Result<undefined, KnownErrors["PasskeyRegistrationFailed"] | KnownErrors["PasskeyWebAuthnError"]>>;
|
|
179
180
|
};
|
|
180
181
|
/**
|
|
181
182
|
* ```
|
|
@@ -218,6 +219,7 @@ type BaseUser = {
|
|
|
218
219
|
*/
|
|
219
220
|
readonly hasPassword: boolean;
|
|
220
221
|
readonly otpAuthEnabled: boolean;
|
|
222
|
+
readonly passkeyAuthEnabled: boolean;
|
|
221
223
|
readonly isMultiFactorRequired: boolean;
|
|
222
224
|
/**
|
|
223
225
|
* A shorthand method to update multiple fields of the user at once.
|
|
@@ -297,6 +299,7 @@ type UserUpdateOptions = {
|
|
|
297
299
|
totpMultiFactorSecret?: Uint8Array | null;
|
|
298
300
|
profileImageUrl?: string | null;
|
|
299
301
|
otpAuthEnabled?: boolean;
|
|
302
|
+
passkeyAuthEnabled?: boolean;
|
|
300
303
|
};
|
|
301
304
|
type ServerBaseUser = {
|
|
302
305
|
setPrimaryEmail(email: string, options?: {
|
|
@@ -380,6 +383,7 @@ type ProjectConfig = {
|
|
|
380
383
|
readonly signUpEnabled: boolean;
|
|
381
384
|
readonly credentialEnabled: boolean;
|
|
382
385
|
readonly magicLinkEnabled: boolean;
|
|
386
|
+
readonly passkeyEnabled: boolean;
|
|
383
387
|
readonly clientTeamCreationEnabled: boolean;
|
|
384
388
|
readonly clientUserDeletionEnabled: boolean;
|
|
385
389
|
readonly oauthProviders: OAuthProviderConfig[];
|
|
@@ -392,6 +396,7 @@ type AdminProjectConfig = {
|
|
|
392
396
|
readonly signUpEnabled: boolean;
|
|
393
397
|
readonly credentialEnabled: boolean;
|
|
394
398
|
readonly magicLinkEnabled: boolean;
|
|
399
|
+
readonly passkeyEnabled: boolean;
|
|
395
400
|
readonly clientTeamCreationEnabled: boolean;
|
|
396
401
|
readonly clientUserDeletionEnabled: boolean;
|
|
397
402
|
readonly legacyGlobalJwtSigning: boolean;
|
|
@@ -439,6 +444,7 @@ type AdminProjectConfigUpdateOptions = {
|
|
|
439
444
|
signUpEnabled?: boolean;
|
|
440
445
|
credentialEnabled?: boolean;
|
|
441
446
|
magicLinkEnabled?: boolean;
|
|
447
|
+
passkeyEnabled?: boolean;
|
|
442
448
|
clientTeamCreationEnabled?: boolean;
|
|
443
449
|
clientUserDeletionEnabled?: boolean;
|
|
444
450
|
allowLocalhost?: boolean;
|
|
@@ -509,7 +515,7 @@ type Team = {
|
|
|
509
515
|
clientReadOnlyMetadata: any;
|
|
510
516
|
inviteUser(options: {
|
|
511
517
|
email: string;
|
|
512
|
-
}): Promise<
|
|
518
|
+
}): Promise<void>;
|
|
513
519
|
listUsers(): Promise<TeamUser[]>;
|
|
514
520
|
useUsers(): TeamUser[];
|
|
515
521
|
update(update: TeamUpdateOptions): Promise<void>;
|
|
@@ -537,7 +543,7 @@ type ServerTeam = {
|
|
|
537
543
|
addUser(userId: string): Promise<void>;
|
|
538
544
|
inviteUser(options: {
|
|
539
545
|
email: string;
|
|
540
|
-
}): Promise<
|
|
546
|
+
}): Promise<void>;
|
|
541
547
|
removeUser(userId: string): Promise<void>;
|
|
542
548
|
} & Team;
|
|
543
549
|
type ServerTeamCreateOptions = TeamCreateOptions;
|
|
@@ -600,6 +606,7 @@ type StackClientApp<HasTokenStore extends boolean = boolean, ProjectId extends s
|
|
|
600
606
|
password: string;
|
|
601
607
|
noRedirect?: boolean;
|
|
602
608
|
}): Promise<Result<undefined, KnownErrors["UserEmailAlreadyExists"] | KnownErrors["PasswordRequirementsNotMet"]>>;
|
|
609
|
+
signInWithPasskey(): Promise<Result<undefined, KnownErrors["PasskeyAuthenticationFailed"] | KnownErrors["InvalidTotpCode"] | KnownErrors["PasskeyWebAuthnError"]>>;
|
|
603
610
|
callOAuthCallback(): Promise<boolean>;
|
|
604
611
|
sendForgotPasswordEmail(email: string): Promise<Result<undefined, KnownErrors["UserNotFound"]>>;
|
|
605
612
|
sendMagicLinkEmail(email: string): Promise<Result<{
|
package/dist/lib/stack-app.js
CHANGED
|
@@ -38,6 +38,7 @@ __export(stack_app_exports, {
|
|
|
38
38
|
stackAppInternalsSymbol: () => stackAppInternalsSymbol
|
|
39
39
|
});
|
|
40
40
|
module.exports = __toCommonJS(stack_app_exports);
|
|
41
|
+
var import_browser = require("@simplewebauthn/browser");
|
|
41
42
|
var import_stack_sc = require("@stackframe/stack-sc");
|
|
42
43
|
var import_stack_shared = require("@stackframe/stack-shared");
|
|
43
44
|
var import_production_mode = require("@stackframe/stack-shared/dist/helpers/production-mode");
|
|
@@ -63,7 +64,7 @@ var import_url = require("../utils/url");
|
|
|
63
64
|
var import_auth = require("./auth");
|
|
64
65
|
var import_cookie = require("./cookie");
|
|
65
66
|
var NextNavigation = (0, import_compile_time.scrambleDuringCompileTime)(NextNavigationUnscrambled);
|
|
66
|
-
var clientVersion = "js @stackframe/stack@2.6.
|
|
67
|
+
var clientVersion = "js @stackframe/stack@2.6.15";
|
|
67
68
|
function getUrls(partial) {
|
|
68
69
|
const handler = partial.handler ?? "/handler";
|
|
69
70
|
const home = partial.home ?? "/";
|
|
@@ -542,6 +543,7 @@ var _StackClientAppImpl = class __StackClientAppImpl {
|
|
|
542
543
|
signUpEnabled: crud.config.sign_up_enabled,
|
|
543
544
|
credentialEnabled: crud.config.credential_enabled,
|
|
544
545
|
magicLinkEnabled: crud.config.magic_link_enabled,
|
|
546
|
+
passkeyEnabled: crud.config.passkey_enabled,
|
|
545
547
|
clientTeamCreationEnabled: crud.config.client_team_creation_enabled,
|
|
546
548
|
clientUserDeletionEnabled: crud.config.client_user_deletion_enabled,
|
|
547
549
|
oauthProviders: crud.config.enabled_oauth_providers.map((p) => ({
|
|
@@ -573,7 +575,7 @@ var _StackClientAppImpl = class __StackClientAppImpl {
|
|
|
573
575
|
clientMetadata: crud.client_metadata,
|
|
574
576
|
clientReadOnlyMetadata: crud.client_read_only_metadata,
|
|
575
577
|
async inviteUser(options) {
|
|
576
|
-
|
|
578
|
+
await app._interface.sendTeamInvitation({
|
|
577
579
|
teamId: crud.id,
|
|
578
580
|
email: options.email,
|
|
579
581
|
session: app._getSession(),
|
|
@@ -638,6 +640,31 @@ var _StackClientAppImpl = class __StackClientAppImpl {
|
|
|
638
640
|
const tokens = await this.currentSession.getTokens();
|
|
639
641
|
return tokens;
|
|
640
642
|
},
|
|
643
|
+
async registerPasskey() {
|
|
644
|
+
const initiationResult = await app._interface.initiatePasskeyRegistration({}, session);
|
|
645
|
+
if (initiationResult.status !== "ok") {
|
|
646
|
+
return import_results.Result.error(new import_stack_shared.KnownErrors.PasskeyRegistrationFailed("Failed to get initiation options for passkey registration"));
|
|
647
|
+
}
|
|
648
|
+
const { options_json, code } = initiationResult.data;
|
|
649
|
+
if (options_json.rp.id !== "THIS_VALUE_WILL_BE_REPLACED.example.com") {
|
|
650
|
+
throw new import_errors.StackAssertionError(`Expected returned RP ID from server to equal sentinel, but found ${options_json.rp.id}`);
|
|
651
|
+
}
|
|
652
|
+
options_json.rp.id = window.location.hostname;
|
|
653
|
+
let attResp;
|
|
654
|
+
try {
|
|
655
|
+
attResp = await (0, import_browser.startRegistration)({ optionsJSON: options_json });
|
|
656
|
+
debugger;
|
|
657
|
+
} catch (error) {
|
|
658
|
+
if (error instanceof import_browser.WebAuthnError) {
|
|
659
|
+
return import_results.Result.error(new import_stack_shared.KnownErrors.PasskeyWebAuthnError(error.message, error.name));
|
|
660
|
+
} else {
|
|
661
|
+
return import_results.Result.error(new import_stack_shared.KnownErrors.PasskeyRegistrationFailed("Failed to start passkey registration"));
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
const registrationResult = await app._interface.registerPasskey({ credential: attResp, code }, session);
|
|
665
|
+
await app._refreshUser(session);
|
|
666
|
+
return registrationResult;
|
|
667
|
+
},
|
|
641
668
|
signOut() {
|
|
642
669
|
return app._signOut(session);
|
|
643
670
|
}
|
|
@@ -660,6 +687,7 @@ var _StackClientAppImpl = class __StackClientAppImpl {
|
|
|
660
687
|
emailAuthEnabled: crud.auth_with_email,
|
|
661
688
|
otpAuthEnabled: crud.otp_auth_enabled,
|
|
662
689
|
oauthProviders: crud.oauth_providers,
|
|
690
|
+
passkeyAuthEnabled: crud.passkey_auth_enabled,
|
|
663
691
|
selectedTeam: crud.selected_team && this._clientTeamFromCrud(crud.selected_team),
|
|
664
692
|
isMultiFactorRequired: crud.requires_totp_mfa,
|
|
665
693
|
toClientJson() {
|
|
@@ -1146,6 +1174,38 @@ var _StackClientAppImpl = class __StackClientAppImpl {
|
|
|
1146
1174
|
return import_results.Result.error(result.error);
|
|
1147
1175
|
}
|
|
1148
1176
|
}
|
|
1177
|
+
async signInWithPasskey() {
|
|
1178
|
+
this._ensurePersistentTokenStore();
|
|
1179
|
+
let result;
|
|
1180
|
+
try {
|
|
1181
|
+
result = await this._catchMfaRequiredError(async () => {
|
|
1182
|
+
const initiationResult = await this._interface.initiatePasskeyAuthentication({}, this._getSession());
|
|
1183
|
+
if (initiationResult.status !== "ok") {
|
|
1184
|
+
return import_results.Result.error(new import_stack_shared.KnownErrors.PasskeyAuthenticationFailed("Failed to get initiation options for passkey authentication"));
|
|
1185
|
+
}
|
|
1186
|
+
const { options_json, code } = initiationResult.data;
|
|
1187
|
+
if (options_json.rpId !== "THIS_VALUE_WILL_BE_REPLACED.example.com") {
|
|
1188
|
+
throw new import_errors.StackAssertionError(`Expected returned RP ID from server to equal sentinel, but found ${options_json.rpId}`);
|
|
1189
|
+
}
|
|
1190
|
+
options_json.rpId = window.location.hostname;
|
|
1191
|
+
const authentication_response = await (0, import_browser.startAuthentication)({ optionsJSON: options_json });
|
|
1192
|
+
return await this._interface.signInWithPasskey({ authentication_response, code });
|
|
1193
|
+
});
|
|
1194
|
+
} catch (error) {
|
|
1195
|
+
if (error instanceof import_browser.WebAuthnError) {
|
|
1196
|
+
return import_results.Result.error(new import_stack_shared.KnownErrors.PasskeyWebAuthnError(error.message, error.name));
|
|
1197
|
+
} else {
|
|
1198
|
+
return import_results.Result.error(new import_stack_shared.KnownErrors.PasskeyAuthenticationFailed("Failed to sign in with passkey"));
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
if (result.status === "ok") {
|
|
1202
|
+
await this._signInToAccountWithTokens(result.data);
|
|
1203
|
+
await this.redirectToAfterSignIn({ replace: true });
|
|
1204
|
+
return import_results.Result.ok(void 0);
|
|
1205
|
+
} else {
|
|
1206
|
+
return import_results.Result.error(result.error);
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1149
1209
|
async callOAuthCallback() {
|
|
1150
1210
|
this._ensurePersistentTokenStore();
|
|
1151
1211
|
let result;
|
|
@@ -1596,7 +1656,7 @@ var _StackServerAppImpl = class extends _StackClientAppImpl {
|
|
|
1596
1656
|
await app._serverTeamMemberProfilesCache.refresh([crud.id]);
|
|
1597
1657
|
},
|
|
1598
1658
|
async inviteUser(options) {
|
|
1599
|
-
|
|
1659
|
+
await app._interface.sendTeamInvitation({
|
|
1600
1660
|
teamId: crud.id,
|
|
1601
1661
|
email: options.email,
|
|
1602
1662
|
session: null,
|
|
@@ -1800,6 +1860,7 @@ var _StackAdminAppImpl = class extends _StackServerAppImpl {
|
|
|
1800
1860
|
signUpEnabled: data.config.sign_up_enabled,
|
|
1801
1861
|
credentialEnabled: data.config.credential_enabled,
|
|
1802
1862
|
magicLinkEnabled: data.config.magic_link_enabled,
|
|
1863
|
+
passkeyEnabled: data.config.passkey_enabled,
|
|
1803
1864
|
legacyGlobalJwtSigning: data.config.legacy_global_jwt_signing,
|
|
1804
1865
|
clientTeamCreationEnabled: data.config.client_team_creation_enabled,
|
|
1805
1866
|
clientUserDeletionEnabled: data.config.client_user_deletion_enabled,
|
|
@@ -2019,7 +2080,8 @@ function userUpdateOptionsToCrud(options) {
|
|
|
2019
2080
|
selected_team_id: options.selectedTeamId,
|
|
2020
2081
|
totp_secret_base64: options.totpMultiFactorSecret != null ? (0, import_bytes.encodeBase64)(options.totpMultiFactorSecret) : options.totpMultiFactorSecret,
|
|
2021
2082
|
profile_image_url: options.profileImageUrl,
|
|
2022
|
-
otp_auth_enabled: options.otpAuthEnabled
|
|
2083
|
+
otp_auth_enabled: options.otpAuthEnabled,
|
|
2084
|
+
passkey_auth_enabled: options.passkeyAuthEnabled
|
|
2023
2085
|
};
|
|
2024
2086
|
}
|
|
2025
2087
|
function serverUserUpdateOptionsToCrud(options) {
|
|
@@ -2082,6 +2144,7 @@ function adminProjectUpdateOptionsToCrud(options) {
|
|
|
2082
2144
|
sign_up_enabled: options.config?.signUpEnabled,
|
|
2083
2145
|
credential_enabled: options.config?.credentialEnabled,
|
|
2084
2146
|
magic_link_enabled: options.config?.magicLinkEnabled,
|
|
2147
|
+
passkey_enabled: options.config?.passkeyEnabled,
|
|
2085
2148
|
allow_localhost: options.config?.allowLocalhost,
|
|
2086
2149
|
create_team_on_sign_up: options.config?.createTeamOnSignUp,
|
|
2087
2150
|
client_team_creation_enabled: options.config?.clientTeamCreationEnabled,
|