@sourceregistry/sveltekit-oidc 1.3.0 → 1.4.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 +36 -34
- package/dist/client/OIDCContext.svelte +3 -1
- package/dist/client/OIDCContext.svelte.d.ts +1 -0
- package/dist/server/index.js +41 -12
- package/dist/server/types.d.ts +12 -4
- package/dist/server/utils.d.ts +1 -1
- package/dist/server/utils.js +4 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -19,10 +19,7 @@ npm install sveltekit-oidc
|
|
|
19
19
|
|
|
20
20
|
```ts
|
|
21
21
|
// src/lib/server/auth.ts
|
|
22
|
-
import {
|
|
23
|
-
createInMemoryBackChannelLogoutStore,
|
|
24
|
-
createOIDC
|
|
25
|
-
} from 'sveltekit-oidc/server';
|
|
22
|
+
import { createOIDC } from 'sveltekit-oidc/server';
|
|
26
23
|
|
|
27
24
|
export const oidc = createOIDC({
|
|
28
25
|
issuer: 'https://your-idp.example.com',
|
|
@@ -32,22 +29,8 @@ export const oidc = createOIDC({
|
|
|
32
29
|
clientAuthMethod: 'client_secret_basic',
|
|
33
30
|
loginPath: '/auth/login',
|
|
34
31
|
redirectPath: '/auth/callback',
|
|
35
|
-
scope:
|
|
36
|
-
|
|
37
|
-
fetchUserInfo: true,
|
|
38
|
-
backChannelLogoutStore: createInMemoryBackChannelLogoutStore(),
|
|
39
|
-
transformSession(session) {
|
|
40
|
-
return {
|
|
41
|
-
...session,
|
|
42
|
-
groups: session.groups,
|
|
43
|
-
user: session.user
|
|
44
|
-
? {
|
|
45
|
-
...session.user,
|
|
46
|
-
groups: session.groups
|
|
47
|
-
}
|
|
48
|
-
: session.user
|
|
49
|
-
};
|
|
50
|
-
},
|
|
32
|
+
scope: 'openid profile email offline_access',
|
|
33
|
+
backChannelLogoutStore: 'memory',
|
|
51
34
|
cookieOptions: {
|
|
52
35
|
secure: process.env.NODE_ENV === 'production'
|
|
53
36
|
}
|
|
@@ -129,6 +112,7 @@ export async function load(event) {
|
|
|
129
112
|
session={data.session}
|
|
130
113
|
config={data.sessionManagement}
|
|
131
114
|
logoutPath="/auth/logout"
|
|
115
|
+
monitorSession={false}
|
|
132
116
|
redirectIfUnauthenticated={false}
|
|
133
117
|
>
|
|
134
118
|
<Account />
|
|
@@ -160,6 +144,10 @@ export async function load(event) {
|
|
|
160
144
|
- periodic `invalidateAll()` revalidation so revoked server sessions are detected
|
|
161
145
|
- a client context for nested auth-aware components through `useOIDC()` / `getOIDCContext()`
|
|
162
146
|
|
|
147
|
+
Set `monitorSession={false}` when you want to keep the client context but leave remote session
|
|
148
|
+
revocation checks to your server-side guard or another mechanism. This disables
|
|
149
|
+
`check_session_iframe` polling without changing the provider metadata exposed through the context.
|
|
150
|
+
|
|
163
151
|
## Typed Custom Claims
|
|
164
152
|
|
|
165
153
|
`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.
|
|
@@ -178,19 +166,17 @@ export const oidc = createOIDC({
|
|
|
178
166
|
});
|
|
179
167
|
```
|
|
180
168
|
|
|
181
|
-
|
|
169
|
+
Wire `App.Locals` so `event.locals.oidc` is fully typed everywhere — `OIDCLocals` infers everything directly from the instance:
|
|
182
170
|
|
|
183
171
|
```ts
|
|
184
172
|
// src/app.d.ts
|
|
185
|
-
import type {
|
|
173
|
+
import type { OIDCLocals } from 'sveltekit-oidc/server';
|
|
186
174
|
import { oidc } from '$lib/server/auth';
|
|
187
175
|
|
|
188
|
-
export type AppClaims = OIDCInferClaims<typeof oidc>;
|
|
189
|
-
|
|
190
176
|
declare global {
|
|
191
177
|
namespace App {
|
|
192
178
|
interface Locals {
|
|
193
|
-
oidc?:
|
|
179
|
+
oidc?: OIDCLocals<typeof oidc>;
|
|
194
180
|
}
|
|
195
181
|
}
|
|
196
182
|
}
|
|
@@ -198,7 +184,16 @@ declare global {
|
|
|
198
184
|
export {};
|
|
199
185
|
```
|
|
200
186
|
|
|
201
|
-
Now `event.locals.oidc?.claims?.roles` is `string[]` and `?.tenant` is `string | undefined` in every hook, load function, and action.
|
|
187
|
+
Now `event.locals.oidc?.claims?.roles` is `string[]` and `?.tenant` is `string | undefined` in every hook, load function, and action — no separate type aliases needed.
|
|
188
|
+
|
|
189
|
+
When you need the claim type explicitly (e.g. in a Svelte component), use `OIDCInferClaims`:
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
import type { OIDCInferClaims } from 'sveltekit-oidc/server';
|
|
193
|
+
import { oidc } from '$lib/server/auth';
|
|
194
|
+
|
|
195
|
+
type AppClaims = OIDCInferClaims<typeof oidc>;
|
|
196
|
+
```
|
|
202
197
|
|
|
203
198
|
`OIDCContext` is a generic component, but Svelte doesn't support passing explicit type arguments in markup — `TClaims` is inferred from the `session` prop instead. Since `data.session` comes from `oidc.getPublicSession(event)`, it's already typed `OIDCPublicSession<AppClaims> | null`, so the inference flows through automatically:
|
|
204
199
|
|
|
@@ -256,20 +251,17 @@ export const oidc = createOIDC({
|
|
|
256
251
|
});
|
|
257
252
|
```
|
|
258
253
|
|
|
259
|
-
|
|
254
|
+
`app.d.ts` stays a one-liner — `OIDCLocals` picks up both `TClaims` and `TSession` from the instance:
|
|
260
255
|
|
|
261
256
|
```ts
|
|
262
257
|
// src/app.d.ts
|
|
263
|
-
import type {
|
|
258
|
+
import type { OIDCLocals } from 'sveltekit-oidc/server';
|
|
264
259
|
import { oidc } from '$lib/server/auth';
|
|
265
260
|
|
|
266
|
-
export type AppClaims = OIDCInferClaims<typeof oidc>;
|
|
267
|
-
export type AppSession = OIDCInferSession<typeof oidc>;
|
|
268
|
-
|
|
269
261
|
declare global {
|
|
270
262
|
namespace App {
|
|
271
263
|
interface Locals {
|
|
272
|
-
oidc?:
|
|
264
|
+
oidc?: OIDCLocals<typeof oidc>;
|
|
273
265
|
}
|
|
274
266
|
}
|
|
275
267
|
}
|
|
@@ -279,6 +271,16 @@ export {};
|
|
|
279
271
|
|
|
280
272
|
Now `event.locals.oidc?.session?.tenantId` is `string` and `?.permissions` is `string[]` everywhere — and `oidc.requireAuth(event)` / `handleCallback`'s `onsuccess` resolve to `AppSession` directly.
|
|
281
273
|
|
|
274
|
+
Use `OIDCInferClaims` / `OIDCInferSession` when you need the types explicitly:
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
import type { OIDCInferClaims, OIDCInferSession } from 'sveltekit-oidc/server';
|
|
278
|
+
import { oidc } from '$lib/server/auth';
|
|
279
|
+
|
|
280
|
+
type AppClaims = OIDCInferClaims<typeof oidc>;
|
|
281
|
+
type AppSession = OIDCInferSession<typeof oidc>;
|
|
282
|
+
```
|
|
283
|
+
|
|
282
284
|
If `transformSession` is omitted, `TSession` defaults to `OIDCSession<TClaims>` — existing setups keep working unchanged.
|
|
283
285
|
|
|
284
286
|
## Example App
|
|
@@ -302,6 +304,6 @@ Set these environment variables to enable it:
|
|
|
302
304
|
- The library validates `id_token` and `logout_token` values through `@sourceregistry/node-jwt` and provider JWKS metadata.
|
|
303
305
|
- `groups` are normalized onto the session from `groups` and `roles` claims when present.
|
|
304
306
|
- Use `transformClaims`, `transformUser`, and `transformSession` to project provider-specific claims into your own session shape.
|
|
305
|
-
- `check_session_iframe` monitoring only runs when the provider advertises that endpoint and the session includes `session_state`.
|
|
307
|
+
- `check_session_iframe` monitoring only runs when `monitorSession` is enabled, the provider advertises that endpoint, and the session includes `session_state`.
|
|
306
308
|
- Refresh token handling is automatic when a valid refresh token is present.
|
|
307
|
-
- `event.locals.oidc` is attached by the hook
|
|
309
|
+
- `event.locals.oidc` is attached by the hook; wire it in `app.d.ts` with `OIDCLocals<typeof oidc>` — see [Typed Custom Claims](#typed-custom-claims).
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
loginPath,
|
|
20
20
|
logoutPath = '/auth/logout',
|
|
21
21
|
checkSessionIntervalMs = 5000,
|
|
22
|
+
monitorSession = true,
|
|
22
23
|
revalidateIntervalMs = 30000,
|
|
23
24
|
redirectOnExpired = 'login',
|
|
24
25
|
redirectOnRevoked = 'login',
|
|
@@ -30,6 +31,7 @@
|
|
|
30
31
|
loginPath?: string;
|
|
31
32
|
logoutPath?: string;
|
|
32
33
|
checkSessionIntervalMs?: number;
|
|
34
|
+
monitorSession?: boolean;
|
|
33
35
|
revalidateIntervalMs?: number;
|
|
34
36
|
redirectOnExpired?: RedirectMode;
|
|
35
37
|
redirectOnRevoked?: RedirectMode;
|
|
@@ -47,7 +49,7 @@
|
|
|
47
49
|
config.metadata.check_session_iframe ?? config.checkSessionIframe ?? undefined
|
|
48
50
|
);
|
|
49
51
|
const canMonitorIframe = $derived(
|
|
50
|
-
Boolean(session?.isAuthenticated && session?.sessionState && iframeUrl)
|
|
52
|
+
Boolean(monitorSession && session?.isAuthenticated && session?.sessionState && iframeUrl)
|
|
51
53
|
);
|
|
52
54
|
|
|
53
55
|
const context = setOIDCContext<TClaims>({
|
|
@@ -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";
|
package/dist/server/index.js
CHANGED
|
@@ -6,7 +6,34 @@ import { asAuthorizationHeader, createClientSecretJwtAssertion, createPrivateKey
|
|
|
6
6
|
import { normalizeTokens, shouldRefresh } from './session.js';
|
|
7
7
|
import { absoluteUrl, base64UrlEncode, buildCookieOptions, collectGroups, createPKCEPair, normalizeIssuer, normalizeScope, parseProviderError, toPublicSession } from './utils.js';
|
|
8
8
|
export { createInMemoryBackChannelLogoutStore, createInMemorySessionStore } from './store.js';
|
|
9
|
+
import { createInMemoryBackChannelLogoutStore, createInMemorySessionStore } from './store.js';
|
|
10
|
+
function buildLogger(logger) {
|
|
11
|
+
const noop = () => { };
|
|
12
|
+
if (logger === false)
|
|
13
|
+
return { debug: noop, info: noop, warn: noop, error: noop };
|
|
14
|
+
if (logger)
|
|
15
|
+
return {
|
|
16
|
+
debug: (...a) => logger.debug?.(...a),
|
|
17
|
+
info: (...a) => logger.info?.(...a),
|
|
18
|
+
warn: (...a) => logger.warn?.(...a),
|
|
19
|
+
error: (...a) => logger.error?.(...a),
|
|
20
|
+
};
|
|
21
|
+
const p = '[sveltekit-oidc]';
|
|
22
|
+
return {
|
|
23
|
+
debug: (...a) => console.debug(p, ...a),
|
|
24
|
+
info: (...a) => console.info(p, ...a),
|
|
25
|
+
warn: (...a) => console.warn(p, ...a),
|
|
26
|
+
error: (...a) => console.error(p, ...a),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
9
29
|
export function createOIDC(options) {
|
|
30
|
+
const log = buildLogger(options.logger);
|
|
31
|
+
const sessionStore = options.sessionStore === 'memory'
|
|
32
|
+
? createInMemorySessionStore()
|
|
33
|
+
: options.sessionStore;
|
|
34
|
+
const backChannelLogoutStore = options.backChannelLogoutStore === 'memory'
|
|
35
|
+
? createInMemoryBackChannelLogoutStore()
|
|
36
|
+
: options.backChannelLogoutStore;
|
|
10
37
|
const cookieOptions = buildCookieOptions(options.cookieOptions);
|
|
11
38
|
const clockSkewSeconds = options.clockSkewSeconds ?? 30;
|
|
12
39
|
const refreshToleranceSeconds = options.refreshToleranceSeconds ?? 30;
|
|
@@ -20,7 +47,7 @@ export function createOIDC(options) {
|
|
|
20
47
|
let metadataPromise;
|
|
21
48
|
let jwksPromise;
|
|
22
49
|
async function readPersistedSession(cookies) {
|
|
23
|
-
if (!
|
|
50
|
+
if (!sessionStore) {
|
|
24
51
|
const session = cookieStore.readSession(cookies);
|
|
25
52
|
return session ? { session } : null;
|
|
26
53
|
}
|
|
@@ -28,7 +55,7 @@ export function createOIDC(options) {
|
|
|
28
55
|
if (!reference?.id) {
|
|
29
56
|
return null;
|
|
30
57
|
}
|
|
31
|
-
const session = await
|
|
58
|
+
const session = await sessionStore.get(reference.id);
|
|
32
59
|
if (!session) {
|
|
33
60
|
cookieStore.clearSessionReference(cookies);
|
|
34
61
|
return null;
|
|
@@ -39,22 +66,22 @@ export function createOIDC(options) {
|
|
|
39
66
|
};
|
|
40
67
|
}
|
|
41
68
|
async function writePersistedSession(cookies, session, sessionId) {
|
|
42
|
-
if (!
|
|
69
|
+
if (!sessionStore) {
|
|
43
70
|
cookieStore.writeSession(cookies, session);
|
|
44
71
|
return;
|
|
45
72
|
}
|
|
46
73
|
const id = sessionId ?? base64UrlEncode(randomBytes(24));
|
|
47
|
-
await
|
|
74
|
+
await sessionStore.set(id, session);
|
|
48
75
|
cookieStore.writeSessionReference(cookies, { id });
|
|
49
76
|
}
|
|
50
77
|
async function clearPersistedSession(cookies, sessionId) {
|
|
51
|
-
if (!
|
|
78
|
+
if (!sessionStore) {
|
|
52
79
|
cookieStore.clearSession(cookies);
|
|
53
80
|
return;
|
|
54
81
|
}
|
|
55
82
|
const id = sessionId ?? cookieStore.readSessionReference(cookies)?.id;
|
|
56
83
|
if (id) {
|
|
57
|
-
await
|
|
84
|
+
await sessionStore.delete(id);
|
|
58
85
|
}
|
|
59
86
|
cookieStore.clearSessionReference(cookies);
|
|
60
87
|
}
|
|
@@ -237,10 +264,10 @@ export function createOIDC(options) {
|
|
|
237
264
|
});
|
|
238
265
|
}
|
|
239
266
|
async function isRevoked(session) {
|
|
240
|
-
if (!session || !
|
|
267
|
+
if (!session || !backChannelLogoutStore) {
|
|
241
268
|
return false;
|
|
242
269
|
}
|
|
243
|
-
return
|
|
270
|
+
return backChannelLogoutStore.isRevoked(session);
|
|
244
271
|
}
|
|
245
272
|
async function maybeRefreshSession(event, persisted) {
|
|
246
273
|
const session = persisted?.session ?? null;
|
|
@@ -285,7 +312,8 @@ export function createOIDC(options) {
|
|
|
285
312
|
await writePersistedSession(event.cookies, finalSession, persisted?.id);
|
|
286
313
|
return finalSession;
|
|
287
314
|
}
|
|
288
|
-
catch {
|
|
315
|
+
catch (err) {
|
|
316
|
+
log.error('Token refresh failed — clearing session', err);
|
|
289
317
|
await clearPersistedSession(event.cookies, persisted?.id);
|
|
290
318
|
return null;
|
|
291
319
|
}
|
|
@@ -337,7 +365,8 @@ export function createOIDC(options) {
|
|
|
337
365
|
const code = event.url.searchParams.get('code');
|
|
338
366
|
if (!stateCookie || !state || !code || stateCookie.state !== state) {
|
|
339
367
|
cookieStore.clearState(event.cookies);
|
|
340
|
-
|
|
368
|
+
log.warn('Invalid or expired callback state — restarting login flow');
|
|
369
|
+
return signIn(event);
|
|
341
370
|
}
|
|
342
371
|
cookieStore.clearState(event.cookies);
|
|
343
372
|
const tokenResponse = await exchangeCode({
|
|
@@ -415,7 +444,7 @@ export function createOIDC(options) {
|
|
|
415
444
|
if (!metadata.backchannel_logout_supported) {
|
|
416
445
|
throw error(400, { message: 'Provider does not advertise back-channel logout support' });
|
|
417
446
|
}
|
|
418
|
-
if (!
|
|
447
|
+
if (!backChannelLogoutStore) {
|
|
419
448
|
throw error(500, {
|
|
420
449
|
message: 'backChannelLogoutStore is required for back-channel logout with cookie sessions'
|
|
421
450
|
});
|
|
@@ -426,7 +455,7 @@ export function createOIDC(options) {
|
|
|
426
455
|
throw error(400, { message: 'logout_token is required' });
|
|
427
456
|
}
|
|
428
457
|
const claims = await validateBackChannelLogoutToken(logoutToken);
|
|
429
|
-
await
|
|
458
|
+
await backChannelLogoutStore.revoke({
|
|
430
459
|
issuer: claims.iss,
|
|
431
460
|
clientId: options.clientId,
|
|
432
461
|
sid: claims.sid,
|
package/dist/server/types.d.ts
CHANGED
|
@@ -133,6 +133,12 @@ export type OIDCSessionManagementConfig = {
|
|
|
133
133
|
backChannelLogoutSupported: boolean;
|
|
134
134
|
backChannelLogoutSessionSupported: boolean;
|
|
135
135
|
};
|
|
136
|
+
export type OIDCLogger = {
|
|
137
|
+
debug?: (...args: unknown[]) => void;
|
|
138
|
+
info?: (...args: unknown[]) => void;
|
|
139
|
+
warn?: (...args: unknown[]) => void;
|
|
140
|
+
error?: (...args: unknown[]) => void;
|
|
141
|
+
};
|
|
136
142
|
export type OIDCOptions<TClaims extends OIDCUserClaims = OIDCUserClaims, TSession extends OIDCSession<TClaims> = OIDCSession<TClaims>> = {
|
|
137
143
|
issuer?: string;
|
|
138
144
|
discoveryUrl?: string;
|
|
@@ -144,7 +150,7 @@ export type OIDCOptions<TClaims extends OIDCUserClaims = OIDCUserClaims, TSessio
|
|
|
144
150
|
loginPath?: string;
|
|
145
151
|
redirectPath?: string;
|
|
146
152
|
postLogoutRedirectUri?: string;
|
|
147
|
-
scope?: string[];
|
|
153
|
+
scope?: string | string[];
|
|
148
154
|
audience?: string;
|
|
149
155
|
fetchUserInfo?: boolean;
|
|
150
156
|
sessionCookieName?: string;
|
|
@@ -155,8 +161,8 @@ export type OIDCOptions<TClaims extends OIDCUserClaims = OIDCUserClaims, TSessio
|
|
|
155
161
|
refreshToleranceSeconds?: number;
|
|
156
162
|
defaultLoginRedirect?: string;
|
|
157
163
|
defaultLogoutRedirect?: string;
|
|
158
|
-
sessionStore?: OIDCSessionStore<TClaims, TSession
|
|
159
|
-
backChannelLogoutStore?: OIDCBackChannelLogoutStore<TClaims, TSession
|
|
164
|
+
sessionStore?: OIDCSessionStore<TClaims, TSession> | 'memory';
|
|
165
|
+
backChannelLogoutStore?: OIDCBackChannelLogoutStore<TClaims, TSession> | 'memory';
|
|
160
166
|
transformClaims?: (claims: OIDCUserClaims) => MaybePromise<TClaims>;
|
|
161
167
|
transformUser?: (user: OIDCUserClaims | undefined, context: {
|
|
162
168
|
claims?: TClaims;
|
|
@@ -169,11 +175,12 @@ export type OIDCOptions<TClaims extends OIDCUserClaims = OIDCUserClaims, TSessio
|
|
|
169
175
|
isRefresh: boolean;
|
|
170
176
|
}) => MaybePromise<TSession>;
|
|
171
177
|
endpoints?: Partial<OIDCDiscoveryDocument>;
|
|
178
|
+
logger?: OIDCLogger | false;
|
|
172
179
|
};
|
|
173
180
|
export type OIDCLoginOptions = {
|
|
174
181
|
returnTo?: string;
|
|
175
182
|
prompt?: 'login' | 'consent' | 'none' | 'select_account';
|
|
176
|
-
scope?: string[];
|
|
183
|
+
scope?: string | string[];
|
|
177
184
|
extraParams?: Record<string, string>;
|
|
178
185
|
};
|
|
179
186
|
export type OIDCLogoutOptions = {
|
|
@@ -256,3 +263,4 @@ export type OIDCInstance<TClaims extends OIDCUserClaims = OIDCUserClaims, TSessi
|
|
|
256
263
|
};
|
|
257
264
|
export type OIDCInferClaims<T> = T extends OIDCInstance<infer TClaims> ? TClaims : OIDCUserClaims;
|
|
258
265
|
export type OIDCInferSession<T> = T extends OIDCInstance<infer _TClaims, infer TSession> ? TSession : OIDCSession<OIDCUserClaims>;
|
|
266
|
+
export type OIDCLocals<T extends OIDCInstance<any, any>> = OIDCHandleLocals<OIDCInferClaims<T>, OIDCInferSession<T>>;
|
package/dist/server/utils.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export declare function createPKCEPair(length?: number): {
|
|
|
6
6
|
challenge: string;
|
|
7
7
|
};
|
|
8
8
|
export declare function normalizeIssuer(issuer: string): string;
|
|
9
|
-
export declare function normalizeScope(scope?: string[]): string[];
|
|
9
|
+
export declare function normalizeScope(scope?: string | string[]): string[];
|
|
10
10
|
export declare function normalizeStringArray(value: unknown): string[];
|
|
11
11
|
export declare function collectGroups<TClaims extends OIDCUserClaims = OIDCUserClaims>(...sources: Array<TClaims | undefined>): string[];
|
|
12
12
|
export declare function createSignedValue(value: string, secret: string): string;
|
package/dist/server/utils.js
CHANGED
|
@@ -13,7 +13,10 @@ export function normalizeIssuer(issuer) {
|
|
|
13
13
|
return issuer.endsWith('/') ? issuer.slice(0, -1) : issuer;
|
|
14
14
|
}
|
|
15
15
|
export function normalizeScope(scope) {
|
|
16
|
-
|
|
16
|
+
if (!scope)
|
|
17
|
+
return ['openid', 'profile', 'email'];
|
|
18
|
+
const arr = typeof scope === 'string' ? scope.trim().split(/\s+/) : scope;
|
|
19
|
+
return arr.length ? [...new Set(arr)] : ['openid', 'profile', 'email'];
|
|
17
20
|
}
|
|
18
21
|
export function normalizeStringArray(value) {
|
|
19
22
|
if (!value)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sourceregistry/sveltekit-oidc",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "OIDC authentication helpers for SvelteKit applications
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"description": "OIDC authentication helpers for SvelteKit applications",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"dev": "vite dev",
|