@svadmin/sso 0.11.1 → 0.11.3

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.
@@ -17,6 +17,8 @@ export interface SSOConfig {
17
17
  scopes?: string[];
18
18
  /** Where to redirect after logout */
19
19
  postLogoutRedirectUri?: string;
20
+ /** Optional public RP-initiated logout endpoint override. */
21
+ endSessionEndpoint?: string;
20
22
  /** Token storage backend. Default: 'local' (localStorage) */
21
23
  storage?: 'local' | 'session' | TokenStorage;
22
24
  /** Storage namespace. Defaults to an issuer/client-specific key. */
@@ -85,6 +85,9 @@ function readOptionalTokenString(response, field, fallback, fallbackMessage) {
85
85
  ? fallback
86
86
  : requireTokenString(response, field, fallbackMessage);
87
87
  }
88
+ function authorizationScheme(tokenType) {
89
+ return tokenType.toLowerCase() === 'bearer' ? 'Bearer' : tokenType;
90
+ }
88
91
  function normalizeTokenResponse(body, defaults, fallbackMessage) {
89
92
  const response = readTokenResponse(body, fallbackMessage);
90
93
  const accessToken = requireTokenString(response, 'access_token', fallbackMessage);
@@ -93,7 +96,7 @@ function normalizeTokenResponse(body, defaults, fallbackMessage) {
93
96
  id_token: typeof response.id_token === 'string' ? response.id_token : defaults.idToken,
94
97
  refresh_token: readOptionalTokenString(response, 'refresh_token', defaults.refreshToken, fallbackMessage),
95
98
  expires_at: getAccessTokenExpiry(response, accessToken),
96
- token_type: readOptionalTokenString(response, 'token_type', defaults.tokenType, fallbackMessage) ?? defaults.tokenType,
99
+ token_type: authorizationScheme(readOptionalTokenString(response, 'token_type', defaults.tokenType, fallbackMessage) ?? defaults.tokenType),
97
100
  };
98
101
  }
99
102
  function generateRandomString(length) {
@@ -210,7 +213,10 @@ export function createSSOAuthProvider(config) {
210
213
  if (oidcConfig)
211
214
  return oidcConfig;
212
215
  if (config.manualEndpoints) {
213
- oidcConfig = config.manualEndpoints;
216
+ oidcConfig = {
217
+ ...config.manualEndpoints,
218
+ ...(config.endSessionEndpoint ? { end_session_endpoint: config.endSessionEndpoint } : {}),
219
+ };
214
220
  return oidcConfig;
215
221
  }
216
222
  const url = `${config.issuer.replace(/\/$/, '')}/.well-known/openid-configuration`;
@@ -234,7 +240,10 @@ export function createSSOAuthProvider(config) {
234
240
  cause: error,
235
241
  });
236
242
  }
237
- oidcConfig = readOIDCConfig(discovered);
243
+ const discoveredConfig = readOIDCConfig(discovered);
244
+ oidcConfig = config.endSessionEndpoint
245
+ ? { ...discoveredConfig, end_session_endpoint: config.endSessionEndpoint }
246
+ : discoveredConfig;
238
247
  return oidcConfig;
239
248
  }
240
249
  async function requestToken(endpoint, body, fallbackMessage) {
@@ -343,7 +352,7 @@ export function createSSOAuthProvider(config) {
343
352
  const accessToken = await sessions.getAccessToken(options);
344
353
  const session = sessions.getSession();
345
354
  return accessToken && session?.access_token === accessToken
346
- ? `${session.token_type} ${accessToken}`
355
+ ? `${authorizationScheme(session.token_type)} ${accessToken}`
347
356
  : null;
348
357
  },
349
358
  };
@@ -407,15 +416,18 @@ export function createSSOAuthProvider(config) {
407
416
  sessions.clearSession();
408
417
  }
409
418
  try {
410
- const endpoints = await discover();
411
- if (typeof window !== 'undefined' && endpoints.end_session_endpoint && session?.id_token) {
412
- const params = new URLSearchParams({
413
- id_token_hint: session.id_token,
414
- ...(config.postLogoutRedirectUri
415
- ? { post_logout_redirect_uri: config.postLogoutRedirectUri }
416
- : {}),
417
- });
418
- window.location.href = `${endpoints.end_session_endpoint}?${params}`;
419
+ const endSessionEndpoint = config.endSessionEndpoint
420
+ ?? (await discover()).end_session_endpoint;
421
+ if (typeof window !== 'undefined' && endSessionEndpoint) {
422
+ const logoutUrl = new URL(endSessionEndpoint, window.location.href);
423
+ logoutUrl.searchParams.set('client_id', config.clientId);
424
+ logoutUrl.searchParams.delete('id_token_hint');
425
+ if (session?.id_token)
426
+ logoutUrl.searchParams.set('id_token_hint', session.id_token);
427
+ if (config.postLogoutRedirectUri) {
428
+ logoutUrl.searchParams.set('post_logout_redirect_uri', config.postLogoutRedirectUri);
429
+ }
430
+ window.location.href = logoutUrl.href;
419
431
  return { success: true };
420
432
  }
421
433
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@svadmin/sso",
3
- "version": "0.11.1",
3
+ "version": "0.11.3",
4
4
  "type": "module",
5
5
  "description": "OIDC/OAuth2 SSO AuthProvider plugin for svadmin — supports Okta, Azure AD, Cognito, Keycloak, Google",
6
6
  "license": "MIT",
@@ -32,10 +32,10 @@
32
32
  "dist"
33
33
  ],
34
34
  "peerDependencies": {
35
- "@svadmin/core": "^0.32.1"
35
+ "@svadmin/core": "^0.32.2"
36
36
  },
37
37
  "devDependencies": {
38
- "typescript": "^5.7.0"
38
+ "typescript": "^6.0.3"
39
39
  },
40
40
  "scripts": {
41
41
  "build": "bun ../../scripts/build-node-package.ts"