@darkauth/client 1.22.2 → 1.23.1
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 +35 -2
- package/dist/index.d.ts +8 -0
- package/dist/index.js +29 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -72,7 +72,8 @@ setConfig({
|
|
|
72
72
|
tokenStorage: 'memory', // Optional. Default 'memory'. Use 'localStorage' only for legacy flows.
|
|
73
73
|
drkStorage: 'memory', // Optional. Default 'memory'. Use 'localStorage' only for explicit convenience mode.
|
|
74
74
|
refreshMode: 'cookie', // Optional. Default 'cookie'. Use 'token' only for legacy refresh-token clients.
|
|
75
|
-
credentials: 'include'
|
|
75
|
+
credentials: 'include', // Optional. Default 'include' for cookie refresh.
|
|
76
|
+
endSessionEndpoint: 'https://auth.example.com/api/logout' // Optional. Override the RP-initiated logout endpoint (otherwise read from discovery).
|
|
76
77
|
});
|
|
77
78
|
```
|
|
78
79
|
|
|
@@ -106,7 +107,28 @@ Behavior:
|
|
|
106
107
|
|
|
107
108
|
#### `logout(): void`
|
|
108
109
|
|
|
109
|
-
Clears the in-memory session, callback state, PKCE verifier, ephemeral ZK key, and any explicitly configured legacy storage.
|
|
110
|
+
Clears the in-memory session, callback state, PKCE verifier, ephemeral ZK key, and any explicitly configured legacy storage. This is a **local-only** logout — it does not end the DarkAuth SSO session, so a subsequent `initiateLogin()` may silently re-authenticate. Use `endSession()` when you need to end the IdP session too.
|
|
111
|
+
|
|
112
|
+
#### `endSession(options?: EndSessionOptions): Promise<void>`
|
|
113
|
+
|
|
114
|
+
Performs OIDC [RP-initiated logout](https://openid.net/specs/openid-connect-rpinitiated-1_0.html). Clears the local session (same as `logout()`) and then redirects the browser to DarkAuth's `end_session_endpoint`, which ends the SSO session and redirects back to your app.
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
import { endSession } from '@DarkAuth/client';
|
|
118
|
+
|
|
119
|
+
await endSession({
|
|
120
|
+
postLogoutRedirectUri: `${window.location.origin}/login`,
|
|
121
|
+
state: 'optional-csrf-value',
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Options (`EndSessionOptions`):
|
|
126
|
+
- `postLogoutRedirectUri?`: Where DarkAuth redirects after ending the session. **Must be registered in the client's `post_logout_redirect_uris` allowlist** on the DarkAuth server (exact match), otherwise the request is rejected. When provided, the SDK also sends `client_id` (the configured `clientId` unless overridden).
|
|
127
|
+
- `state?`: Opaque value echoed back on the post-logout redirect (use it to protect against CSRF / restore app state).
|
|
128
|
+
- `idTokenHint?`: The ID token to send as `id_token_hint`. Defaults to the current session's ID token. With a valid hint DarkAuth ends the session without a confirmation prompt.
|
|
129
|
+
- `clientId?`: Override the `client_id` sent alongside `post_logout_redirect_uri` (defaults to the configured `clientId`).
|
|
130
|
+
|
|
131
|
+
The `end_session_endpoint` is resolved from the server's `/.well-known/openid-configuration` discovery document, falling back to `<issuer>/api/logout`, or to the `endSessionEndpoint` config value when set.
|
|
110
132
|
|
|
111
133
|
#### `getStoredSession(): AuthSession | null`
|
|
112
134
|
|
|
@@ -300,6 +322,17 @@ type Config = {
|
|
|
300
322
|
drkStorage?: 'memory' | 'localStorage';
|
|
301
323
|
refreshMode?: 'cookie' | 'token';
|
|
302
324
|
credentials?: RequestCredentials;
|
|
325
|
+
endSessionEndpoint?: string;
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### `EndSessionOptions`
|
|
330
|
+
```typescript
|
|
331
|
+
type EndSessionOptions = {
|
|
332
|
+
postLogoutRedirectUri?: string;
|
|
333
|
+
state?: string;
|
|
334
|
+
idTokenHint?: string;
|
|
335
|
+
clientId?: string;
|
|
303
336
|
}
|
|
304
337
|
```
|
|
305
338
|
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ type Config = {
|
|
|
9
9
|
zk?: boolean;
|
|
10
10
|
authorizationEndpoint?: string;
|
|
11
11
|
tokenEndpoint?: string;
|
|
12
|
+
endSessionEndpoint?: string;
|
|
12
13
|
discovery?: boolean;
|
|
13
14
|
firstParty?: boolean;
|
|
14
15
|
tokenStorage?: "memory" | "localStorage";
|
|
@@ -60,6 +61,12 @@ export type SwitchOrganizationOptions = {
|
|
|
60
61
|
export type RefreshSessionOptions = {
|
|
61
62
|
force?: boolean;
|
|
62
63
|
};
|
|
64
|
+
export type EndSessionOptions = {
|
|
65
|
+
postLogoutRedirectUri?: string;
|
|
66
|
+
state?: string;
|
|
67
|
+
idTokenHint?: string;
|
|
68
|
+
clientId?: string;
|
|
69
|
+
};
|
|
63
70
|
export type DarkAuthSessionInfo = {
|
|
64
71
|
authenticated: boolean;
|
|
65
72
|
sub?: string;
|
|
@@ -94,4 +101,5 @@ export declare function listOrganizations(): Promise<DarkAuthOrganization[]>;
|
|
|
94
101
|
export declare function getSessionInfo(): Promise<DarkAuthSessionInfo>;
|
|
95
102
|
export declare function switchOrganization(organizationId: string, options?: SwitchOrganizationOptions): Promise<AuthSession | null>;
|
|
96
103
|
export declare function logout(): void;
|
|
104
|
+
export declare function endSession(options?: EndSessionOptions): Promise<void>;
|
|
97
105
|
export declare function getCurrentUser(): JwtClaims | null;
|
package/dist/index.js
CHANGED
|
@@ -155,6 +155,7 @@ async function resolveEndpoints() {
|
|
|
155
155
|
cfg.scope || "",
|
|
156
156
|
cfg.authorizationEndpoint || "",
|
|
157
157
|
cfg.tokenEndpoint || "",
|
|
158
|
+
cfg.endSessionEndpoint || "",
|
|
158
159
|
cfg.discovery === false ? "0" : "1",
|
|
159
160
|
].join("|");
|
|
160
161
|
if (endpointsInFlight && endpointsCacheKey === cacheKey)
|
|
@@ -164,8 +165,9 @@ async function resolveEndpoints() {
|
|
|
164
165
|
const fallback = {
|
|
165
166
|
authorizationEndpoint: cfg.authorizationEndpoint || rootEndpoint("/authorize"),
|
|
166
167
|
tokenEndpoint: cfg.tokenEndpoint || rootEndpoint("/token"),
|
|
168
|
+
endSessionEndpoint: cfg.endSessionEndpoint || rootEndpoint("/api/logout"),
|
|
167
169
|
};
|
|
168
|
-
if (cfg.authorizationEndpoint && cfg.tokenEndpoint)
|
|
170
|
+
if (cfg.authorizationEndpoint && cfg.tokenEndpoint && cfg.endSessionEndpoint)
|
|
169
171
|
return fallback;
|
|
170
172
|
if (cfg.discovery === false || typeof fetch !== "function")
|
|
171
173
|
return fallback;
|
|
@@ -184,6 +186,10 @@ async function resolveEndpoints() {
|
|
|
184
186
|
(typeof metadata.token_endpoint === "string"
|
|
185
187
|
? metadata.token_endpoint
|
|
186
188
|
: fallback.tokenEndpoint),
|
|
189
|
+
endSessionEndpoint: cfg.endSessionEndpoint ||
|
|
190
|
+
(typeof metadata.end_session_endpoint === "string"
|
|
191
|
+
? metadata.end_session_endpoint
|
|
192
|
+
: fallback.endSessionEndpoint),
|
|
187
193
|
};
|
|
188
194
|
}
|
|
189
195
|
catch {
|
|
@@ -744,7 +750,7 @@ export async function switchOrganization(organizationId, options = {}) {
|
|
|
744
750
|
location.assign(switchUrl.toString());
|
|
745
751
|
return null;
|
|
746
752
|
}
|
|
747
|
-
|
|
753
|
+
function clearLocalSession() {
|
|
748
754
|
memorySession = null;
|
|
749
755
|
memoryRefreshToken = null;
|
|
750
756
|
clearStoredIdToken();
|
|
@@ -755,6 +761,27 @@ export function logout() {
|
|
|
755
761
|
sessionStorage.removeItem(OAUTH_STATE_KEY);
|
|
756
762
|
localStorage.removeItem(REFRESH_TOKEN_KEY);
|
|
757
763
|
}
|
|
764
|
+
export function logout() {
|
|
765
|
+
clearLocalSession();
|
|
766
|
+
}
|
|
767
|
+
export async function endSession(options = {}) {
|
|
768
|
+
const idTokenHint = options.idTokenHint ||
|
|
769
|
+
memorySession?.idToken ||
|
|
770
|
+
(tokenStorageMode() === "localStorage" ? getStoredIdToken() : null) ||
|
|
771
|
+
undefined;
|
|
772
|
+
const endpoints = await resolveEndpoints();
|
|
773
|
+
const url = new URL(endpoints.endSessionEndpoint);
|
|
774
|
+
if (idTokenHint)
|
|
775
|
+
url.searchParams.set("id_token_hint", idTokenHint);
|
|
776
|
+
if (options.postLogoutRedirectUri) {
|
|
777
|
+
url.searchParams.set("post_logout_redirect_uri", options.postLogoutRedirectUri);
|
|
778
|
+
url.searchParams.set("client_id", options.clientId || cfg.clientId);
|
|
779
|
+
}
|
|
780
|
+
if (options.state)
|
|
781
|
+
url.searchParams.set("state", options.state);
|
|
782
|
+
clearLocalSession();
|
|
783
|
+
location.assign(url.toString());
|
|
784
|
+
}
|
|
758
785
|
export function getCurrentUser() {
|
|
759
786
|
const idToken = memorySession?.idToken || (tokenStorageMode() === "localStorage" ? getStoredIdToken() : null);
|
|
760
787
|
if (!idToken)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@darkauth/client",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.23.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"directory": "packages/darkauth-client",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"scripts": {
|
|
27
27
|
"build": "tsc",
|
|
28
|
-
"test": "
|
|
28
|
+
"test": "tsc -p tsconfig.test.json && node --test --test-reporter=dot \".test-build/**/*.test.js\"",
|
|
29
29
|
"typecheck": "tsc --noEmit",
|
|
30
30
|
"format": "biome format --write .",
|
|
31
31
|
"lint": "biome lint .",
|