@auth0/auth0-server-js 1.15.0 → 1.16.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/README.md +38 -0
- package/dist/index.cjs +501 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +519 -59
- package/dist/index.d.ts +519 -59
- package/dist/index.js +479 -7
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -20,28 +20,34 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
AbstractAnonymousStore: () => AbstractAnonymousStore,
|
|
23
24
|
AbstractStateStore: () => AbstractStateStore,
|
|
24
25
|
AbstractTransactionStore: () => AbstractTransactionStore,
|
|
26
|
+
AnonymousSessionError: () => import_auth0_auth_js6.AnonymousSessionError,
|
|
27
|
+
AnonymousSessionExpiredError: () => AnonymousSessionExpiredError,
|
|
25
28
|
BackchannelLogoutError: () => BackchannelLogoutError,
|
|
26
29
|
ChangePasswordError: () => import_auth0_auth_js5.ChangePasswordError,
|
|
27
30
|
CookieTransactionStore: () => CookieTransactionStore,
|
|
28
|
-
|
|
31
|
+
DEFAULT_ANONYMOUS_SESSION_LIFETIME: () => DEFAULT_ANONYMOUS_SESSION_LIFETIME,
|
|
32
|
+
EnterpriseConnectNotSupportedError: () => import_auth0_auth_js7.EnterpriseConnectNotSupportedError,
|
|
29
33
|
InvalidConfigurationError: () => InvalidConfigurationError,
|
|
30
34
|
IssuerValidationError: () => IssuerValidationError,
|
|
31
35
|
MfaChallengeError: () => import_auth0_auth_js3.MfaChallengeError,
|
|
32
36
|
MfaEnrollmentError: () => import_auth0_auth_js3.MfaEnrollmentError,
|
|
33
37
|
MfaListAuthenticatorsError: () => import_auth0_auth_js3.MfaListAuthenticatorsError,
|
|
34
38
|
MfaVerifyError: () => import_auth0_auth_js3.MfaVerifyError,
|
|
35
|
-
|
|
39
|
+
MissingAnonymousSessionError: () => MissingAnonymousSessionError,
|
|
40
|
+
MissingClientAuthError: () => import_auth0_auth_js7.MissingClientAuthError,
|
|
36
41
|
MissingRequiredArgumentError: () => MissingRequiredArgumentError,
|
|
37
42
|
MissingSessionError: () => MissingSessionError,
|
|
38
43
|
MissingTransactionError: () => MissingTransactionError,
|
|
39
|
-
OrganizationValidationError: () =>
|
|
44
|
+
OrganizationValidationError: () => import_auth0_auth_js7.OrganizationValidationError,
|
|
40
45
|
PasskeyChallengeError: () => import_auth0_auth_js4.PasskeyChallengeError,
|
|
41
46
|
PasskeyGetTokenError: () => import_auth0_auth_js4.PasskeyGetTokenError,
|
|
42
47
|
PasskeyRegisterError: () => import_auth0_auth_js4.PasskeyRegisterError,
|
|
43
|
-
PasswordlessStartError: () =>
|
|
44
|
-
PasswordlessVerifyError: () =>
|
|
48
|
+
PasswordlessStartError: () => import_auth0_auth_js7.PasswordlessStartError,
|
|
49
|
+
PasswordlessVerifyError: () => import_auth0_auth_js7.PasswordlessVerifyError,
|
|
50
|
+
ServerAnonymousClient: () => ServerAnonymousClient,
|
|
45
51
|
ServerClient: () => ServerClient,
|
|
46
52
|
ServerDatabaseClient: () => ServerDatabaseClient,
|
|
47
53
|
ServerMfaClient: () => ServerMfaClient,
|
|
@@ -50,13 +56,14 @@ __export(index_exports, {
|
|
|
50
56
|
SignUpError: () => import_auth0_auth_js5.SignUpError,
|
|
51
57
|
StartLinkUserError: () => StartLinkUserError,
|
|
52
58
|
StatefulStateStore: () => StatefulStateStore,
|
|
59
|
+
StatelessAnonymousStore: () => StatelessAnonymousStore,
|
|
53
60
|
StatelessStateStore: () => StatelessStateStore,
|
|
54
|
-
TokenExchangeError: () =>
|
|
61
|
+
TokenExchangeError: () => import_auth0_auth_js7.TokenExchangeError,
|
|
55
62
|
TokenExchangeErrorCode: () => TokenExchangeErrorCode,
|
|
56
|
-
TokenRevocationError: () =>
|
|
57
|
-
UserInfoError: () =>
|
|
58
|
-
isFederatedDomain: () =>
|
|
59
|
-
isMfaRequiredError: () =>
|
|
63
|
+
TokenRevocationError: () => import_auth0_auth_js7.TokenRevocationError,
|
|
64
|
+
UserInfoError: () => import_auth0_auth_js7.UserInfoError,
|
|
65
|
+
isFederatedDomain: () => import_auth0_auth_js7.isFederatedDomain,
|
|
66
|
+
isMfaRequiredError: () => import_auth0_auth_js7.isMfaRequiredError
|
|
60
67
|
});
|
|
61
68
|
module.exports = __toCommonJS(index_exports);
|
|
62
69
|
|
|
@@ -115,6 +122,22 @@ var IssuerValidationError = class extends Error {
|
|
|
115
122
|
this.name = "IssuerValidationError";
|
|
116
123
|
}
|
|
117
124
|
};
|
|
125
|
+
var MissingAnonymousSessionError = class extends Error {
|
|
126
|
+
code = "missing_anonymous_session_error";
|
|
127
|
+
constructor(message) {
|
|
128
|
+
super(message ?? "There is no anonymous session. Call `anonymous.createSession()` first.");
|
|
129
|
+
this.name = "MissingAnonymousSessionError";
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
var AnonymousSessionExpiredError = class extends Error {
|
|
133
|
+
code = "anonymous_session_expired";
|
|
134
|
+
constructor(message) {
|
|
135
|
+
super(
|
|
136
|
+
message ?? "The anonymous session has expired or is no longer valid. Call `anonymous.createSession()` to start a new one."
|
|
137
|
+
);
|
|
138
|
+
this.name = "AnonymousSessionExpiredError";
|
|
139
|
+
}
|
|
140
|
+
};
|
|
118
141
|
var SessionExpiredError = class extends Error {
|
|
119
142
|
code = "session_expired";
|
|
120
143
|
constructor(message) {
|
|
@@ -255,7 +278,7 @@ var compareScopes = (scopes, requiredScopes) => {
|
|
|
255
278
|
};
|
|
256
279
|
|
|
257
280
|
// src/server-client.ts
|
|
258
|
-
var
|
|
281
|
+
var import_jose2 = require("jose");
|
|
259
282
|
|
|
260
283
|
// src/telemetry.ts
|
|
261
284
|
function getTelemetryConfig(config) {
|
|
@@ -265,7 +288,7 @@ function getTelemetryConfig(config) {
|
|
|
265
288
|
return {
|
|
266
289
|
enabled: true,
|
|
267
290
|
name: config?.name ?? "@auth0/auth0-server-js",
|
|
268
|
-
version: config?.version ?? "1.
|
|
291
|
+
version: config?.version ?? "1.16.0"
|
|
269
292
|
};
|
|
270
293
|
}
|
|
271
294
|
|
|
@@ -339,6 +362,7 @@ var ServerMfaClient = class {
|
|
|
339
362
|
true,
|
|
340
363
|
storeOptions
|
|
341
364
|
);
|
|
365
|
+
await this.#options.onUserSessionEstablished?.(storeOptions);
|
|
342
366
|
const result = {
|
|
343
367
|
accessToken: tokenResponse.accessToken,
|
|
344
368
|
tokenType: tokenResponse.tokenType ?? "bearer",
|
|
@@ -447,6 +471,7 @@ var ServerPasskeyClient = class {
|
|
|
447
471
|
const existingStateData = await this.#options.stateStore.get(this.#options.stateStoreIdentifier, storeOptions);
|
|
448
472
|
const stateData = updateStateData(audience ?? "default", existingStateData, tokenEndpointResponse, { domain });
|
|
449
473
|
await this.#options.stateStore.set(this.#options.stateStoreIdentifier, stateData, true, storeOptions);
|
|
474
|
+
await this.#options.onUserSessionEstablished?.(storeOptions);
|
|
450
475
|
return {
|
|
451
476
|
authorizationDetails: tokenEndpointResponse.authorizationDetails
|
|
452
477
|
};
|
|
@@ -541,6 +566,225 @@ function applyEnterpriseConnectRestrictions(instance) {
|
|
|
541
566
|
}
|
|
542
567
|
}
|
|
543
568
|
|
|
569
|
+
// src/anonymous/server-anonymous-client.ts
|
|
570
|
+
var import_jose = require("jose");
|
|
571
|
+
var DEFAULT_AUDIENCE_CACHE_KEY = "default";
|
|
572
|
+
var readAnonymousSub = (accessToken) => {
|
|
573
|
+
try {
|
|
574
|
+
const { sub } = (0, import_jose.decodeJwt)(accessToken);
|
|
575
|
+
return typeof sub === "string" ? sub : void 0;
|
|
576
|
+
} catch {
|
|
577
|
+
return void 0;
|
|
578
|
+
}
|
|
579
|
+
};
|
|
580
|
+
var cacheKeyScope = (tokenSet) => tokenSet.requestedScope ?? tokenSet.scope;
|
|
581
|
+
var upsertTokenSet = (tokenSets, tokenSet) => {
|
|
582
|
+
const matches = (candidate) => candidate.audience === tokenSet.audience && cacheKeyScope(candidate) === cacheKeyScope(tokenSet);
|
|
583
|
+
return tokenSets.some(matches) ? tokenSets.map((candidate) => matches(candidate) ? tokenSet : candidate) : [...tokenSets, tokenSet];
|
|
584
|
+
};
|
|
585
|
+
var ServerAnonymousClient = class {
|
|
586
|
+
#options;
|
|
587
|
+
/**
|
|
588
|
+
* @internal
|
|
589
|
+
*/
|
|
590
|
+
constructor(options) {
|
|
591
|
+
this.#options = options;
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Creates an anonymous session and stores it, returning the first anonymous access token.
|
|
595
|
+
*
|
|
596
|
+
* Replaces any anonymous session already stored for this visitor. Metadata can only be
|
|
597
|
+
* attached here, because Auth0 rejects a request that carries both metadata and an
|
|
598
|
+
* existing session.
|
|
599
|
+
*
|
|
600
|
+
* The anonymous identity (`sub`) is read off the first access token and stored alongside
|
|
601
|
+
* the metadata, so {@link ServerAnonymousClient.getSession} can hand both back without the
|
|
602
|
+
* application decoding a token. It stays `undefined` for an audience with token encryption
|
|
603
|
+
* (`token_encryption`) enabled, whose access token is an encrypted JWE only the API can
|
|
604
|
+
* read.
|
|
605
|
+
*
|
|
606
|
+
* @param options Optional audience, scope and metadata for the new session.
|
|
607
|
+
* @param storeOptions Optional options used to pass to the anonymous store (and to resolve the domain in resolver mode).
|
|
608
|
+
*
|
|
609
|
+
* @throws {AnonymousSessionError} If Auth0 rejected the request. Common codes are
|
|
610
|
+
* `feature_not_enabled` (the tenant flag is off), `unauthorized_client` (the client is
|
|
611
|
+
* not enabled for anonymous sessions), `invalid_target` (the resource server does not
|
|
612
|
+
* allow anonymous access), `invalid_request` (metadata over 1024 bytes, or not all
|
|
613
|
+
* strings) and `access_denied`. `code` is `server_error` when Auth0 answers with a body
|
|
614
|
+
* that is not JSON.
|
|
615
|
+
*
|
|
616
|
+
* Only call this once you have established the visitor has no anonymous session (check
|
|
617
|
+
* {@link ServerAnonymousClient.getSession} first), rather than on every request.
|
|
618
|
+
*
|
|
619
|
+
* @returns The anonymous access token for the requested audience.
|
|
620
|
+
*/
|
|
621
|
+
async createSession(options, storeOptions) {
|
|
622
|
+
const domain = await this.#options.resolveDomain(storeOptions);
|
|
623
|
+
const requestedAudience = options?.audience ?? this.#options.defaultAudience;
|
|
624
|
+
const audience = requestedAudience ?? DEFAULT_AUDIENCE_CACHE_KEY;
|
|
625
|
+
const scope = options?.scope;
|
|
626
|
+
const session = await this.#options.getAuthClient(domain).anonymous.createSession({
|
|
627
|
+
...requestedAudience && { audience: requestedAudience },
|
|
628
|
+
...scope && { scope },
|
|
629
|
+
...options?.metadata && { metadata: options.metadata }
|
|
630
|
+
});
|
|
631
|
+
const tokenSet = {
|
|
632
|
+
audience,
|
|
633
|
+
accessToken: session.accessToken,
|
|
634
|
+
scope: session.scope,
|
|
635
|
+
...scope && scope !== session.scope && { requestedScope: scope },
|
|
636
|
+
expiresAt: session.expiresAt
|
|
637
|
+
};
|
|
638
|
+
const stateData = {
|
|
639
|
+
sessionToken: session.sessionToken,
|
|
640
|
+
sessionTokenExpiresAt: session.sessionTokenExpiresAt,
|
|
641
|
+
sub: readAnonymousSub(session.accessToken),
|
|
642
|
+
...options?.metadata && { metadata: options.metadata },
|
|
643
|
+
createdAt: Math.floor(Date.now() / 1e3),
|
|
644
|
+
tokenSets: [tokenSet],
|
|
645
|
+
domain
|
|
646
|
+
};
|
|
647
|
+
await this.#options.anonymousStore.set(
|
|
648
|
+
this.#options.anonymousStoreIdentifier,
|
|
649
|
+
stateData,
|
|
650
|
+
true,
|
|
651
|
+
storeOptions
|
|
652
|
+
);
|
|
653
|
+
return tokenSet;
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Returns an anonymous access token for the stored anonymous session, fetching a fresh
|
|
657
|
+
* one from Auth0 when the cached one has expired.
|
|
658
|
+
*
|
|
659
|
+
* Tokens are cached per audience and scope, so requesting a second audience returns a
|
|
660
|
+
* second token for the same anonymous identity without replacing the first.
|
|
661
|
+
*
|
|
662
|
+
* Auth0 may grant fewer scopes than requested — a scope the anonymous identity is not
|
|
663
|
+
* entitled to is silently dropped and the response is still a success. Always check
|
|
664
|
+
* `tokenSet.scope` before calling your API; do not assume the token carries every scope
|
|
665
|
+
* you asked for.
|
|
666
|
+
*
|
|
667
|
+
* This never creates a session. If the anonymous session has expired, the stored session
|
|
668
|
+
* is deleted and `AnonymousSessionExpiredError` is thrown, so a visitor is never moved
|
|
669
|
+
* onto a fresh anonymous identity behind your back.
|
|
670
|
+
*
|
|
671
|
+
* @param options Optional audience and scope for the requested token.
|
|
672
|
+
* @param storeOptions Optional options used to pass to the anonymous store (and to resolve the domain in resolver mode).
|
|
673
|
+
*
|
|
674
|
+
* @throws {MissingAnonymousSessionError} When there is no anonymous session stored, or the stored one belongs to another Auth0 domain (resolver mode).
|
|
675
|
+
* @throws {AnonymousSessionExpiredError} When the anonymous session has expired or Auth0 rejected the session token. The stored session is deleted first.
|
|
676
|
+
*
|
|
677
|
+
* @returns The anonymous access token for the requested audience.
|
|
678
|
+
*/
|
|
679
|
+
async getAccessToken(options, storeOptions) {
|
|
680
|
+
const stateData = await this.#options.anonymousStore.get(
|
|
681
|
+
this.#options.anonymousStoreIdentifier,
|
|
682
|
+
storeOptions
|
|
683
|
+
);
|
|
684
|
+
if (!stateData?.sessionToken) {
|
|
685
|
+
throw new MissingAnonymousSessionError();
|
|
686
|
+
}
|
|
687
|
+
const domain = await this.#options.resolveDomain(storeOptions);
|
|
688
|
+
if (this.#options.isResolverMode() && stateData.domain !== domain) {
|
|
689
|
+
throw new MissingAnonymousSessionError(
|
|
690
|
+
"The stored anonymous session was created for a different Auth0 domain."
|
|
691
|
+
);
|
|
692
|
+
}
|
|
693
|
+
const requestedAudience = options?.audience ?? this.#options.defaultAudience;
|
|
694
|
+
const audience = requestedAudience ?? DEFAULT_AUDIENCE_CACHE_KEY;
|
|
695
|
+
const scope = options?.scope;
|
|
696
|
+
const cachedTokenSet = stateData.tokenSets.find(
|
|
697
|
+
(tokenSet2) => tokenSet2.audience === audience && (!scope || cacheKeyScope(tokenSet2) === scope || compareScopes(tokenSet2.scope, scope))
|
|
698
|
+
);
|
|
699
|
+
if (cachedTokenSet && cachedTokenSet.expiresAt > Date.now() / 1e3) {
|
|
700
|
+
return cachedTokenSet;
|
|
701
|
+
}
|
|
702
|
+
const renewed = await this.#options.getAuthClient(domain).anonymous.getAccessToken({
|
|
703
|
+
sessionToken: stateData.sessionToken,
|
|
704
|
+
...requestedAudience && { audience: requestedAudience },
|
|
705
|
+
...scope && { scope }
|
|
706
|
+
});
|
|
707
|
+
if (renewed.sessionReplaced) {
|
|
708
|
+
await this.#options.anonymousStore.delete(this.#options.anonymousStoreIdentifier, storeOptions);
|
|
709
|
+
throw new AnonymousSessionExpiredError();
|
|
710
|
+
}
|
|
711
|
+
const tokenSet = {
|
|
712
|
+
audience,
|
|
713
|
+
accessToken: renewed.accessToken,
|
|
714
|
+
scope: renewed.scope,
|
|
715
|
+
...scope && scope !== renewed.scope && { requestedScope: scope },
|
|
716
|
+
expiresAt: renewed.expiresAt
|
|
717
|
+
};
|
|
718
|
+
const existingStateData = await this.#options.anonymousStore.get(
|
|
719
|
+
this.#options.anonymousStoreIdentifier,
|
|
720
|
+
storeOptions
|
|
721
|
+
);
|
|
722
|
+
if (existingStateData?.sessionToken === stateData.sessionToken) {
|
|
723
|
+
await this.#options.anonymousStore.set(
|
|
724
|
+
this.#options.anonymousStoreIdentifier,
|
|
725
|
+
{
|
|
726
|
+
...existingStateData,
|
|
727
|
+
...existingStateData.sub === void 0 && { sub: readAnonymousSub(renewed.accessToken) },
|
|
728
|
+
tokenSets: upsertTokenSet(existingStateData.tokenSets, tokenSet)
|
|
729
|
+
},
|
|
730
|
+
false,
|
|
731
|
+
storeOptions
|
|
732
|
+
);
|
|
733
|
+
}
|
|
734
|
+
return tokenSet;
|
|
735
|
+
}
|
|
736
|
+
/**
|
|
737
|
+
* Returns the stored anonymous session, or `undefined` when there is none.
|
|
738
|
+
*
|
|
739
|
+
* Two common uses:
|
|
740
|
+
* - **Gate `createSession`** — call this first; only create a session when the result is `undefined`.
|
|
741
|
+
* - **Read identity for a merge** — `sub` and `metadata` are available here without decoding a token.
|
|
742
|
+
*
|
|
743
|
+
* This is a local read of the store with no request to Auth0. It cannot tell you whether
|
|
744
|
+
* Auth0 still considers the session valid — only {@link ServerAnonymousClient.getAccessToken} can.
|
|
745
|
+
* The session token is never included in the result.
|
|
746
|
+
*
|
|
747
|
+
* @param storeOptions Optional options used to pass to the anonymous store (and to resolve the domain in resolver mode).
|
|
748
|
+
*
|
|
749
|
+
* @returns The anonymous session, or `undefined` when there is none for this visitor (or it belongs to another Auth0 domain in resolver mode).
|
|
750
|
+
*/
|
|
751
|
+
async getSession(storeOptions) {
|
|
752
|
+
const stateData = await this.#options.anonymousStore.get(
|
|
753
|
+
this.#options.anonymousStoreIdentifier,
|
|
754
|
+
storeOptions
|
|
755
|
+
);
|
|
756
|
+
if (!stateData) {
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
if (this.#options.isResolverMode()) {
|
|
760
|
+
const domain = await this.#options.resolveDomain(storeOptions);
|
|
761
|
+
if (stateData.domain !== domain) {
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
const { sessionToken, ...sessionData } = stateData;
|
|
766
|
+
return sessionData;
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* Clears the anonymous session from the store.
|
|
770
|
+
*
|
|
771
|
+
* Does not call `POST /anonymous/logout` — that endpoint only clears the `auth0_anon`
|
|
772
|
+
* browser cookie, which your server never holds. Any access tokens already issued remain
|
|
773
|
+
* valid until they expire (~2 hours by default).
|
|
774
|
+
*
|
|
775
|
+
* You rarely need to call this directly: every method that establishes a user session
|
|
776
|
+
* clears the anonymous session automatically (unless `clearAnonymousSessionOnLogin: false`
|
|
777
|
+
* is set), and `serverClient.logout()` clears it too. Call this to explicitly reset a
|
|
778
|
+
* visitor's anonymous identity, or to clean up after your own post-login merge logic when
|
|
779
|
+
* automatic clearing is disabled.
|
|
780
|
+
*
|
|
781
|
+
* @param storeOptions Optional options used to pass to the anonymous store.
|
|
782
|
+
*/
|
|
783
|
+
async logout(storeOptions) {
|
|
784
|
+
await this.#options.anonymousStore.delete(this.#options.anonymousStoreIdentifier, storeOptions);
|
|
785
|
+
}
|
|
786
|
+
};
|
|
787
|
+
|
|
544
788
|
// src/server-client.ts
|
|
545
789
|
var normalizeDomain = (value) => {
|
|
546
790
|
const trimmed = value.trim();
|
|
@@ -549,7 +793,7 @@ var normalizeDomain = (value) => {
|
|
|
549
793
|
};
|
|
550
794
|
var decodeIssuer = (token) => {
|
|
551
795
|
try {
|
|
552
|
-
const { iss } = (0,
|
|
796
|
+
const { iss } = (0, import_jose2.decodeJwt)(token);
|
|
553
797
|
return typeof iss === "string" ? iss : void 0;
|
|
554
798
|
} catch {
|
|
555
799
|
return void 0;
|
|
@@ -564,7 +808,7 @@ var actorUnavailableError = (message) => {
|
|
|
564
808
|
};
|
|
565
809
|
var isTokenExpired = (token) => {
|
|
566
810
|
try {
|
|
567
|
-
const { exp } = (0,
|
|
811
|
+
const { exp } = (0, import_jose2.decodeJwt)(token);
|
|
568
812
|
if (typeof exp !== "number") {
|
|
569
813
|
return true;
|
|
570
814
|
}
|
|
@@ -586,6 +830,7 @@ var ServerClient = class {
|
|
|
586
830
|
#mfaClient;
|
|
587
831
|
#passkeyClient;
|
|
588
832
|
#databaseClient;
|
|
833
|
+
#anonymousClient;
|
|
589
834
|
/**
|
|
590
835
|
* The underlying `authClient` instance that can be used to interact with the Auth0 Authentication API.
|
|
591
836
|
* Generally, you should prefer to use the higher-level methods exposed on the `ServerClient` instance.
|
|
@@ -648,6 +893,42 @@ var ServerClient = class {
|
|
|
648
893
|
get database() {
|
|
649
894
|
return this.#databaseClient;
|
|
650
895
|
}
|
|
896
|
+
/**
|
|
897
|
+
* The anonymous session client, for giving a visitor who has not logged in a stable
|
|
898
|
+
* identity and an access token for your API.
|
|
899
|
+
*
|
|
900
|
+
* Provides `createSession()` to establish the anonymous identity, `getAccessToken()` to
|
|
901
|
+
* obtain and renew anonymous access tokens, `getSession()` to check whether a visitor
|
|
902
|
+
* already has one, and `logout()` to discard it.
|
|
903
|
+
*
|
|
904
|
+
* Requires `anonymousStore` on the `ServerClient`, and a tenant and client configured for
|
|
905
|
+
* anonymous sessions. Anonymous sessions are kept in that store, never in the state
|
|
906
|
+
* store, so `getSession()` and `getUser()` still report no user while one is active.
|
|
907
|
+
*
|
|
908
|
+
* The anonymous session ends when the visitor logs in: every login method clears it once
|
|
909
|
+
* the user session is written, unless you set `clearAnonymousSessionOnLogin: false`.
|
|
910
|
+
* {@link ServerClient.logout} clears it too.
|
|
911
|
+
*
|
|
912
|
+
* For `/authorize` flows, `startInteractiveLogin()` links the anonymous session to
|
|
913
|
+
* the user automatically via a Session Transfer Ticket — no extra configuration needed.
|
|
914
|
+
* For logins that bypass `/authorize` (passkey, passwordless, backchannel, custom token
|
|
915
|
+
* exchange), the anonymous session is not linked. Read `anonymous.getSession()` before
|
|
916
|
+
* the login to get the anonymous `sub` for a manual merge, or set
|
|
917
|
+
* `clearAnonymousSessionOnLogin: false` and clear it yourself afterwards.
|
|
918
|
+
*
|
|
919
|
+
* Like `passkey` and `database`, this works in both static and resolver (multi-tenant)
|
|
920
|
+
* domain modes.
|
|
921
|
+
*
|
|
922
|
+
* @throws {InvalidConfigurationError} When no `anonymousStore` is configured.
|
|
923
|
+
*/
|
|
924
|
+
get anonymous() {
|
|
925
|
+
if (!this.#anonymousClient) {
|
|
926
|
+
throw new InvalidConfigurationError(
|
|
927
|
+
"anonymous is only available when an `anonymousStore` is configured on the ServerClient."
|
|
928
|
+
);
|
|
929
|
+
}
|
|
930
|
+
return this.#anonymousClient;
|
|
931
|
+
}
|
|
651
932
|
constructor(options) {
|
|
652
933
|
this.#options = options;
|
|
653
934
|
this.#enterpriseConnect = !!options.enterpriseConnect;
|
|
@@ -706,7 +987,8 @@ var ServerClient = class {
|
|
|
706
987
|
domain,
|
|
707
988
|
stateStore: this.#stateStore,
|
|
708
989
|
stateStoreIdentifier: this.#stateStoreIdentifier,
|
|
709
|
-
defaultAudience: this.#options.authorizationParams?.audience ?? "default"
|
|
990
|
+
defaultAudience: this.#options.authorizationParams?.audience ?? "default",
|
|
991
|
+
onUserSessionEstablished: (storeOptions) => this.#clearAnonymousSessionAfterLogin(storeOptions)
|
|
710
992
|
});
|
|
711
993
|
}
|
|
712
994
|
this.#passkeyClient = new ServerPasskeyClient({
|
|
@@ -715,12 +997,26 @@ var ServerClient = class {
|
|
|
715
997
|
stateStore: this.#stateStore,
|
|
716
998
|
stateStoreIdentifier: this.#stateStoreIdentifier,
|
|
717
999
|
defaultScope: this.#options.authorizationParams?.scope,
|
|
718
|
-
defaultAudience: this.#options.authorizationParams?.audience
|
|
1000
|
+
defaultAudience: this.#options.authorizationParams?.audience,
|
|
1001
|
+
onUserSessionEstablished: (storeOptions) => this.#clearAnonymousSessionAfterLogin(storeOptions)
|
|
719
1002
|
});
|
|
720
1003
|
this.#databaseClient = new ServerDatabaseClient({
|
|
721
1004
|
resolveDomain: (storeOptions) => this.#resolveDomain(storeOptions),
|
|
722
1005
|
getAuthClient: (domain) => this.#getAuthClient(domain)
|
|
723
1006
|
});
|
|
1007
|
+
if (this.#options.anonymousStore) {
|
|
1008
|
+
this.#anonymousClient = new ServerAnonymousClient({
|
|
1009
|
+
resolveDomain: (storeOptions) => this.#resolveDomain(storeOptions),
|
|
1010
|
+
getAuthClient: (domain) => this.#getAuthClient(domain),
|
|
1011
|
+
isResolverMode: () => this.#isResolverMode(),
|
|
1012
|
+
anonymousStore: this.#options.anonymousStore,
|
|
1013
|
+
anonymousStoreIdentifier: this.#options.anonymousSessionIdentifier || "__a0_anon",
|
|
1014
|
+
// Only the audience is inherited from the client-level authorizationParams. The
|
|
1015
|
+
// scope there is written for a user session (`openid profile email offline_access`)
|
|
1016
|
+
// and none of it applies to an anonymous identity.
|
|
1017
|
+
defaultAudience: this.#options.authorizationParams?.audience
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
724
1020
|
}
|
|
725
1021
|
async #resolveDomain(storeOptions) {
|
|
726
1022
|
if (typeof this.#options.domain === "function") {
|
|
@@ -797,6 +1093,54 @@ var ServerClient = class {
|
|
|
797
1093
|
storeOptions
|
|
798
1094
|
);
|
|
799
1095
|
}
|
|
1096
|
+
/**
|
|
1097
|
+
* Discards the anonymous session once a login has established a user session.
|
|
1098
|
+
*
|
|
1099
|
+
* Called by every method that writes a user session, always AFTER the state store has been
|
|
1100
|
+
* written. An anonymous session outliving the login would leave a 30-day bearer credential
|
|
1101
|
+
* in a cookie on every request, and `anonymous.getAccessToken()` would keep minting
|
|
1102
|
+
* anonymous tokens for a visitor who is no longer anonymous.
|
|
1103
|
+
*
|
|
1104
|
+
* Two deliberate properties:
|
|
1105
|
+
* - **Best-effort.** The user is authenticated and their session is already persisted by
|
|
1106
|
+
* this point, so a failing anonymous store must not turn a successful login into an
|
|
1107
|
+
* error. The visitor would be unable to log in at all because of leftover state they
|
|
1108
|
+
* cannot see or clear.
|
|
1109
|
+
* - **Unconditional across domains.** In resolver (multi-tenant) mode the anonymous session
|
|
1110
|
+
* is dropped even when it was created against a different Auth0 domain than the one just
|
|
1111
|
+
* logged into. The anonymous store holds a single session per visitor, and "no anonymous
|
|
1112
|
+
* session survives a login" is a rule that can be reasoned about; a domain-dependent one
|
|
1113
|
+
* cannot.
|
|
1114
|
+
*
|
|
1115
|
+
* Skipped entirely when no `anonymousStore` is configured, or when the application opted
|
|
1116
|
+
* out with `clearAnonymousSessionOnLogin: false`.
|
|
1117
|
+
*/
|
|
1118
|
+
async #clearAnonymousSessionAfterLogin(storeOptions) {
|
|
1119
|
+
if (this.#options.clearAnonymousSessionOnLogin === false) {
|
|
1120
|
+
return;
|
|
1121
|
+
}
|
|
1122
|
+
await this.#discardAnonymousSession(storeOptions);
|
|
1123
|
+
}
|
|
1124
|
+
/**
|
|
1125
|
+
* Drops the anonymous session, swallowing store failures.
|
|
1126
|
+
*
|
|
1127
|
+
* Shared by the login sites and {@link ServerClient.logout}. Both run after the user
|
|
1128
|
+
* session has already been written or deleted, so the outcome the caller cares about is
|
|
1129
|
+
* settled: a failing anonymous store must not fail a login the user completed, nor block a
|
|
1130
|
+
* logout redirect and leave the visitor unable to log out. When the store is the
|
|
1131
|
+
* cookie-backed default this cannot fail, since deleting is a `Set-Cookie` on the response.
|
|
1132
|
+
*
|
|
1133
|
+
* No-op when no `anonymousStore` is configured.
|
|
1134
|
+
*/
|
|
1135
|
+
async #discardAnonymousSession(storeOptions) {
|
|
1136
|
+
if (!this.#anonymousClient) {
|
|
1137
|
+
return;
|
|
1138
|
+
}
|
|
1139
|
+
try {
|
|
1140
|
+
await this.#anonymousClient.logout(storeOptions);
|
|
1141
|
+
} catch {
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
800
1144
|
/**
|
|
801
1145
|
* Starts the interactive login process, and returns a URL to redirect the user-agent to to request authorization at Auth0.
|
|
802
1146
|
*
|
|
@@ -832,6 +1176,17 @@ var ServerClient = class {
|
|
|
832
1176
|
}
|
|
833
1177
|
const domain = await this.#resolveDomain(storeOptions);
|
|
834
1178
|
const authClient = this.#getAuthClient(domain);
|
|
1179
|
+
let anonTransferToken;
|
|
1180
|
+
if (this.#options.anonymousStore) {
|
|
1181
|
+
try {
|
|
1182
|
+
const identifier = this.#options.anonymousSessionIdentifier || "__a0_anon";
|
|
1183
|
+
const stateData = await this.#options.anonymousStore.get(identifier, storeOptions);
|
|
1184
|
+
if (stateData?.sessionToken) {
|
|
1185
|
+
anonTransferToken = await authClient.anonymous.mintTransferToken(stateData.sessionToken) ?? void 0;
|
|
1186
|
+
}
|
|
1187
|
+
} catch {
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
835
1190
|
const { codeVerifier, authorizationUrl } = await authClient.buildAuthorizationUrl({
|
|
836
1191
|
pushedAuthorizationRequests: options?.pushedAuthorizationRequests,
|
|
837
1192
|
authorizationParams: {
|
|
@@ -839,7 +1194,8 @@ var ServerClient = class {
|
|
|
839
1194
|
redirect_uri: redirectUri,
|
|
840
1195
|
scope,
|
|
841
1196
|
...resolvedOrganization ? { organization: resolvedOrganization } : {},
|
|
842
|
-
...options?.invitation ? { invitation: options.invitation } : {}
|
|
1197
|
+
...options?.invitation ? { invitation: options.invitation } : {},
|
|
1198
|
+
...anonTransferToken ? { anon_transfer_token: anonTransferToken } : {}
|
|
843
1199
|
}
|
|
844
1200
|
});
|
|
845
1201
|
const transactionState = {
|
|
@@ -909,6 +1265,7 @@ var ServerClient = class {
|
|
|
909
1265
|
tokenEndpointResponse.claims
|
|
910
1266
|
);
|
|
911
1267
|
await this.#stateStore.set(this.#stateStoreIdentifier, stateData, true, storeOptions);
|
|
1268
|
+
await this.#clearAnonymousSessionAfterLogin(storeOptions);
|
|
912
1269
|
return {
|
|
913
1270
|
appState: transactionData.appState,
|
|
914
1271
|
authorizationDetails: tokenEndpointResponse.authorizationDetails
|
|
@@ -1076,6 +1433,7 @@ var ServerClient = class {
|
|
|
1076
1433
|
tokenEndpointResponse.claims
|
|
1077
1434
|
);
|
|
1078
1435
|
await this.#stateStore.set(this.#stateStoreIdentifier, stateData, true, storeOptions);
|
|
1436
|
+
await this.#clearAnonymousSessionAfterLogin(storeOptions);
|
|
1079
1437
|
const result = {
|
|
1080
1438
|
authorizationDetails: tokenEndpointResponse.authorizationDetails
|
|
1081
1439
|
};
|
|
@@ -1222,6 +1580,7 @@ var ServerClient = class {
|
|
|
1222
1580
|
{ domain }
|
|
1223
1581
|
);
|
|
1224
1582
|
await this.#stateStore.set(this.#stateStoreIdentifier, stateData, true, storeOptions);
|
|
1583
|
+
await this.#clearAnonymousSessionAfterLogin(storeOptions);
|
|
1225
1584
|
const result = {
|
|
1226
1585
|
authorizationDetails: tokenEndpointResponse.authorizationDetails
|
|
1227
1586
|
};
|
|
@@ -1272,6 +1631,7 @@ var ServerClient = class {
|
|
|
1272
1631
|
domain
|
|
1273
1632
|
});
|
|
1274
1633
|
await this.#stateStore.set(this.#stateStoreIdentifier, stateData, true, storeOptions);
|
|
1634
|
+
await this.#clearAnonymousSessionAfterLogin(storeOptions);
|
|
1275
1635
|
await this.#transactionStore.delete(this.#transactionStoreIdentifier, storeOptions);
|
|
1276
1636
|
return {
|
|
1277
1637
|
authorizationDetails: tokenEndpointResponse.authorizationDetails
|
|
@@ -1579,6 +1939,29 @@ var ServerClient = class {
|
|
|
1579
1939
|
}
|
|
1580
1940
|
/**
|
|
1581
1941
|
* Logs the user out and returns a URL to redirect the user-agent to after they log out.
|
|
1942
|
+
*
|
|
1943
|
+
* Clears the anonymous session as well, whenever an `anonymousStore` is configured. Logging
|
|
1944
|
+
* out means the visitor is done, so leaving a 30-day anonymous credential behind in a
|
|
1945
|
+
* cookie would be surprising, and `anonymous.getAccessToken()` would keep working right
|
|
1946
|
+
* after the user logged out. This happens even when there is no user session to clear: a
|
|
1947
|
+
* visitor who only ever had an anonymous session can log out. Unlike the automatic clearing
|
|
1948
|
+
* at login, it is not affected by `clearAnonymousSessionOnLogin`, which exists so an
|
|
1949
|
+
* application can finish its post-login work.
|
|
1950
|
+
*
|
|
1951
|
+
* In resolver (multi-tenant) mode the one exception is a stored user session belonging to a
|
|
1952
|
+
* different Auth0 domain than the request resolves to. Nothing local is cleared in that
|
|
1953
|
+
* case, anonymous session included, exactly as today: that state belongs to another tenant.
|
|
1954
|
+
*
|
|
1955
|
+
* The anonymous session is only ever cleared locally. The SDK does not call
|
|
1956
|
+
* `POST /anonymous/logout`: that endpoint exists to clear the `auth0_anon` cookie in a
|
|
1957
|
+
* browser, and it revokes nothing server-side. Your server never holds that cookie, so
|
|
1958
|
+
* calling it would achieve nothing. If the visitor's browser created an anonymous session
|
|
1959
|
+
* of its own (through `@auth0/auth0-spa-js`, for example), that cookie is not covered by
|
|
1960
|
+
* this SDK and has to be cleared from the browser.
|
|
1961
|
+
*
|
|
1962
|
+
* Anonymous access tokens already handed out stay valid until they expire; there is no
|
|
1963
|
+
* anonymous session to revoke them against.
|
|
1964
|
+
*
|
|
1582
1965
|
* @param options Options used to configure the logout process.
|
|
1583
1966
|
* @param storeOptions Optional options used to pass to the Transaction and State Store.
|
|
1584
1967
|
* @param requestOptions Optional per-request options (signal, headers, customFetch). Applied to the token revocation ONLY. Building the logout URL is local string work and issues no request, so nothing here can affect it.
|
|
@@ -1599,12 +1982,14 @@ var ServerClient = class {
|
|
|
1599
1982
|
} catch {
|
|
1600
1983
|
}
|
|
1601
1984
|
await this.#stateStore.delete(this.#stateStoreIdentifier, storeOptions);
|
|
1985
|
+
await this.#discardAnonymousSession(storeOptions);
|
|
1602
1986
|
return this.authClient.buildLogoutUrl(options);
|
|
1603
1987
|
}
|
|
1604
1988
|
const resolvedDomain = await this.#resolveDomain(storeOptions);
|
|
1605
1989
|
const authClient = this.#getAuthClient(resolvedDomain);
|
|
1606
1990
|
const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
|
|
1607
1991
|
if (!stateData) {
|
|
1992
|
+
await this.#discardAnonymousSession(storeOptions);
|
|
1608
1993
|
return authClient.buildLogoutUrl(options);
|
|
1609
1994
|
}
|
|
1610
1995
|
const sessionDomain = this.#getSessionDomain(stateData);
|
|
@@ -1615,6 +2000,7 @@ var ServerClient = class {
|
|
|
1615
2000
|
} catch {
|
|
1616
2001
|
}
|
|
1617
2002
|
await this.#stateStore.delete(this.#stateStoreIdentifier, storeOptions);
|
|
2003
|
+
await this.#discardAnonymousSession(storeOptions);
|
|
1618
2004
|
}
|
|
1619
2005
|
return authClient.buildLogoutUrl(options);
|
|
1620
2006
|
}
|
|
@@ -1646,6 +2032,7 @@ var ServerClient = class {
|
|
|
1646
2032
|
{ domain }
|
|
1647
2033
|
);
|
|
1648
2034
|
await this.#stateStore.set(this.#stateStoreIdentifier, stateData, true, storeOptions);
|
|
2035
|
+
await this.#clearAnonymousSessionAfterLogin(storeOptions);
|
|
1649
2036
|
const result = {
|
|
1650
2037
|
authorizationDetails: tokenEndpointResponse.authorizationDetails
|
|
1651
2038
|
};
|
|
@@ -1893,7 +2280,7 @@ var ServerClient = class {
|
|
|
1893
2280
|
};
|
|
1894
2281
|
|
|
1895
2282
|
// src/encryption/index.ts
|
|
1896
|
-
var
|
|
2283
|
+
var import_jose3 = require("jose");
|
|
1897
2284
|
var ENC = "A256CBC-HS512";
|
|
1898
2285
|
var ALG = "dir";
|
|
1899
2286
|
var DIGEST = "SHA-256";
|
|
@@ -1901,7 +2288,7 @@ var BIT_LENGTH = 512;
|
|
|
1901
2288
|
var HKDF_INFO = "derived cookie encryption secret";
|
|
1902
2289
|
var encoder;
|
|
1903
2290
|
function isDecryptionError(e) {
|
|
1904
|
-
return e instanceof
|
|
2291
|
+
return e instanceof import_jose3.errors.JWEDecryptionFailed || e instanceof import_jose3.errors.JWEInvalid;
|
|
1905
2292
|
}
|
|
1906
2293
|
async function deriveEncryptionSecret(secret, salt, kid) {
|
|
1907
2294
|
encoder ||= new TextEncoder();
|
|
@@ -1922,7 +2309,7 @@ async function deriveEncryptionSecret(secret, salt, kid) {
|
|
|
1922
2309
|
async function _encrypt(payload, secret, salt, expiration) {
|
|
1923
2310
|
const kid = crypto.randomUUID();
|
|
1924
2311
|
const encryptionSecret = await deriveEncryptionSecret(secret, salt, kid);
|
|
1925
|
-
return await new
|
|
2312
|
+
return await new import_jose3.EncryptJWT(payload).setProtectedHeader({ enc: ENC, alg: ALG, kid }).setExpirationTime(expiration).encrypt(encryptionSecret);
|
|
1926
2313
|
}
|
|
1927
2314
|
async function encrypt(payload, secret, salt, expiration) {
|
|
1928
2315
|
if (typeof secret === "string") {
|
|
@@ -1936,7 +2323,7 @@ async function encrypt(payload, secret, salt, expiration) {
|
|
|
1936
2323
|
}
|
|
1937
2324
|
}
|
|
1938
2325
|
async function _decrypt(value, secret, salt) {
|
|
1939
|
-
const res = await (0,
|
|
2326
|
+
const res = await (0, import_jose3.jwtDecrypt)(
|
|
1940
2327
|
value,
|
|
1941
2328
|
async (protectedHeader) => {
|
|
1942
2329
|
if (!protectedHeader.kid) {
|
|
@@ -2014,7 +2401,7 @@ var AbstractTransactionStore = class extends AbstractStore {
|
|
|
2014
2401
|
};
|
|
2015
2402
|
|
|
2016
2403
|
// src/index.ts
|
|
2017
|
-
var
|
|
2404
|
+
var import_auth0_auth_js7 = require("@auth0/auth0-auth-js");
|
|
2018
2405
|
|
|
2019
2406
|
// src/store/cookie-transaction-store.ts
|
|
2020
2407
|
var CookieTransactionStore = class extends AbstractTransactionStore {
|
|
@@ -2210,6 +2597,88 @@ var StatelessStateStore = class extends AbstractSessionStore {
|
|
|
2210
2597
|
}
|
|
2211
2598
|
};
|
|
2212
2599
|
|
|
2600
|
+
// src/store/abstract-anonymous-store.ts
|
|
2601
|
+
var AbstractAnonymousStore = class extends AbstractStore {
|
|
2602
|
+
constructor(options) {
|
|
2603
|
+
super(options);
|
|
2604
|
+
}
|
|
2605
|
+
};
|
|
2606
|
+
|
|
2607
|
+
// src/store/stateless-anonymous-store.ts
|
|
2608
|
+
var DEFAULT_ANONYMOUS_SESSION_LIFETIME = 60 * 60 * 24 * 30;
|
|
2609
|
+
var CHUNK_SIZE = 3072;
|
|
2610
|
+
var StatelessAnonymousStore = class extends AbstractAnonymousStore {
|
|
2611
|
+
#cookieOptions;
|
|
2612
|
+
#cookieHandler;
|
|
2613
|
+
#sessionTokenLifetime;
|
|
2614
|
+
constructor(options, cookieHandler) {
|
|
2615
|
+
super(options);
|
|
2616
|
+
this.#cookieOptions = options.cookie;
|
|
2617
|
+
this.#cookieHandler = cookieHandler;
|
|
2618
|
+
this.#sessionTokenLifetime = options.sessionTokenLifetime ?? DEFAULT_ANONYMOUS_SESSION_LIFETIME;
|
|
2619
|
+
}
|
|
2620
|
+
async set(identifier, anonymousStateData, removeIfExists, options) {
|
|
2621
|
+
const expiration = this.#getExpiration(anonymousStateData);
|
|
2622
|
+
const maxAge = expiration - Math.floor(Date.now() / 1e3);
|
|
2623
|
+
if (maxAge <= 0) {
|
|
2624
|
+
await this.delete(identifier, options);
|
|
2625
|
+
return;
|
|
2626
|
+
}
|
|
2627
|
+
const cookieOpts = this.#getCookieOptions({ maxAge });
|
|
2628
|
+
const encryptedStateData = await this.encrypt(identifier, anonymousStateData, expiration);
|
|
2629
|
+
const chunkCount = Math.ceil(encryptedStateData.length / CHUNK_SIZE);
|
|
2630
|
+
const chunks = [...Array(chunkCount).keys()].map((i) => ({
|
|
2631
|
+
value: encryptedStateData.substring(i * CHUNK_SIZE, (i + 1) * CHUNK_SIZE),
|
|
2632
|
+
name: `${identifier}.${i}`
|
|
2633
|
+
}));
|
|
2634
|
+
chunks.forEach((chunk) => {
|
|
2635
|
+
this.#cookieHandler.setCookie(chunk.name, chunk.value, cookieOpts, options);
|
|
2636
|
+
});
|
|
2637
|
+
const existingCookieKeys = this.#getCookieKeys(identifier, options);
|
|
2638
|
+
existingCookieKeys.filter((key) => !chunks.some((chunk) => chunk.name === key)).forEach((key) => {
|
|
2639
|
+
this.#cookieHandler.deleteCookie(key, options, this.#getCookieOptions());
|
|
2640
|
+
});
|
|
2641
|
+
}
|
|
2642
|
+
async get(identifier, options) {
|
|
2643
|
+
const cookieKeys = this.#getCookieKeys(identifier, options);
|
|
2644
|
+
const encryptedStateData = cookieKeys.map((key) => ({
|
|
2645
|
+
index: parseInt(key.split(".")[1], 10),
|
|
2646
|
+
value: this.#cookieHandler.getCookie(key, options)
|
|
2647
|
+
})).sort((a, b) => a.index - b.index).map((item) => item.value).join("");
|
|
2648
|
+
if (encryptedStateData) {
|
|
2649
|
+
return await this.decrypt(identifier, encryptedStateData);
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2652
|
+
async delete(identifier, options) {
|
|
2653
|
+
const cookieKeys = this.#getCookieKeys(identifier, options);
|
|
2654
|
+
for (const key of cookieKeys) {
|
|
2655
|
+
this.#cookieHandler.deleteCookie(key, options, this.#getCookieOptions());
|
|
2656
|
+
}
|
|
2657
|
+
}
|
|
2658
|
+
/**
|
|
2659
|
+
* Absolute expiry of the anonymous session, in Unix seconds.
|
|
2660
|
+
*
|
|
2661
|
+
* Prefers the value Auth0 reports. `sessionTokenExpiresAt` is not populated yet, because
|
|
2662
|
+
* `auth0-auth-js` does not surface `session_expires_in` from the token response; until it
|
|
2663
|
+
* does, this falls back to the configured lifetime measured from creation.
|
|
2664
|
+
*/
|
|
2665
|
+
#getExpiration(anonymousStateData) {
|
|
2666
|
+
return anonymousStateData.sessionTokenExpiresAt ?? anonymousStateData.createdAt + this.#sessionTokenLifetime;
|
|
2667
|
+
}
|
|
2668
|
+
#getCookieKeys(identifier, options) {
|
|
2669
|
+
return Object.keys(this.#cookieHandler.getCookies(options)).filter((key) => key.startsWith(identifier));
|
|
2670
|
+
}
|
|
2671
|
+
#getCookieOptions(partial) {
|
|
2672
|
+
return {
|
|
2673
|
+
httpOnly: true,
|
|
2674
|
+
sameSite: this.#cookieOptions?.sameSite ?? "lax",
|
|
2675
|
+
path: this.#cookieOptions?.path ?? "/",
|
|
2676
|
+
secure: this.#cookieOptions?.secure ?? true,
|
|
2677
|
+
...partial
|
|
2678
|
+
};
|
|
2679
|
+
}
|
|
2680
|
+
};
|
|
2681
|
+
|
|
2213
2682
|
// src/mfa/index.ts
|
|
2214
2683
|
var import_auth0_auth_js3 = require("@auth0/auth0-auth-js");
|
|
2215
2684
|
|
|
@@ -2218,13 +2687,20 @@ var import_auth0_auth_js4 = require("@auth0/auth0-auth-js");
|
|
|
2218
2687
|
|
|
2219
2688
|
// src/database/index.ts
|
|
2220
2689
|
var import_auth0_auth_js5 = require("@auth0/auth0-auth-js");
|
|
2690
|
+
|
|
2691
|
+
// src/anonymous/index.ts
|
|
2692
|
+
var import_auth0_auth_js6 = require("@auth0/auth0-auth-js");
|
|
2221
2693
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2222
2694
|
0 && (module.exports = {
|
|
2695
|
+
AbstractAnonymousStore,
|
|
2223
2696
|
AbstractStateStore,
|
|
2224
2697
|
AbstractTransactionStore,
|
|
2698
|
+
AnonymousSessionError,
|
|
2699
|
+
AnonymousSessionExpiredError,
|
|
2225
2700
|
BackchannelLogoutError,
|
|
2226
2701
|
ChangePasswordError,
|
|
2227
2702
|
CookieTransactionStore,
|
|
2703
|
+
DEFAULT_ANONYMOUS_SESSION_LIFETIME,
|
|
2228
2704
|
EnterpriseConnectNotSupportedError,
|
|
2229
2705
|
InvalidConfigurationError,
|
|
2230
2706
|
IssuerValidationError,
|
|
@@ -2232,6 +2708,7 @@ var import_auth0_auth_js5 = require("@auth0/auth0-auth-js");
|
|
|
2232
2708
|
MfaEnrollmentError,
|
|
2233
2709
|
MfaListAuthenticatorsError,
|
|
2234
2710
|
MfaVerifyError,
|
|
2711
|
+
MissingAnonymousSessionError,
|
|
2235
2712
|
MissingClientAuthError,
|
|
2236
2713
|
MissingRequiredArgumentError,
|
|
2237
2714
|
MissingSessionError,
|
|
@@ -2242,6 +2719,7 @@ var import_auth0_auth_js5 = require("@auth0/auth0-auth-js");
|
|
|
2242
2719
|
PasskeyRegisterError,
|
|
2243
2720
|
PasswordlessStartError,
|
|
2244
2721
|
PasswordlessVerifyError,
|
|
2722
|
+
ServerAnonymousClient,
|
|
2245
2723
|
ServerClient,
|
|
2246
2724
|
ServerDatabaseClient,
|
|
2247
2725
|
ServerMfaClient,
|
|
@@ -2250,6 +2728,7 @@ var import_auth0_auth_js5 = require("@auth0/auth0-auth-js");
|
|
|
2250
2728
|
SignUpError,
|
|
2251
2729
|
StartLinkUserError,
|
|
2252
2730
|
StatefulStateStore,
|
|
2731
|
+
StatelessAnonymousStore,
|
|
2253
2732
|
StatelessStateStore,
|
|
2254
2733
|
TokenExchangeError,
|
|
2255
2734
|
TokenExchangeErrorCode,
|