@darkauth/client 1.20.2 → 1.21.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 +4 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +33 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -118,7 +118,7 @@ If `tokenStorage: 'localStorage'` or `drkStorage: 'localStorage'` is configured
|
|
|
118
118
|
|
|
119
119
|
Refreshes the current session. In default first-party mode, the browser sends the DarkAuth refresh cookie and no JavaScript-readable refresh token is required. For non-ZK sessions, returns `drk` as an empty `Uint8Array`.
|
|
120
120
|
|
|
121
|
-
Use `{ force: true }` after
|
|
121
|
+
Use `{ force: true }` after hosted first-party organization changes so the app receives tokens for the newly selected organization even if the current in-memory ID token has not expired.
|
|
122
122
|
|
|
123
123
|
### Organization Switching
|
|
124
124
|
|
|
@@ -126,7 +126,7 @@ DarkAuth treats organization switching as choosing a new authorization context.
|
|
|
126
126
|
|
|
127
127
|
#### `listOrganizations(): Promise<DarkAuthOrganization[]>`
|
|
128
128
|
|
|
129
|
-
Returns the current user's organizations for app-owned switcher UI. Use `status` to decide which memberships are selectable.
|
|
129
|
+
Returns the current user's organizations for app-owned switcher UI. When the SDK has a current app access token, the request is authorized with `Authorization: Bearer <access_token>` and does not depend on DarkAuth session cookies. Use `status` to decide which memberships are selectable.
|
|
130
130
|
|
|
131
131
|
#### `getSessionInfo(): Promise<{ authenticated: boolean; sub?: string; email?: string | null; name?: string | null; organizationId?: string; organizationSlug?: string | null }>`
|
|
132
132
|
|
|
@@ -134,7 +134,7 @@ Returns current first-party session and organization context for app chrome befo
|
|
|
134
134
|
|
|
135
135
|
#### `switchOrganization(organizationId: string, options?: SwitchOrganizationOptions): Promise<AuthSession | null>`
|
|
136
136
|
|
|
137
|
-
Switches the selected organization. The default `
|
|
137
|
+
Switches the selected organization. The default `token` mode exchanges the current app access token for fresh tokens scoped to the selected organization. `authorize` mode starts a new authorization-code flow. `hosted` mode redirects to DarkAuth's `/switch-org` page.
|
|
138
138
|
|
|
139
139
|
#### App-owned switcher
|
|
140
140
|
|
|
@@ -156,7 +156,7 @@ async function selectOrganization(organizationId: string) {
|
|
|
156
156
|
}
|
|
157
157
|
```
|
|
158
158
|
|
|
159
|
-
After the
|
|
159
|
+
After the exchange, verify that `selectedOrganizationId` matches the workspace being loaded. Treat the switch as a tenant or workspace state reset: clear tenant-local caches, selected resources, open realtime subscriptions, in-flight requests, and authorization decisions before loading data for the new `org_id`.
|
|
160
160
|
|
|
161
161
|
Use `mode: 'authorize'` when a deployment should re-enter the redirect-based OAuth flow for every organization switch.
|
|
162
162
|
|
package/dist/index.d.ts
CHANGED
|
@@ -54,7 +54,7 @@ export type InitiateLoginOptions = {
|
|
|
54
54
|
returnTo?: string;
|
|
55
55
|
};
|
|
56
56
|
export type SwitchOrganizationOptions = {
|
|
57
|
-
mode?: "
|
|
57
|
+
mode?: "token" | "authorize" | "hosted";
|
|
58
58
|
returnTo?: string;
|
|
59
59
|
};
|
|
60
60
|
export type RefreshSessionOptions = {
|
package/dist/index.js
CHANGED
|
@@ -647,7 +647,11 @@ export async function refreshSession(options = {}) {
|
|
|
647
647
|
});
|
|
648
648
|
}
|
|
649
649
|
export async function listOrganizations() {
|
|
650
|
+
const accessToken = memorySession?.accessToken ||
|
|
651
|
+
(tokenStorageMode() === "localStorage" ? getStoredAccessToken() : null);
|
|
652
|
+
const headers = accessToken ? { authorization: `Bearer ${accessToken}` } : undefined;
|
|
650
653
|
const response = await fetch(rootEndpoint("/api/user/organizations"), {
|
|
654
|
+
headers,
|
|
651
655
|
credentials: fetchCredentials(),
|
|
652
656
|
});
|
|
653
657
|
if (!response.ok)
|
|
@@ -686,22 +690,44 @@ export async function getSessionInfo() {
|
|
|
686
690
|
};
|
|
687
691
|
}
|
|
688
692
|
export async function switchOrganization(organizationId, options = {}) {
|
|
689
|
-
const mode = options.mode || "
|
|
690
|
-
if (mode === "
|
|
691
|
-
const
|
|
693
|
+
const mode = options.mode || "token";
|
|
694
|
+
if (mode === "token") {
|
|
695
|
+
const current = getStoredSession();
|
|
696
|
+
const bearerToken = current?.accessToken;
|
|
697
|
+
if (!current || !bearerToken) {
|
|
698
|
+
await initiateLogin({ organizationId, returnTo: options.returnTo });
|
|
699
|
+
return null;
|
|
700
|
+
}
|
|
701
|
+
const response = await fetch(rootEndpoint("/api/token/organization"), {
|
|
692
702
|
method: "POST",
|
|
693
|
-
headers: {
|
|
703
|
+
headers: {
|
|
704
|
+
"content-type": "application/json",
|
|
705
|
+
authorization: `Bearer ${bearerToken}`,
|
|
706
|
+
},
|
|
694
707
|
body: JSON.stringify({
|
|
695
708
|
organization_id: organizationId,
|
|
696
|
-
return_to: options.returnTo,
|
|
697
709
|
client_id: cfg.clientId,
|
|
698
710
|
}),
|
|
699
711
|
credentials: fetchCredentials(),
|
|
700
712
|
});
|
|
701
713
|
if (!response.ok)
|
|
702
714
|
throw await errorForResponse(response);
|
|
703
|
-
await response.json()
|
|
704
|
-
|
|
715
|
+
const tokenResponse = await response.json();
|
|
716
|
+
const idToken = tokenResponse.id_token;
|
|
717
|
+
const accessToken = typeof tokenResponse.access_token === "string"
|
|
718
|
+
? tokenResponse.access_token
|
|
719
|
+
: undefined;
|
|
720
|
+
const refreshToken = refreshMode() === "token" ? tokenResponse.refresh_token : undefined;
|
|
721
|
+
return storeSession({
|
|
722
|
+
idToken,
|
|
723
|
+
accessToken,
|
|
724
|
+
drk: current.drk || EMPTY_DRK,
|
|
725
|
+
clientAppKey: current.clientAppKey,
|
|
726
|
+
rootKey: current.rootKey,
|
|
727
|
+
deliveredKeyKind: current.deliveredKeyKind,
|
|
728
|
+
keyDeliveryVersion: current.keyDeliveryVersion,
|
|
729
|
+
refreshToken,
|
|
730
|
+
});
|
|
705
731
|
}
|
|
706
732
|
if (mode === "authorize") {
|
|
707
733
|
await initiateLogin({ organizationId, returnTo: options.returnTo });
|