@sourceregistry/sveltekit-oidc 1.2.0 → 1.3.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 CHANGED
@@ -129,6 +129,7 @@ export async function load(event) {
129
129
  session={data.session}
130
130
  config={data.sessionManagement}
131
131
  logoutPath="/auth/logout"
132
+ monitorSession={false}
132
133
  redirectIfUnauthenticated={false}
133
134
  >
134
135
  <Account />
@@ -160,6 +161,10 @@ export async function load(event) {
160
161
  - periodic `invalidateAll()` revalidation so revoked server sessions are detected
161
162
  - a client context for nested auth-aware components through `useOIDC()` / `getOIDCContext()`
162
163
 
164
+ Set `monitorSession={false}` when you want to keep the client context but leave remote session
165
+ revocation checks to your server-side guard or another mechanism. This disables
166
+ `check_session_iframe` polling without changing the provider metadata exposed through the context.
167
+
163
168
  ## Typed Custom Claims
164
169
 
165
170
  `createOIDC` infers a `TClaims` type from whatever `transformClaims` / `transformUser` / `transformSession` return, and threads it through the session, `event.locals.oidc`, `OIDCPublicSession`, and the client context — no casts needed.
@@ -230,6 +235,57 @@ Now `event.locals.oidc?.claims?.roles` is `string[]` and `?.tenant` is `string |
230
235
 
231
236
  If `transformClaims` (and friends) are omitted, `TClaims` defaults to `OIDCUserClaims` — existing setups keep working unchanged.
232
237
 
238
+ ## Typed Custom Session
239
+
240
+ Backend apps commonly stash application-specific data on the session itself (e.g. `tenantId`, `permissions`) — not just inside `claims`/`user`. A second generic, `TSession`, is inferred from `transformSession`'s return type and threads through the session store, cookies, `event.locals.oidc`, and `handleCallback`'s result — again with no casts:
241
+
242
+ ```ts
243
+ // src/lib/server/auth.ts
244
+ import { createOIDC, type OIDCSession } from 'sveltekit-oidc/server';
245
+
246
+ type AppSession = OIDCSession<AppClaims> & {
247
+ tenantId: string;
248
+ permissions: string[];
249
+ };
250
+
251
+ export const oidc = createOIDC({
252
+ issuer: 'https://your-idp.example.com',
253
+ clientId: process.env.OIDC_CLIENT_ID!,
254
+ cookieSecret: process.env.OIDC_COOKIE_SECRET!,
255
+ transformClaims: (claims) => ({ ...claims, tenant: claims.tenant as string | undefined }),
256
+ transformSession: (session): AppSession => ({
257
+ ...session,
258
+ tenantId: session.claims?.tenant ?? 'default',
259
+ permissions: session.user?.roles ?? []
260
+ })
261
+ });
262
+ ```
263
+
264
+ Extract the inferred type with `OIDCInferSession` and apply it alongside `OIDCInferClaims`:
265
+
266
+ ```ts
267
+ // src/app.d.ts
268
+ import type { OIDCHandleLocals, OIDCInferClaims, OIDCInferSession } from 'sveltekit-oidc/server';
269
+ import { oidc } from '$lib/server/auth';
270
+
271
+ export type AppClaims = OIDCInferClaims<typeof oidc>;
272
+ export type AppSession = OIDCInferSession<typeof oidc>;
273
+
274
+ declare global {
275
+ namespace App {
276
+ interface Locals {
277
+ oidc?: OIDCHandleLocals<AppClaims, AppSession>;
278
+ }
279
+ }
280
+ }
281
+
282
+ export {};
283
+ ```
284
+
285
+ Now `event.locals.oidc?.session?.tenantId` is `string` and `?.permissions` is `string[]` everywhere — and `oidc.requireAuth(event)` / `handleCallback`'s `onsuccess` resolve to `AppSession` directly.
286
+
287
+ If `transformSession` is omitted, `TSession` defaults to `OIDCSession<TClaims>` — existing setups keep working unchanged.
288
+
233
289
  ## Example App
234
290
 
235
291
  This repository now includes a runnable example under [src/routes](C:/Users/alexa/WebstormProjects/github.com/SourceRegistry/sveltekit-oidc/src/routes) and [src/hooks.server.ts](C:/Users/alexa/WebstormProjects/github.com/SourceRegistry/sveltekit-oidc/src/hooks.server.ts).
@@ -251,6 +307,6 @@ Set these environment variables to enable it:
251
307
  - The library validates `id_token` and `logout_token` values through `@sourceregistry/node-jwt` and provider JWKS metadata.
252
308
  - `groups` are normalized onto the session from `groups` and `roles` claims when present.
253
309
  - Use `transformClaims`, `transformUser`, and `transformSession` to project provider-specific claims into your own session shape.
254
- - `check_session_iframe` monitoring only runs when the provider advertises that endpoint and the session includes `session_state`.
310
+ - `check_session_iframe` monitoring only runs when `monitorSession` is enabled, the provider advertises that endpoint, and the session includes `session_state`.
255
311
  - Refresh token handling is automatic when a valid refresh token is present.
256
312
  - `event.locals.oidc` is attached by the hook and typed via `OIDCHandleLocals<TClaims>`; see [Typed Custom Claims](#typed-custom-claims) for wiring your own claim shapes through `app.d.ts`.
@@ -1,212 +1,216 @@
1
+ <script lang="ts" module>
2
+ import type {
3
+ OIDCPublicSession,
4
+ OIDCSessionManagementConfig, OIDCUserClaims
5
+ } from '../server/index.js';
6
+ </script>
7
+
1
8
  <script lang="ts" generics="TClaims extends OIDCUserClaims = OIDCUserClaims">
2
- import { goto, invalidateAll } from '$app/navigation';
3
- import type { Snippet } from 'svelte';
4
-
5
- import { setOIDCContext } from './context.js';
6
- import type {
7
- OIDCPublicSession,
8
- OIDCSessionManagementConfig,
9
- OIDCUserClaims
10
- } from '../server/index.js';
11
-
12
- type RedirectMode = 'login' | 'logout' | 'reload' | 'none';
13
-
14
- let {
15
- session = null,
16
- config,
17
- loginPath,
18
- logoutPath = '/auth/logout',
19
- checkSessionIntervalMs = 5000,
20
- revalidateIntervalMs = 30000,
21
- redirectOnExpired = 'login',
22
- redirectOnRevoked = 'login',
23
- redirectIfUnauthenticated = false,
24
- children
25
- }: {
26
- session?: OIDCPublicSession<TClaims> | null;
27
- config: OIDCSessionManagementConfig;
28
- loginPath?: string;
29
- logoutPath?: string;
30
- checkSessionIntervalMs?: number;
31
- revalidateIntervalMs?: number;
32
- redirectOnExpired?: RedirectMode;
33
- redirectOnRevoked?: RedirectMode;
34
- redirectIfUnauthenticated?: boolean;
35
- children?: Snippet;
36
- } = $props();
37
-
38
- let iframe = $state<HTMLIFrameElement | undefined>(undefined);
39
- let status = $state<'authenticated' | 'unauthenticated' | 'expired' | 'revoked'>('unauthenticated');
40
- let handledUnauthenticated = $state(false);
41
-
42
- const metadata = $derived(config.metadata);
43
- const resolvedLoginPath = $derived(loginPath ?? config.loginPath ?? '/auth/login');
44
- const iframeUrl = $derived(
45
- config.metadata.check_session_iframe ?? config.checkSessionIframe ?? undefined
46
- );
47
- const canMonitorIframe = $derived(
48
- Boolean(session?.isAuthenticated && session?.sessionState && iframeUrl)
49
- );
50
-
51
- const context = setOIDCContext<TClaims>({
52
- get isAuthenticated() {
53
- return Boolean(session?.isAuthenticated);
54
- },
55
- get session() {
56
- return session;
57
- },
58
- get user() {
59
- return session?.user;
60
- },
61
- get claims() {
62
- return session?.claims;
63
- },
64
- get groups() {
65
- return session?.groups ?? [];
66
- },
67
- get metadata() {
68
- return metadata;
69
- },
70
- get status() {
71
- return status;
72
- },
73
- login: (returnTo?: string) => login(returnTo),
74
- logout,
75
- revalidate
76
- });
77
-
78
- void context;
79
-
80
- function buildLoginUrl(returnTo = `${window.location.pathname}${window.location.search}`) {
81
- return `${resolvedLoginPath}?returnTo=${encodeURIComponent(returnTo)}`;
82
- }
83
-
84
- async function logout(clearSessionOnly = false) {
85
- const body = new URLSearchParams();
86
- if (clearSessionOnly) {
87
- body.set('clearSessionOnly', '1');
88
- }
89
-
90
- await fetch(logoutPath, {
91
- method: 'POST',
92
- headers: {
93
- 'content-type': 'application/x-www-form-urlencoded'
94
- },
95
- body
96
- });
97
- }
98
-
99
- function login(returnTo?: string) {
100
- void goto(buildLoginUrl(returnTo), { invalidateAll: false });
101
- }
102
-
103
- async function revalidate() {
104
- await invalidateAll();
105
- }
106
-
107
- async function handleRedirect(mode: RedirectMode) {
108
- if (mode === 'none') {
109
- return;
110
- }
111
- if (mode === 'reload') {
112
- window.location.reload();
113
- return;
114
- }
115
- if (mode === 'logout') {
116
- await logout(true);
117
- window.location.reload();
118
- return;
119
- }
120
-
121
- login();
122
- }
123
-
124
- $effect(() => {
125
- const isAuthenticated = Boolean(session?.isAuthenticated);
126
- status = isAuthenticated ? 'authenticated' : status === 'authenticated' ? 'unauthenticated' : status;
127
- });
128
-
129
- $effect(() => {
130
- if (!session?.isAuthenticated || !session.expiresAt) {
131
- return;
132
- }
133
-
134
- const timeoutMs = Math.max(0, session.expiresAt * 1000 - Date.now());
135
- const timer = window.setTimeout(() => {
136
- status = 'expired';
137
- void handleRedirect(redirectOnExpired);
138
- }, timeoutMs);
139
-
140
- return () => window.clearTimeout(timer);
141
- });
142
-
143
- $effect(() => {
144
- if (!session?.isAuthenticated || !revalidateIntervalMs) {
145
- return;
146
- }
147
-
148
- const timer = window.setInterval(() => {
149
- void revalidate();
150
- }, revalidateIntervalMs);
151
-
152
- return () => window.clearInterval(timer);
153
- });
154
-
155
- $effect(() => {
156
- if (session?.isAuthenticated) {
157
- handledUnauthenticated = false;
158
- return;
159
- }
160
- if (!redirectIfUnauthenticated || handledUnauthenticated) {
161
- return;
162
- }
163
-
164
- handledUnauthenticated = true;
165
- status = status === 'expired' || status === 'revoked' ? status : 'unauthenticated';
166
- void handleRedirect(status === 'revoked' ? redirectOnRevoked : redirectOnExpired);
167
- });
168
-
169
- $effect(() => {
170
- if (!canMonitorIframe || !iframeUrl || !iframe) {
171
- return;
172
- }
173
-
174
- const targetOrigin = new URL(iframeUrl).origin;
175
- const poll = window.setInterval(() => {
176
- if (!iframe?.contentWindow || !session?.sessionState) {
177
- return;
178
- }
179
-
180
- iframe.contentWindow.postMessage(`${config.clientId} ${session.sessionState}`, targetOrigin);
181
- }, checkSessionIntervalMs);
182
-
183
- const onMessage = (event: MessageEvent) => {
184
- if (event.origin !== targetOrigin || typeof event.data !== 'string') {
185
- return;
186
- }
187
- if (event.data === 'changed' || event.data === 'error') {
188
- status = 'revoked';
189
- void logout(true).then(() => handleRedirect(redirectOnRevoked));
190
- }
191
- };
192
-
193
- window.addEventListener('message', onMessage);
194
-
195
- return () => {
196
- window.clearInterval(poll);
197
- window.removeEventListener('message', onMessage);
198
- };
199
- });
9
+ import {goto, invalidateAll} from '$app/navigation';
10
+ import type {Snippet} from 'svelte';
11
+
12
+ import {setOIDCContext} from './context.js';
13
+
14
+ type RedirectMode = 'login' | 'logout' | 'reload' | 'none';
15
+
16
+ let {
17
+ session = null,
18
+ config,
19
+ loginPath,
20
+ logoutPath = '/auth/logout',
21
+ checkSessionIntervalMs = 5000,
22
+ monitorSession = true,
23
+ revalidateIntervalMs = 30000,
24
+ redirectOnExpired = 'login',
25
+ redirectOnRevoked = 'login',
26
+ redirectIfUnauthenticated = false,
27
+ children
28
+ }: {
29
+ session?: OIDCPublicSession<TClaims> | null;
30
+ config: OIDCSessionManagementConfig;
31
+ loginPath?: string;
32
+ logoutPath?: string;
33
+ checkSessionIntervalMs?: number;
34
+ monitorSession?: boolean;
35
+ revalidateIntervalMs?: number;
36
+ redirectOnExpired?: RedirectMode;
37
+ redirectOnRevoked?: RedirectMode;
38
+ redirectIfUnauthenticated?: boolean;
39
+ children?: Snippet;
40
+ } = $props();
41
+
42
+ let iframe = $state<HTMLIFrameElement | undefined>(undefined);
43
+ let status = $state<'authenticated' | 'unauthenticated' | 'expired' | 'revoked'>('unauthenticated');
44
+ let handledUnauthenticated = $state(false);
45
+
46
+ const metadata = $derived(config.metadata);
47
+ const resolvedLoginPath = $derived(loginPath ?? config.loginPath ?? '/auth/login');
48
+ const iframeUrl = $derived(
49
+ config.metadata.check_session_iframe ?? config.checkSessionIframe ?? undefined
50
+ );
51
+ const canMonitorIframe = $derived(
52
+ Boolean(monitorSession && session?.isAuthenticated && session?.sessionState && iframeUrl)
53
+ );
54
+
55
+ const context = setOIDCContext<TClaims>({
56
+ get isAuthenticated() {
57
+ return Boolean(session?.isAuthenticated);
58
+ },
59
+ get session() {
60
+ return session;
61
+ },
62
+ get user() {
63
+ return session?.user;
64
+ },
65
+ get claims() {
66
+ return session?.claims;
67
+ },
68
+ get groups() {
69
+ return session?.groups ?? [];
70
+ },
71
+ get metadata() {
72
+ return metadata;
73
+ },
74
+ get status() {
75
+ return status;
76
+ },
77
+ login: (returnTo?: string) => login(returnTo),
78
+ logout,
79
+ revalidate
80
+ });
81
+
82
+ void context;
83
+
84
+ function buildLoginUrl(returnTo = `${window.location.pathname}${window.location.search}`) {
85
+ return `${resolvedLoginPath}?returnTo=${encodeURIComponent(returnTo)}`;
86
+ }
87
+
88
+ async function logout(clearSessionOnly = false) {
89
+ const body = new URLSearchParams();
90
+ if (clearSessionOnly) {
91
+ body.set('clearSessionOnly', '1');
92
+ }
93
+
94
+ await fetch(logoutPath, {
95
+ method: 'POST',
96
+ headers: {
97
+ 'content-type': 'application/x-www-form-urlencoded'
98
+ },
99
+ body
100
+ });
101
+ }
102
+
103
+ function login(returnTo?: string) {
104
+ void goto(buildLoginUrl(returnTo), {invalidateAll: false});
105
+ }
106
+
107
+ async function revalidate() {
108
+ await invalidateAll();
109
+ }
110
+
111
+ async function handleRedirect(mode: RedirectMode) {
112
+ if (mode === 'none') {
113
+ return;
114
+ }
115
+ if (mode === 'reload') {
116
+ window.location.reload();
117
+ return;
118
+ }
119
+ if (mode === 'logout') {
120
+ await logout(true);
121
+ window.location.reload();
122
+ return;
123
+ }
124
+
125
+ login();
126
+ }
127
+
128
+ $effect(() => {
129
+ const isAuthenticated = Boolean(session?.isAuthenticated);
130
+ status = isAuthenticated ? 'authenticated' : status === 'authenticated' ? 'unauthenticated' : status;
131
+ });
132
+
133
+ $effect(() => {
134
+ if (!session?.isAuthenticated || !session.expiresAt) {
135
+ return;
136
+ }
137
+
138
+ const timeoutMs = Math.max(0, session.expiresAt * 1000 - Date.now());
139
+ const timer = window.setTimeout(() => {
140
+ status = 'expired';
141
+ void handleRedirect(redirectOnExpired);
142
+ }, timeoutMs);
143
+
144
+ return () => window.clearTimeout(timer);
145
+ });
146
+
147
+ $effect(() => {
148
+ if (!session?.isAuthenticated || !revalidateIntervalMs) {
149
+ return;
150
+ }
151
+
152
+ const timer = window.setInterval(() => {
153
+ void revalidate();
154
+ }, revalidateIntervalMs);
155
+
156
+ return () => window.clearInterval(timer);
157
+ });
158
+
159
+ $effect(() => {
160
+ if (session?.isAuthenticated) {
161
+ handledUnauthenticated = false;
162
+ return;
163
+ }
164
+ if (!redirectIfUnauthenticated || handledUnauthenticated) {
165
+ return;
166
+ }
167
+
168
+ handledUnauthenticated = true;
169
+ status = status === 'expired' || status === 'revoked' ? status : 'unauthenticated';
170
+ void handleRedirect(status === 'revoked' ? redirectOnRevoked : redirectOnExpired);
171
+ });
172
+
173
+ $effect(() => {
174
+ if (!canMonitorIframe || !iframeUrl || !iframe) {
175
+ return;
176
+ }
177
+
178
+ const targetOrigin = new URL(iframeUrl).origin;
179
+ const poll = window.setInterval(() => {
180
+ if (!iframe?.contentWindow || !session?.sessionState) {
181
+ return;
182
+ }
183
+
184
+ iframe.contentWindow.postMessage(`${config.clientId} ${session.sessionState}`, targetOrigin);
185
+ }, checkSessionIntervalMs);
186
+
187
+ const onMessage = (event: MessageEvent) => {
188
+ if (event.origin !== targetOrigin || typeof event.data !== 'string') {
189
+ return;
190
+ }
191
+ if (event.data === 'changed' || event.data === 'error') {
192
+ status = 'revoked';
193
+ void logout(true).then(() => handleRedirect(redirectOnRevoked));
194
+ }
195
+ };
196
+
197
+ window.addEventListener('message', onMessage);
198
+
199
+ return () => {
200
+ window.clearInterval(poll);
201
+ window.removeEventListener('message', onMessage);
202
+ };
203
+ });
200
204
  </script>
201
205
 
202
206
  {#if canMonitorIframe && iframeUrl}
203
- <iframe
204
- bind:this={iframe}
205
- title="OIDC session monitor"
206
- src={iframeUrl}
207
- hidden
208
- aria-hidden="true"
209
- ></iframe>
207
+ <iframe
208
+ bind:this={iframe}
209
+ title="OIDC session monitor"
210
+ src={iframeUrl}
211
+ hidden
212
+ aria-hidden="true"
213
+ ></iframe>
210
214
  {/if}
211
215
 
212
216
  {@render children?.()}
@@ -1,5 +1,5 @@
1
- import type { Snippet } from 'svelte';
2
1
  import type { OIDCPublicSession, OIDCSessionManagementConfig, OIDCUserClaims } from '../server/index.js';
2
+ import type { Snippet } from 'svelte';
3
3
  declare function $$render<TClaims extends OIDCUserClaims = OIDCUserClaims>(): {
4
4
  props: {
5
5
  session?: OIDCPublicSession<TClaims> | null;
@@ -7,6 +7,7 @@ declare function $$render<TClaims extends OIDCUserClaims = OIDCUserClaims>(): {
7
7
  loginPath?: string;
8
8
  logoutPath?: string;
9
9
  checkSessionIntervalMs?: number;
10
+ monitorSession?: boolean;
10
11
  revalidateIntervalMs?: number;
11
12
  redirectOnExpired?: "none" | "login" | "logout" | "reload";
12
13
  redirectOnRevoked?: "none" | "login" | "logout" | "reload";
@@ -1,2 +1,2 @@
1
- import type { CookieOptions, OIDCCookies, OIDCUserClaims } from './types.js';
2
- export declare function createOIDCCookieStore<TClaims extends OIDCUserClaims = OIDCUserClaims>(cookieSecret: string, sessionCookieName: string, stateCookieName: string, cookieOptions: CookieOptions): OIDCCookies<TClaims>;
1
+ import type { CookieOptions, OIDCCookies, OIDCSession, OIDCUserClaims } from './types.js';
2
+ export declare function createOIDCCookieStore<TClaims extends OIDCUserClaims = OIDCUserClaims, TSession extends OIDCSession<TClaims> = OIDCSession<TClaims>>(cookieSecret: string, sessionCookieName: string, stateCookieName: string, cookieOptions: CookieOptions): OIDCCookies<TClaims, TSession>;
@@ -1,5 +1,5 @@
1
- import type { OIDCOptions, OIDCInstance, OIDCUserClaims } from './types.js';
1
+ import type { OIDCOptions, OIDCInstance, OIDCSession, OIDCUserClaims } from './types.js';
2
2
  export type * from './types.js';
3
3
  export { createInMemoryBackChannelLogoutStore, createInMemorySessionStore } from './store.js';
4
- export declare function createOIDC<TClaims extends OIDCUserClaims = OIDCUserClaims>(options: OIDCOptions<TClaims>): OIDCInstance<TClaims>;
4
+ export declare function createOIDC<TClaims extends OIDCUserClaims = OIDCUserClaims, TSession extends OIDCSession<TClaims> = OIDCSession<TClaims>>(options: OIDCOptions<TClaims, TSession>): OIDCInstance<TClaims, TSession>;
5
5
  export declare const OpenIDConnect: typeof createOIDC;
@@ -1,3 +1,3 @@
1
- import type { OIDCBackChannelLogoutStore, OIDCSessionStore, OIDCUserClaims } from './types.js';
2
- export declare function createInMemoryBackChannelLogoutStore<TClaims extends OIDCUserClaims = OIDCUserClaims>(): OIDCBackChannelLogoutStore<TClaims>;
3
- export declare function createInMemorySessionStore<TClaims extends OIDCUserClaims = OIDCUserClaims>(): OIDCSessionStore<TClaims>;
1
+ import type { OIDCBackChannelLogoutStore, OIDCSession, OIDCSessionStore, OIDCUserClaims } from './types.js';
2
+ export declare function createInMemoryBackChannelLogoutStore<TClaims extends OIDCUserClaims = OIDCUserClaims, TSession extends OIDCSession<TClaims> = OIDCSession<TClaims>>(): OIDCBackChannelLogoutStore<TClaims, TSession>;
3
+ export declare function createInMemorySessionStore<TClaims extends OIDCUserClaims = OIDCUserClaims, TSession extends OIDCSession<TClaims> = OIDCSession<TClaims>>(): OIDCSessionStore<TClaims, TSession>;
@@ -114,13 +114,13 @@ export type OIDCBackChannelLogoutRecord = {
114
114
  jti: string;
115
115
  iat: number;
116
116
  };
117
- export type OIDCBackChannelLogoutStore<TClaims extends OIDCUserClaims = OIDCUserClaims> = {
117
+ export type OIDCBackChannelLogoutStore<TClaims extends OIDCUserClaims = OIDCUserClaims, TSession extends OIDCSession<TClaims> = OIDCSession<TClaims>> = {
118
118
  revoke(record: OIDCBackChannelLogoutRecord): MaybePromise<void>;
119
- isRevoked(session: OIDCSession<TClaims>): MaybePromise<boolean>;
119
+ isRevoked(session: TSession): MaybePromise<boolean>;
120
120
  };
121
- export type OIDCSessionStore<TClaims extends OIDCUserClaims = OIDCUserClaims> = {
122
- get(sessionId: string): MaybePromise<OIDCSession<TClaims> | null>;
123
- set(sessionId: string, session: OIDCSession<TClaims>): MaybePromise<void>;
121
+ export type OIDCSessionStore<TClaims extends OIDCUserClaims = OIDCUserClaims, TSession extends OIDCSession<TClaims> = OIDCSession<TClaims>> = {
122
+ get(sessionId: string): MaybePromise<TSession | null>;
123
+ set(sessionId: string, session: TSession): MaybePromise<void>;
124
124
  delete(sessionId: string): MaybePromise<void>;
125
125
  };
126
126
  export type OIDCSessionManagementConfig = {
@@ -133,7 +133,7 @@ export type OIDCSessionManagementConfig = {
133
133
  backChannelLogoutSupported: boolean;
134
134
  backChannelLogoutSessionSupported: boolean;
135
135
  };
136
- export type OIDCOptions<TClaims extends OIDCUserClaims = OIDCUserClaims> = {
136
+ export type OIDCOptions<TClaims extends OIDCUserClaims = OIDCUserClaims, TSession extends OIDCSession<TClaims> = OIDCSession<TClaims>> = {
137
137
  issuer?: string;
138
138
  discoveryUrl?: string;
139
139
  clientId: string;
@@ -155,8 +155,8 @@ export type OIDCOptions<TClaims extends OIDCUserClaims = OIDCUserClaims> = {
155
155
  refreshToleranceSeconds?: number;
156
156
  defaultLoginRedirect?: string;
157
157
  defaultLogoutRedirect?: string;
158
- sessionStore?: OIDCSessionStore<TClaims>;
159
- backChannelLogoutStore?: OIDCBackChannelLogoutStore<TClaims>;
158
+ sessionStore?: OIDCSessionStore<TClaims, TSession>;
159
+ backChannelLogoutStore?: OIDCBackChannelLogoutStore<TClaims, TSession>;
160
160
  transformClaims?: (claims: OIDCUserClaims) => MaybePromise<TClaims>;
161
161
  transformUser?: (user: OIDCUserClaims | undefined, context: {
162
162
  claims?: TClaims;
@@ -167,7 +167,7 @@ export type OIDCOptions<TClaims extends OIDCUserClaims = OIDCUserClaims> = {
167
167
  claims?: TClaims;
168
168
  user?: TClaims;
169
169
  isRefresh: boolean;
170
- }) => MaybePromise<OIDCSession<TClaims>>;
170
+ }) => MaybePromise<TSession>;
171
171
  endpoints?: Partial<OIDCDiscoveryDocument>;
172
172
  };
173
173
  export type OIDCLoginOptions = {
@@ -181,16 +181,16 @@ export type OIDCLogoutOptions = {
181
181
  state?: string;
182
182
  clearSessionOnly?: boolean;
183
183
  };
184
- export type OIDCCallbackResult<TClaims extends OIDCUserClaims = OIDCUserClaims> = {
185
- session: OIDCSession<TClaims>;
184
+ export type OIDCCallbackResult<TClaims extends OIDCUserClaims = OIDCUserClaims, TSession extends OIDCSession<TClaims> = OIDCSession<TClaims>> = {
185
+ session: TSession;
186
186
  returnTo: string;
187
187
  };
188
- export type OIDCHandleLocals<TClaims extends OIDCUserClaims = OIDCUserClaims> = {
188
+ export type OIDCHandleLocals<TClaims extends OIDCUserClaims = OIDCUserClaims, TSession extends OIDCSession<TClaims> = OIDCSession<TClaims>> = {
189
189
  isAuthenticated: boolean;
190
- session: OIDCSession<TClaims> | null;
190
+ session: TSession | null;
191
191
  user?: TClaims;
192
192
  claims?: TClaims;
193
- requireAuth: () => Promise<OIDCSession<TClaims>>;
193
+ requireAuth: () => Promise<TSession>;
194
194
  clearSession: () => Promise<void>;
195
195
  };
196
196
  export type OIDCStateCookie = {
@@ -200,8 +200,8 @@ export type OIDCStateCookie = {
200
200
  returnTo: string;
201
201
  createdAt: number;
202
202
  };
203
- export type OIDCCallbackHandlerOptions<TClaims extends OIDCUserClaims = OIDCUserClaims> = {
204
- onsuccess?: (event: RequestEvent, result: OIDCCallbackResult<TClaims>) => MaybePromise<Response | void>;
203
+ export type OIDCCallbackHandlerOptions<TClaims extends OIDCUserClaims = OIDCUserClaims, TSession extends OIDCSession<TClaims> = OIDCSession<TClaims>> = {
204
+ onsuccess?: (event: RequestEvent, result: OIDCCallbackResult<TClaims, TSession>) => MaybePromise<Response | void>;
205
205
  onfailure?: (event: RequestEvent, err: unknown) => MaybePromise<Response | void>;
206
206
  redirectTo?: string;
207
207
  };
@@ -214,9 +214,9 @@ export type OIDCClientAssertionOptions = {
214
214
  clientId: string;
215
215
  clientSecret?: string;
216
216
  };
217
- export type OIDCCookies<TClaims extends OIDCUserClaims = OIDCUserClaims> = {
218
- readSession(cookies: Cookies): OIDCSession<TClaims> | null;
219
- writeSession(cookies: Cookies, session: OIDCSession<TClaims>): void;
217
+ export type OIDCCookies<TClaims extends OIDCUserClaims = OIDCUserClaims, TSession extends OIDCSession<TClaims> = OIDCSession<TClaims>> = {
218
+ readSession(cookies: Cookies): TSession | null;
219
+ writeSession(cookies: Cookies, session: TSession): void;
220
220
  clearSession(cookies: Cookies): void;
221
221
  readSessionReference(cookies: Cookies): {
222
222
  id: string;
@@ -229,29 +229,30 @@ export type OIDCCookies<TClaims extends OIDCUserClaims = OIDCUserClaims> = {
229
229
  writeState(cookies: Cookies, state: OIDCStateCookie): void;
230
230
  clearState(cookies: Cookies): void;
231
231
  };
232
- export type OIDCPersistedSession<TClaims extends OIDCUserClaims = OIDCUserClaims> = {
232
+ export type OIDCPersistedSession<TClaims extends OIDCUserClaims = OIDCUserClaims, TSession extends OIDCSession<TClaims> = OIDCSession<TClaims>> = {
233
233
  id?: string;
234
- session: OIDCSession<TClaims>;
234
+ session: TSession;
235
235
  };
236
- export type OIDCInstance<TClaims extends OIDCUserClaims = OIDCUserClaims> = {
236
+ export type OIDCInstance<TClaims extends OIDCUserClaims = OIDCUserClaims, TSession extends OIDCSession<TClaims> = OIDCSession<TClaims>> = {
237
237
  handle: Handle;
238
238
  getMetadata: () => Promise<OIDCDiscoveryDocument>;
239
- getSession: (event: RequestEvent) => Promise<OIDCSession<TClaims> | null>;
239
+ getSession: (event: RequestEvent) => Promise<TSession | null>;
240
240
  getPublicSession: (event: RequestEvent) => Promise<OIDCPublicSession<TClaims> | null>;
241
241
  getSessionManagementConfig: () => Promise<OIDCSessionManagementConfig>;
242
242
  login: (event: RequestEvent, loginOptions?: OIDCLoginOptions) => Promise<never>;
243
243
  logout: (event: RequestEvent, logoutOptions?: OIDCLogoutOptions) => Promise<never>;
244
- handleCallback: (event: RequestEvent) => Promise<OIDCCallbackResult<TClaims>>;
244
+ handleCallback: (event: RequestEvent) => Promise<OIDCCallbackResult<TClaims, TSession>>;
245
245
  handleBackChannelLogout: (event: RequestEvent) => Promise<Response>;
246
246
  loginHandler: (defaults?: OIDCLoginOptions) => RequestHandler;
247
- callbackHandler: (handlerOptions?: OIDCCallbackHandlerOptions<TClaims>) => RequestHandler;
247
+ callbackHandler: (handlerOptions?: OIDCCallbackHandlerOptions<TClaims, TSession>) => RequestHandler;
248
248
  logoutHandler: (defaults?: OIDCLogoutOptions) => RequestHandler;
249
249
  backChannelLogoutHandler: () => RequestHandler;
250
250
  createActions: (actionOptions?: OIDCActionOptions) => Readonly<{
251
251
  login: Action;
252
252
  logout: Action;
253
253
  }>;
254
- requireAuth: (event: RequestEvent, returnTo?: string) => Promise<OIDCSession<TClaims>>;
254
+ requireAuth: (event: RequestEvent, returnTo?: string) => Promise<TSession>;
255
255
  clearSession: (cookies: Cookies) => Promise<void>;
256
256
  };
257
257
  export type OIDCInferClaims<T> = T extends OIDCInstance<infer TClaims> ? TClaims : OIDCUserClaims;
258
+ export type OIDCInferSession<T> = T extends OIDCInstance<infer _TClaims, infer TSession> ? TSession : OIDCSession<OIDCUserClaims>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sourceregistry/sveltekit-oidc",
3
- "version": "1.2.0",
4
- "description": "OIDC authentication helpers for SvelteKit applications.",
3
+ "version": "1.3.1",
4
+ "description": "OIDC authentication helpers for SvelteKit applications",
5
5
  "license": "Apache-2.0",
6
6
  "scripts": {
7
7
  "dev": "vite dev",