nuxt-auth-utils 0.5.8 → 0.5.10
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 +62 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +10 -0
- package/dist/runtime/server/lib/oauth/apple.d.ts +73 -0
- package/dist/runtime/server/lib/oauth/apple.js +77 -0
- package/dist/runtime/server/lib/utils.d.ts +25 -0
- package/dist/runtime/server/lib/utils.js +17 -0
- package/dist/runtime/server/plugins/ws.d.ts +2 -0
- package/dist/runtime/server/plugins/ws.js +7 -0
- package/dist/runtime/server/utils/session.d.ts +5 -2
- package/dist/runtime/server/utils/session.js +12 -6
- package/dist/runtime/types/oauth-config.d.ts +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -16,13 +16,14 @@ Add Authentication to Nuxt applications with secured & sealed cookies sessions.
|
|
|
16
16
|
## Features
|
|
17
17
|
|
|
18
18
|
- [Hybrid Rendering](#hybrid-rendering) support (SSR / CSR / SWR / Prerendering)
|
|
19
|
-
- [
|
|
19
|
+
- [30+ OAuth Providers](#supported-oauth-providers)
|
|
20
20
|
- [Password Hashing](#password-hashing)
|
|
21
21
|
- [WebAuthn (passkey)](#webauthn-passkey)
|
|
22
22
|
- [`useUserSession()` Vue composable](#vue-composable)
|
|
23
23
|
- [Tree-shakable server utils](#server-utils)
|
|
24
24
|
- [`<AuthState>` component](#authstate-component)
|
|
25
25
|
- [Extendable with hooks](#extend-session)
|
|
26
|
+
- [WebSocket support](#websocket-support)
|
|
26
27
|
|
|
27
28
|
It has few dependencies (only from [UnJS](https://github.com/unjs)), run on multiple JS environments (Node, Deno, Workers) and is fully typed with TypeScript.
|
|
28
29
|
|
|
@@ -204,6 +205,7 @@ It can also be set using environment variables:
|
|
|
204
205
|
|
|
205
206
|
#### Supported OAuth Providers
|
|
206
207
|
|
|
208
|
+
- Apple
|
|
207
209
|
- Atlassian
|
|
208
210
|
- Auth0
|
|
209
211
|
- Authentik
|
|
@@ -596,6 +598,65 @@ You can use the `placeholder` slot to show a placeholder on server-side and whil
|
|
|
596
598
|
|
|
597
599
|
If you are caching your routes with `routeRules`, please make sure to use [Nitro](https://github.com/unjs/nitro) >= `2.9.7` to support the client-side fetching of the user session.
|
|
598
600
|
|
|
601
|
+
## WebSocket Support
|
|
602
|
+
|
|
603
|
+
Nuxt Auth Utils is compatible with [Nitro WebSockets](https://nitro.build/guide/websocket).
|
|
604
|
+
|
|
605
|
+
Make sure to enable the `experimental.websocket` option in your `nuxt.config.ts`:
|
|
606
|
+
|
|
607
|
+
```ts
|
|
608
|
+
export default defineNuxtConfig({
|
|
609
|
+
nitro: {
|
|
610
|
+
experimental: {
|
|
611
|
+
websocket: true
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
})
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
You can use the `requireUserSession` function in the `upgrade` function to check if the user is authenticated before upgrading the WebSocket connection.
|
|
618
|
+
|
|
619
|
+
```ts
|
|
620
|
+
// server/routes/ws.ts
|
|
621
|
+
export default defineWebSocketHandler({
|
|
622
|
+
async upgrade(request) {
|
|
623
|
+
// Make sure the user is authenticated before upgrading the WebSocket connection
|
|
624
|
+
await requireUserSession(request)
|
|
625
|
+
},
|
|
626
|
+
async open(peer) {
|
|
627
|
+
const { user } = await requireUserSession(peer)
|
|
628
|
+
|
|
629
|
+
peer.send(`Hello, ${user.name}!`)
|
|
630
|
+
},
|
|
631
|
+
message(peer, message) {
|
|
632
|
+
peer.send(`Echo: ${message}`)
|
|
633
|
+
},
|
|
634
|
+
})
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
Then, in your application, you can use the [useWebSocket](https://vueuse.org/core/useWebSocket/) composable to connect to the WebSocket:
|
|
638
|
+
|
|
639
|
+
```vue
|
|
640
|
+
<script setup>
|
|
641
|
+
const { status, data, send, open, close } = useWebSocket('/ws', { immediate: false })
|
|
642
|
+
|
|
643
|
+
// Only open the websocket after the page is hydrated (client-only)
|
|
644
|
+
onMounted(open)
|
|
645
|
+
</script>
|
|
646
|
+
|
|
647
|
+
<template>
|
|
648
|
+
<div>
|
|
649
|
+
<p>Status: {{ status }}</p>
|
|
650
|
+
<p>Data: {{ data }}</p>
|
|
651
|
+
<p>
|
|
652
|
+
<button @click="open">Open</button>
|
|
653
|
+
<button @click="close(1000, 'Closing')">Close</button>
|
|
654
|
+
<button @click="send('hello')">Send hello</button>
|
|
655
|
+
</p>
|
|
656
|
+
</div>
|
|
657
|
+
</template>
|
|
658
|
+
```
|
|
659
|
+
|
|
599
660
|
## Configuration
|
|
600
661
|
|
|
601
662
|
We leverage `runtimeConfig.session` to give the defaults option to [h3 `useSession`](https://h3.unjs.io/examples/handle-session).
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -33,6 +33,9 @@ const module = defineNuxtModule({
|
|
|
33
33
|
addPlugin(resolver.resolve("./runtime/app/plugins/session.client"));
|
|
34
34
|
addServerPlugin(resolver.resolve("./runtime/server/plugins/oauth"));
|
|
35
35
|
addServerImportsDir(resolver.resolve("./runtime/server/lib/oauth"));
|
|
36
|
+
if (nuxt.options.nitro?.experimental?.websocket) {
|
|
37
|
+
addServerPlugin(resolver.resolve("./runtime/server/plugins/ws"));
|
|
38
|
+
}
|
|
36
39
|
if (options.webAuthn) {
|
|
37
40
|
const missingDeps = [];
|
|
38
41
|
const peerDeps = ["@simplewebauthn/server", "@simplewebauthn/browser"];
|
|
@@ -271,6 +274,13 @@ const module = defineNuxtModule({
|
|
|
271
274
|
clientSecret: "",
|
|
272
275
|
redirectURL: ""
|
|
273
276
|
});
|
|
277
|
+
runtimeConfig.oauth.apple = defu(runtimeConfig.oauth.apple, {
|
|
278
|
+
teamId: "",
|
|
279
|
+
keyId: "",
|
|
280
|
+
privateKey: "",
|
|
281
|
+
redirectURL: "",
|
|
282
|
+
clientId: ""
|
|
283
|
+
});
|
|
274
284
|
}
|
|
275
285
|
});
|
|
276
286
|
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { OAuthConfig } from '#auth-utils';
|
|
2
|
+
export interface OAuthAppleConfig {
|
|
3
|
+
/**
|
|
4
|
+
* Apple OAuth Client ID
|
|
5
|
+
* @default process.env.NUXT_OAUTH_APPLE_CLIENT_ID
|
|
6
|
+
*/
|
|
7
|
+
clientId?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Apple OAuth team ID
|
|
10
|
+
* @default process.env.NUXT_OAUTH_APPLE_TEAM_ID
|
|
11
|
+
*/
|
|
12
|
+
teamId?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Apple OAuth key identifier
|
|
15
|
+
* @default process.env.NUXT_OAUTH_APPLE_KEY_ID
|
|
16
|
+
*/
|
|
17
|
+
keyId?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Apple OAuth Private Key. Linebreaks must be replaced with \n
|
|
20
|
+
* @example '-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM...\n-----END PRIVATE KEY-----'
|
|
21
|
+
* @default process.env.NUXT_OAUTH_APPLE_PRIVATE_KEY
|
|
22
|
+
*/
|
|
23
|
+
privateKey?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Apple OAuth Scope. Apple wants this to be a string separated by spaces, but for consistency with other providers, we also allow an array of strings.
|
|
26
|
+
* @default ''
|
|
27
|
+
* @see https://developer.apple.com/documentation/sign_in_with_apple/clientconfigi/3230955-scope
|
|
28
|
+
* @example 'name email'
|
|
29
|
+
*/
|
|
30
|
+
scope?: string | string[];
|
|
31
|
+
/**
|
|
32
|
+
* Apple OAuth Authorization URL
|
|
33
|
+
* @default 'https://appleid.apple.com/auth/authorize'
|
|
34
|
+
*/
|
|
35
|
+
authorizationURL?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Extra authorization parameters to provide to the authorization URL
|
|
38
|
+
* @see https://developer.apple.com/documentation/sign_in_with_apple/clientconfigi/3230955-scope
|
|
39
|
+
* @example { usePop: true }
|
|
40
|
+
*/
|
|
41
|
+
authorizationParams?: Record<string, string | boolean>;
|
|
42
|
+
/**
|
|
43
|
+
* Apple OAuth Token URL
|
|
44
|
+
* @default 'https://appleid.apple.com/auth/token'
|
|
45
|
+
*/
|
|
46
|
+
tokenURL?: string;
|
|
47
|
+
/**
|
|
48
|
+
* Redirect URL to to allow overriding for situations like prod failing to determine public hostname
|
|
49
|
+
* @default process.env.NUXT_OAUTH_APPLE_REDIRECT_URL or current URL
|
|
50
|
+
*/
|
|
51
|
+
redirectURL?: string;
|
|
52
|
+
}
|
|
53
|
+
export interface OAuthAppleTokens {
|
|
54
|
+
iss: string;
|
|
55
|
+
aud: string;
|
|
56
|
+
exp: number;
|
|
57
|
+
iat: number;
|
|
58
|
+
sub: string;
|
|
59
|
+
at_hash: string;
|
|
60
|
+
email: string;
|
|
61
|
+
email_verified: boolean;
|
|
62
|
+
is_private_email: boolean;
|
|
63
|
+
auth_time: number;
|
|
64
|
+
nonce_supported: boolean;
|
|
65
|
+
}
|
|
66
|
+
export interface OAuthAppleUser {
|
|
67
|
+
name?: {
|
|
68
|
+
firstName?: string;
|
|
69
|
+
lastName?: string;
|
|
70
|
+
};
|
|
71
|
+
email?: string;
|
|
72
|
+
}
|
|
73
|
+
export declare function defineOAuthAppleEventHandler({ config, onSuccess, onError, }: OAuthConfig<OAuthAppleConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { eventHandler, getRequestHeader, readBody, sendRedirect } from "h3";
|
|
2
|
+
import { withQuery } from "ufo";
|
|
3
|
+
import { defu } from "defu";
|
|
4
|
+
import { handleMissingConfiguration, handleAccessTokenErrorResponse, getOAuthRedirectURL, requestAccessToken, signJwt, verifyJwt } from "../utils.js";
|
|
5
|
+
import { useRuntimeConfig } from "#imports";
|
|
6
|
+
export function defineOAuthAppleEventHandler({
|
|
7
|
+
config,
|
|
8
|
+
onSuccess,
|
|
9
|
+
onError
|
|
10
|
+
}) {
|
|
11
|
+
return eventHandler(async (event) => {
|
|
12
|
+
config = defu(config, useRuntimeConfig(event).oauth?.apple, {
|
|
13
|
+
authorizationURL: config?.authorizationURL || "https://appleid.apple.com/auth/authorize",
|
|
14
|
+
authorizationParams: {}
|
|
15
|
+
});
|
|
16
|
+
if (!config.teamId || !config.keyId || !config.privateKey || !config.clientId) {
|
|
17
|
+
return handleMissingConfiguration(event, "apple", ["teamId", "keyId", "privateKey", "clientId"], onError);
|
|
18
|
+
}
|
|
19
|
+
const isPost = getRequestHeader(event, "content-type") === "application/x-www-form-urlencoded";
|
|
20
|
+
let code;
|
|
21
|
+
let user;
|
|
22
|
+
if (isPost) {
|
|
23
|
+
({ code, user } = await readBody(event));
|
|
24
|
+
}
|
|
25
|
+
if (!isPost || !code) {
|
|
26
|
+
const redirectURL = config.redirectURL || getOAuthRedirectURL(event);
|
|
27
|
+
config.scope = Array.isArray(config.scope) ? config.scope.join(" ") : config.scope || "name email";
|
|
28
|
+
return sendRedirect(
|
|
29
|
+
event,
|
|
30
|
+
withQuery(config.authorizationURL, {
|
|
31
|
+
response_type: "code",
|
|
32
|
+
response_mode: "form_post",
|
|
33
|
+
client_id: config.clientId,
|
|
34
|
+
redirect_uri: redirectURL,
|
|
35
|
+
scope: config.scope,
|
|
36
|
+
...config.authorizationParams
|
|
37
|
+
})
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const secret = await signJwt(
|
|
42
|
+
{
|
|
43
|
+
iss: config.teamId,
|
|
44
|
+
aud: "https://appleid.apple.com",
|
|
45
|
+
sub: config.clientId
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
privateKey: config.privateKey,
|
|
49
|
+
keyId: config.keyId,
|
|
50
|
+
teamId: config.teamId,
|
|
51
|
+
clientId: config.clientId,
|
|
52
|
+
expiresIn: "5m"
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
const accessTokenResult = await requestAccessToken(config.tokenURL || "https://appleid.apple.com/auth/token", {
|
|
56
|
+
params: {
|
|
57
|
+
client_id: config.clientId,
|
|
58
|
+
client_secret: secret,
|
|
59
|
+
code,
|
|
60
|
+
grant_type: "authorization_code",
|
|
61
|
+
redirect_uri: config.redirectURL
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
const tokens = await verifyJwt(accessTokenResult.id_token, {
|
|
65
|
+
publicJwkUrl: "https://appleid.apple.com/auth/keys",
|
|
66
|
+
audience: config.clientId,
|
|
67
|
+
issuer: "https://appleid.apple.com"
|
|
68
|
+
});
|
|
69
|
+
if (!tokens) {
|
|
70
|
+
return handleAccessTokenErrorResponse(event, "apple", tokens, onError);
|
|
71
|
+
}
|
|
72
|
+
return onSuccess(event, { user, tokens });
|
|
73
|
+
} catch (error) {
|
|
74
|
+
return handleAccessTokenErrorResponse(event, "apple", error, onError);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
@@ -34,4 +34,29 @@ export declare function requestAccessToken(url: string, options: RequestAccessTo
|
|
|
34
34
|
*/
|
|
35
35
|
export declare function handleAccessTokenErrorResponse(event: H3Event, oauthProvider: OAuthProvider, oauthError: any, onError?: OnError): void | Promise<void>;
|
|
36
36
|
export declare function handleMissingConfiguration(event: H3Event, provider: OAuthProvider, missingKeys: string[], onError?: OnError): void | Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* JWT signing using jose
|
|
39
|
+
*
|
|
40
|
+
* @see https://github.com/panva/jose
|
|
41
|
+
*/
|
|
42
|
+
interface JWTSignOptions {
|
|
43
|
+
privateKey: string;
|
|
44
|
+
keyId: string;
|
|
45
|
+
teamId?: string;
|
|
46
|
+
clientId?: string;
|
|
47
|
+
algorithm?: 'ES256' | 'RS256';
|
|
48
|
+
expiresIn?: string;
|
|
49
|
+
}
|
|
50
|
+
export declare function signJwt<T extends Record<string, unknown>>(payload: T, options: JWTSignOptions): Promise<string>;
|
|
51
|
+
/**
|
|
52
|
+
* Verify a JWT token using jose - will throw error if invalid
|
|
53
|
+
*
|
|
54
|
+
* @see https://github.com/panva/jose
|
|
55
|
+
*/
|
|
56
|
+
interface JWTVerifyOptions {
|
|
57
|
+
publicJwkUrl: string;
|
|
58
|
+
audience: string;
|
|
59
|
+
issuer: string;
|
|
60
|
+
}
|
|
61
|
+
export declare function verifyJwt<T>(token: string, options: JWTVerifyOptions): Promise<T>;
|
|
37
62
|
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getRequestURL } from "h3";
|
|
2
2
|
import { FetchError } from "ofetch";
|
|
3
3
|
import { snakeCase, upperFirst } from "scule";
|
|
4
|
+
import * as jose from "jose";
|
|
4
5
|
import { createError } from "#imports";
|
|
5
6
|
export function getOAuthRedirectURL(event) {
|
|
6
7
|
const requestURL = getRequestURL(event);
|
|
@@ -44,3 +45,19 @@ export function handleMissingConfiguration(event, provider, missingKeys, onError
|
|
|
44
45
|
if (!onError) throw error;
|
|
45
46
|
return onError(event, error);
|
|
46
47
|
}
|
|
48
|
+
export async function signJwt(payload, options) {
|
|
49
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
50
|
+
const privateKey = await jose.importPKCS8(
|
|
51
|
+
options.privateKey.replace(/\\n/g, "\n"),
|
|
52
|
+
options.algorithm || "ES256"
|
|
53
|
+
);
|
|
54
|
+
return new jose.SignJWT(payload).setProtectedHeader({ alg: options.algorithm || "ES256", kid: options.keyId }).setIssuedAt(now).setExpirationTime(options.expiresIn || "5m").sign(privateKey);
|
|
55
|
+
}
|
|
56
|
+
export async function verifyJwt(token, options) {
|
|
57
|
+
const JWKS = jose.createRemoteJWKSet(new URL(options.publicJwkUrl));
|
|
58
|
+
const { payload } = await jose.jwtVerify(token, JWKS, {
|
|
59
|
+
audience: options.audience,
|
|
60
|
+
issuer: options.issuer
|
|
61
|
+
});
|
|
62
|
+
return payload;
|
|
63
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { H3Event, SessionConfig } from 'h3';
|
|
2
|
+
import { useSession } from 'h3';
|
|
2
3
|
import type { UserSession, UserSessionRequired } from '#auth-utils';
|
|
4
|
+
type UseSessionEvent = Parameters<typeof useSession>[0];
|
|
3
5
|
export interface SessionHooks {
|
|
4
6
|
/**
|
|
5
7
|
* Called when fetching the session from the API
|
|
@@ -18,7 +20,7 @@ export declare const sessionHooks: import("hookable").Hookable<SessionHooks, imp
|
|
|
18
20
|
* @param event The Request (h3) event
|
|
19
21
|
* @returns The user session
|
|
20
22
|
*/
|
|
21
|
-
export declare function getUserSession(event:
|
|
23
|
+
export declare function getUserSession(event: UseSessionEvent): Promise<UserSession>;
|
|
22
24
|
/**
|
|
23
25
|
* Set a user session
|
|
24
26
|
* @param event The Request (h3) event
|
|
@@ -46,7 +48,8 @@ export declare function clearUserSession(event: H3Event, config?: Partial<Sessio
|
|
|
46
48
|
* @param opts.message The message to use for the error (defaults to Unauthorized)
|
|
47
49
|
* @see https://github.com/atinux/nuxt-auth-utils
|
|
48
50
|
*/
|
|
49
|
-
export declare function requireUserSession(event:
|
|
51
|
+
export declare function requireUserSession(event: UseSessionEvent, opts?: {
|
|
50
52
|
statusCode?: number;
|
|
51
53
|
message?: string;
|
|
52
54
|
}): Promise<UserSessionRequired>;
|
|
55
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useSession, createError } from "h3";
|
|
1
|
+
import { useSession, createError, isEvent } from "h3";
|
|
2
2
|
import { defu } from "defu";
|
|
3
3
|
import { createHooks } from "hookable";
|
|
4
4
|
import { useRuntimeConfig } from "#imports";
|
|
@@ -26,17 +26,23 @@ export async function clearUserSession(event, config) {
|
|
|
26
26
|
export async function requireUserSession(event, opts = {}) {
|
|
27
27
|
const userSession = await getUserSession(event);
|
|
28
28
|
if (!userSession.user) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
if (isEvent(event)) {
|
|
30
|
+
throw createError({
|
|
31
|
+
statusCode: opts.statusCode || 401,
|
|
32
|
+
message: opts.message || "Unauthorized"
|
|
33
|
+
});
|
|
34
|
+
} else {
|
|
35
|
+
throw new Response(opts.message || "Unauthorized", {
|
|
36
|
+
status: opts.statusCode || 401
|
|
37
|
+
});
|
|
38
|
+
}
|
|
33
39
|
}
|
|
34
40
|
return userSession;
|
|
35
41
|
}
|
|
36
42
|
let sessionConfig;
|
|
37
43
|
function _useSession(event, config = {}) {
|
|
38
44
|
if (!sessionConfig) {
|
|
39
|
-
const runtimeConfig = useRuntimeConfig(event);
|
|
45
|
+
const runtimeConfig = useRuntimeConfig(isEvent(event) ? event : void 0);
|
|
40
46
|
const envSessionPassword = `${runtimeConfig.nitro?.envPrefix || "NUXT_"}SESSION_PASSWORD`;
|
|
41
47
|
sessionConfig = defu({ password: process.env[envSessionPassword] }, runtimeConfig.session);
|
|
42
48
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { H3Event, H3Error } from 'h3';
|
|
2
|
-
export type OAuthProvider = 'atlassian' | 'auth0' | 'authentik' | 'battledotnet' | 'cognito' | 'discord' | 'dropbox' | 'facebook' | 'github' | 'gitlab' | 'google' | 'hubspot' | 'instagram' | 'keycloak' | 'line' | 'linear' | 'linkedin' | 'microsoft' | 'paypal' | 'polar' | 'spotify' | 'seznam' | 'steam' | 'strava' | 'tiktok' | 'twitch' | 'vk' | 'workos' | 'x' | 'xsuaa' | 'yandex' | 'zitadel' | (string & {});
|
|
2
|
+
export type OAuthProvider = 'atlassian' | 'auth0' | 'authentik' | 'battledotnet' | 'cognito' | 'discord' | 'dropbox' | 'facebook' | 'github' | 'gitlab' | 'google' | 'hubspot' | 'instagram' | 'keycloak' | 'line' | 'linear' | 'linkedin' | 'microsoft' | 'paypal' | 'polar' | 'spotify' | 'seznam' | 'steam' | 'strava' | 'tiktok' | 'twitch' | 'vk' | 'workos' | 'x' | 'xsuaa' | 'yandex' | 'zitadel' | 'apple' | (string & {});
|
|
3
3
|
export type OnError = (event: H3Event, error: H3Error) => Promise<void> | void;
|
|
4
4
|
export interface OAuthConfig<TConfig, TUser = any, TTokens = any> {
|
|
5
5
|
config?: TConfig;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-auth-utils",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.10",
|
|
4
4
|
"description": "Add Authentication to Nuxt applications with secured & sealed cookies sessions.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -38,8 +38,9 @@
|
|
|
38
38
|
"@adonisjs/hash": "^9.0.5",
|
|
39
39
|
"@nuxt/kit": "^3.15.2",
|
|
40
40
|
"defu": "^6.1.4",
|
|
41
|
-
"h3": "^1.
|
|
41
|
+
"h3": "^1.14.0",
|
|
42
42
|
"hookable": "^5.5.3",
|
|
43
|
+
"jose": "^5.9.6",
|
|
43
44
|
"ofetch": "^1.4.1",
|
|
44
45
|
"ohash": "^1.1.4",
|
|
45
46
|
"openid-client": "^6.1.7",
|