nuxt-auth-utils 0.5.31 → 0.5.33
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 +55 -4
- package/dist/module.json +1 -1
- package/dist/module.mjs +19 -1
- package/dist/runtime/app/composables/session.js +8 -3
- package/dist/runtime/app/plugins/session.client.js +8 -4
- package/dist/runtime/server/lib/oauth/apple.js +4 -1
- package/dist/runtime/server/lib/oauth/atlassian.js +1 -1
- package/dist/runtime/server/lib/oauth/auth0.js +1 -1
- package/dist/runtime/server/lib/oauth/authentik.js +1 -1
- package/dist/runtime/server/lib/oauth/azureb2c.js +1 -1
- package/dist/runtime/server/lib/oauth/battledotnet.js +1 -1
- package/dist/runtime/server/lib/oauth/box.js +1 -1
- package/dist/runtime/server/lib/oauth/cloudflare.d.ts +86 -0
- package/dist/runtime/server/lib/oauth/cloudflare.js +72 -0
- package/dist/runtime/server/lib/oauth/cognito.js +1 -1
- package/dist/runtime/server/lib/oauth/discord.js +1 -1
- package/dist/runtime/server/lib/oauth/dropbox.js +1 -1
- package/dist/runtime/server/lib/oauth/facebook.d.ts +13 -2
- package/dist/runtime/server/lib/oauth/facebook.js +16 -4
- package/dist/runtime/server/lib/oauth/gitea.js +1 -1
- package/dist/runtime/server/lib/oauth/github.js +1 -1
- package/dist/runtime/server/lib/oauth/gitlab.js +1 -1
- package/dist/runtime/server/lib/oauth/google.js +1 -1
- package/dist/runtime/server/lib/oauth/heroku.js +1 -1
- package/dist/runtime/server/lib/oauth/hubspot.js +1 -1
- package/dist/runtime/server/lib/oauth/instagram.js +1 -1
- package/dist/runtime/server/lib/oauth/keycloak.js +1 -1
- package/dist/runtime/server/lib/oauth/kick.js +1 -1
- package/dist/runtime/server/lib/oauth/line.js +1 -1
- package/dist/runtime/server/lib/oauth/linear.js +1 -1
- package/dist/runtime/server/lib/oauth/linkedin.js +1 -1
- package/dist/runtime/server/lib/oauth/livechat.js +1 -1
- package/dist/runtime/server/lib/oauth/mastodon.d.ts +62 -0
- package/dist/runtime/server/lib/oauth/mastodon.js +178 -0
- package/dist/runtime/server/lib/oauth/microsoft.js +1 -1
- package/dist/runtime/server/lib/oauth/oidc.js +5 -4
- package/dist/runtime/server/lib/oauth/okta.js +1 -1
- package/dist/runtime/server/lib/oauth/ory.js +1 -1
- package/dist/runtime/server/lib/oauth/osu.js +1 -1
- package/dist/runtime/server/lib/oauth/paypal.js +1 -1
- package/dist/runtime/server/lib/oauth/polar.js +1 -1
- package/dist/runtime/server/lib/oauth/riotgames.js +1 -1
- package/dist/runtime/server/lib/oauth/roblox.js +1 -1
- package/dist/runtime/server/lib/oauth/salesforce.d.ts +8 -3
- package/dist/runtime/server/lib/oauth/salesforce.js +9 -5
- package/dist/runtime/server/lib/oauth/seznam.js +1 -1
- package/dist/runtime/server/lib/oauth/shopifyCustomer.js +2 -2
- package/dist/runtime/server/lib/oauth/slack.js +1 -1
- package/dist/runtime/server/lib/oauth/spotify.js +1 -1
- package/dist/runtime/server/lib/oauth/steam.js +1 -1
- package/dist/runtime/server/lib/oauth/strava.js +1 -1
- package/dist/runtime/server/lib/oauth/tiktok.js +1 -1
- package/dist/runtime/server/lib/oauth/twitch.js +1 -1
- package/dist/runtime/server/lib/oauth/vk.js +1 -1
- package/dist/runtime/server/lib/oauth/wechat.d.ts +67 -0
- package/dist/runtime/server/lib/oauth/wechat.js +107 -0
- package/dist/runtime/server/lib/oauth/workos.js +1 -1
- package/dist/runtime/server/lib/oauth/x.js +1 -1
- package/dist/runtime/server/lib/oauth/xsuaa.js +1 -1
- package/dist/runtime/server/lib/oauth/yandex.js +1 -1
- package/dist/runtime/server/lib/oauth/zitadel.js +1 -1
- package/dist/runtime/server/lib/utils.d.ts +1 -0
- package/dist/runtime/server/lib/utils.js +3 -3
- package/dist/runtime/server/utils/session.js +6 -1
- package/dist/runtime/types/oauth-config.d.ts +1 -1
- package/package.json +12 -16
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { eventHandler, getQuery, sendRedirect } from "h3";
|
|
2
|
+
import { withQuery } from "ufo";
|
|
3
|
+
import { defu } from "defu";
|
|
4
|
+
import {
|
|
5
|
+
getOAuthRedirectURL,
|
|
6
|
+
handleInvalidState,
|
|
7
|
+
handleMissingConfiguration,
|
|
8
|
+
handleState
|
|
9
|
+
} from "../utils.js";
|
|
10
|
+
import { createError, useRuntimeConfig } from "#imports";
|
|
11
|
+
function isWechatOAuthError(value) {
|
|
12
|
+
return Boolean(
|
|
13
|
+
value && typeof value === "object" && "errcode" in value && "errmsg" in value
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
function handleWechatOAuthError(event, phase, oauthError, onError) {
|
|
17
|
+
const error = createError({
|
|
18
|
+
statusCode: 401,
|
|
19
|
+
message: `WeChat ${phase} request failed: ${oauthError.errmsg} (${oauthError.errcode})`,
|
|
20
|
+
data: oauthError
|
|
21
|
+
});
|
|
22
|
+
if (!onError) throw error;
|
|
23
|
+
return onError(event, error);
|
|
24
|
+
}
|
|
25
|
+
export function defineOAuthWechatEventHandler({
|
|
26
|
+
config,
|
|
27
|
+
onSuccess,
|
|
28
|
+
onError
|
|
29
|
+
}) {
|
|
30
|
+
return eventHandler(async (event) => {
|
|
31
|
+
config = defu(config, useRuntimeConfig(event).oauth?.wechat, {
|
|
32
|
+
authorizationURL: "https://open.weixin.qq.com/connect/qrconnect",
|
|
33
|
+
tokenURL: "https://api.weixin.qq.com/sns/oauth2/access_token",
|
|
34
|
+
userURL: "https://api.weixin.qq.com/sns/userinfo",
|
|
35
|
+
lang: "zh_CN"
|
|
36
|
+
});
|
|
37
|
+
const query = getQuery(event);
|
|
38
|
+
if (query.error) {
|
|
39
|
+
const error = createError({
|
|
40
|
+
statusCode: 401,
|
|
41
|
+
message: `WeChat login failed: ${query.error || "Unknown error"}`,
|
|
42
|
+
data: query
|
|
43
|
+
});
|
|
44
|
+
if (!onError) throw error;
|
|
45
|
+
return onError(event, error);
|
|
46
|
+
}
|
|
47
|
+
if (!config.appId || !config.appSecret) {
|
|
48
|
+
return handleMissingConfiguration(event, "wechat", ["appId", "appSecret"], onError);
|
|
49
|
+
}
|
|
50
|
+
const redirectURL = config.redirectURL || getOAuthRedirectURL(event);
|
|
51
|
+
if (!query.code && query.state) {
|
|
52
|
+
await handleState(event, { isCallback: true });
|
|
53
|
+
const error = createError({
|
|
54
|
+
statusCode: 401,
|
|
55
|
+
message: "WeChat login failed: authorization denied",
|
|
56
|
+
data: query
|
|
57
|
+
});
|
|
58
|
+
if (!onError) throw error;
|
|
59
|
+
return onError(event, error);
|
|
60
|
+
}
|
|
61
|
+
const state = await handleState(event);
|
|
62
|
+
if (!query.code) {
|
|
63
|
+
config.scope = config.scope?.length ? config.scope : ["snsapi_login"];
|
|
64
|
+
return sendRedirect(
|
|
65
|
+
event,
|
|
66
|
+
`${withQuery(config.authorizationURL, {
|
|
67
|
+
appid: config.appId,
|
|
68
|
+
redirect_uri: redirectURL,
|
|
69
|
+
response_type: "code",
|
|
70
|
+
scope: config.scope.join(","),
|
|
71
|
+
state
|
|
72
|
+
})}#wechat_redirect`
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
if (!state || query.state !== state) {
|
|
76
|
+
return handleInvalidState(event, "wechat", onError);
|
|
77
|
+
}
|
|
78
|
+
const tokens = await $fetch(config.tokenURL, {
|
|
79
|
+
// WeChat answers JSON with a text/plain content type
|
|
80
|
+
responseType: "json",
|
|
81
|
+
query: {
|
|
82
|
+
appid: config.appId,
|
|
83
|
+
secret: config.appSecret,
|
|
84
|
+
code: query.code,
|
|
85
|
+
grant_type: "authorization_code"
|
|
86
|
+
}
|
|
87
|
+
}).catch((error) => ({ errcode: error?.response?.status ?? -1, errmsg: "token request failed" }));
|
|
88
|
+
if (isWechatOAuthError(tokens)) {
|
|
89
|
+
return handleWechatOAuthError(event, "token", tokens, onError);
|
|
90
|
+
}
|
|
91
|
+
const user = await $fetch(config.userURL, {
|
|
92
|
+
responseType: "json",
|
|
93
|
+
query: {
|
|
94
|
+
access_token: tokens.access_token,
|
|
95
|
+
openid: tokens.openid,
|
|
96
|
+
lang: config.lang
|
|
97
|
+
}
|
|
98
|
+
}).catch((error) => ({ errcode: error?.response?.status ?? -1, errmsg: "userinfo request failed" }));
|
|
99
|
+
if (isWechatOAuthError(user)) {
|
|
100
|
+
return handleWechatOAuthError(event, "userinfo", user, onError);
|
|
101
|
+
}
|
|
102
|
+
return onSuccess(event, {
|
|
103
|
+
tokens,
|
|
104
|
+
user
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
}
|
|
@@ -30,7 +30,7 @@ export function defineOAuthWorkOSEventHandler({ config, onSuccess, onError }) {
|
|
|
30
30
|
})
|
|
31
31
|
);
|
|
32
32
|
}
|
|
33
|
-
if (query.state !== state) {
|
|
33
|
+
if (!state || query.state !== state) {
|
|
34
34
|
return handleInvalidState(event, "workos", onError);
|
|
35
35
|
}
|
|
36
36
|
const authenticateResponse = await requestAccessToken("https://api.workos.com/user_management/authenticate", {
|
|
@@ -27,7 +27,7 @@ export function defineOAuthXSUAAEventHandler({ config, onSuccess, onError }) {
|
|
|
27
27
|
})
|
|
28
28
|
);
|
|
29
29
|
}
|
|
30
|
-
if (query.state !== state) {
|
|
30
|
+
if (!state || query.state !== state) {
|
|
31
31
|
return handleInvalidState(event, "xsuaa", onError);
|
|
32
32
|
}
|
|
33
33
|
const tokens = await requestAccessToken(tokenURL, {
|
|
@@ -48,7 +48,7 @@ export function defineOAuthYandexEventHandler({
|
|
|
48
48
|
})
|
|
49
49
|
);
|
|
50
50
|
}
|
|
51
|
-
if (query.state !== state) {
|
|
51
|
+
if (!state || query.state !== state) {
|
|
52
52
|
return handleInvalidState(event, "yandex", onError);
|
|
53
53
|
}
|
|
54
54
|
const tokens = await requestAccessToken(config.tokenURL, {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type H3Event } from 'h3';
|
|
2
2
|
import * as jose from 'jose';
|
|
3
3
|
import type { OAuthProvider, OnError } from '#auth-utils';
|
|
4
|
+
export declare const isDevelopment: boolean;
|
|
4
5
|
export declare function getOAuthRedirectURL(event: H3Event): string;
|
|
5
6
|
/**
|
|
6
7
|
* Request an access token body.
|
|
@@ -5,7 +5,7 @@ import { snakeCase, upperFirst } from "scule";
|
|
|
5
5
|
import * as jose from "jose";
|
|
6
6
|
import { subtle, getRandomValues } from "uncrypto";
|
|
7
7
|
import { createError } from "#imports";
|
|
8
|
-
const isDevelopment = process.env.NODE_ENV === "development";
|
|
8
|
+
export const isDevelopment = process.env.NODE_ENV === "development";
|
|
9
9
|
const OAUTH_COOKIE_MAX_AGE = 60 * 10;
|
|
10
10
|
export function getOAuthRedirectURL(event) {
|
|
11
11
|
const requestURL = getRequestURL(event);
|
|
@@ -24,14 +24,14 @@ export async function requestAccessToken(url, options) {
|
|
|
24
24
|
headers,
|
|
25
25
|
body
|
|
26
26
|
}).catch((error) => {
|
|
27
|
-
if (error instanceof FetchError && error.status
|
|
27
|
+
if (error instanceof FetchError && error.status && error.status >= 400 && error.status < 500 && error.data?.error) {
|
|
28
28
|
return error.data;
|
|
29
29
|
}
|
|
30
30
|
throw error;
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
33
|
export function handleAccessTokenErrorResponse(event, oauthProvider, oauthError, onError) {
|
|
34
|
-
const message = `${upperFirst(oauthProvider)} login failed: ${oauthError.error_description || oauthError.error || "Unknown error"}`;
|
|
34
|
+
const message = `${upperFirst(oauthProvider)} login failed: ${oauthError.error_description || oauthError.error?.message || oauthError.error || "Unknown error"}`;
|
|
35
35
|
const error = createError({
|
|
36
36
|
statusCode: 401,
|
|
37
37
|
message,
|
|
@@ -18,7 +18,12 @@ export async function setUserSession(event, data, config) {
|
|
|
18
18
|
export async function replaceUserSession(event, data, config) {
|
|
19
19
|
const session = await _useSession(event, config);
|
|
20
20
|
await session.clear();
|
|
21
|
-
await session.update(
|
|
21
|
+
await session.update((oldData) => {
|
|
22
|
+
for (const key of Object.keys(oldData)) {
|
|
23
|
+
Reflect.deleteProperty(oldData, key);
|
|
24
|
+
}
|
|
25
|
+
return data;
|
|
26
|
+
});
|
|
22
27
|
return session.data;
|
|
23
28
|
}
|
|
24
29
|
export async function clearUserSession(event, config) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { H3Event, H3Error } from 'h3';
|
|
2
2
|
export type ATProtoProvider = 'bluesky';
|
|
3
|
-
export type OAuthProvider = ATProtoProvider | 'atlassian' | 'auth0' | 'authentik' | 'azureb2c' | 'battledotnet' | 'cognito' | 'discord' | 'dropbox' | 'facebook' | 'gitea' | 'github' | 'gitlab' | 'google' | 'hubspot' | 'instagram' | 'kick' | 'keycloak' | 'line' | 'linear' | 'linkedin' | 'microsoft' | 'paypal' | 'polar' | 'spotify' | 'seznam' | 'steam' | 'strava' | 'tiktok' | 'twitch' | 'vk' | 'workos' | 'x' | 'xsuaa' | 'yandex' | 'zitadel' | 'apple' | 'livechat' | 'salesforce' | 'slack' | 'heroku' | 'roblox' | 'okta' | 'ory' | 'shopifyCustomer' | 'oidc' | 'osu' | 'riotgames' | 'box' | (string & {});
|
|
3
|
+
export type OAuthProvider = ATProtoProvider | 'atlassian' | 'auth0' | 'authentik' | 'azureb2c' | 'battledotnet' | 'cloudflare' | 'cognito' | 'discord' | 'dropbox' | 'facebook' | 'gitea' | 'github' | 'gitlab' | 'google' | 'hubspot' | 'instagram' | 'kick' | 'keycloak' | 'line' | 'linear' | 'linkedin' | 'mastodon' | 'microsoft' | 'paypal' | 'polar' | 'spotify' | 'seznam' | 'steam' | 'strava' | 'tiktok' | 'twitch' | 'vk' | 'wechat' | 'workos' | 'x' | 'xsuaa' | 'yandex' | 'zitadel' | 'apple' | 'livechat' | 'salesforce' | 'slack' | 'heroku' | 'roblox' | 'okta' | 'ory' | 'shopifyCustomer' | 'oidc' | 'osu' | 'riotgames' | 'box' | (string & {});
|
|
4
4
|
export type OnError = (event: H3Event, error: H3Error) => Promise<void> | void;
|
|
5
5
|
export interface OAuthConfig<TConfig, TResult = {
|
|
6
6
|
user: any;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-auth-utils",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.33",
|
|
4
4
|
"description": "Add Authentication to Nuxt applications with secured & sealed cookies sessions.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
},
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"type": "module",
|
|
11
|
-
"packageManager": "pnpm@10.29.3",
|
|
12
11
|
"exports": {
|
|
13
12
|
".": {
|
|
14
13
|
"types": "./dist/types.d.mts",
|
|
@@ -26,18 +25,6 @@
|
|
|
26
25
|
"files": [
|
|
27
26
|
"dist"
|
|
28
27
|
],
|
|
29
|
-
"scripts": {
|
|
30
|
-
"prepack": "nuxt-module-build build",
|
|
31
|
-
"dev": "nuxi dev playground",
|
|
32
|
-
"dev:build": "nuxi build playground",
|
|
33
|
-
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
|
|
34
|
-
"release": "npm run lint && npm run test && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
|
|
35
|
-
"lint": "eslint .",
|
|
36
|
-
"lint:fix": "eslint . --fix",
|
|
37
|
-
"test": "vitest run",
|
|
38
|
-
"test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit",
|
|
39
|
-
"test:watch": "vitest watch"
|
|
40
|
-
},
|
|
41
28
|
"dependencies": {
|
|
42
29
|
"@adonisjs/hash": "^9.1.1",
|
|
43
30
|
"@nuxt/kit": "^4.3.1",
|
|
@@ -81,11 +68,20 @@
|
|
|
81
68
|
"@nuxt/ui": "^4.4.0",
|
|
82
69
|
"@simplewebauthn/types": "^12.0.0",
|
|
83
70
|
"@types/node": "latest",
|
|
84
|
-
"changelogen": "^0.6.2",
|
|
85
71
|
"eslint": "^10.0.0",
|
|
86
72
|
"nuxt": "^4.6.0",
|
|
87
73
|
"typescript": "5.9.3",
|
|
88
74
|
"vitest": "^4.0.18",
|
|
89
75
|
"vue-tsc": "^3.2.4"
|
|
76
|
+
},
|
|
77
|
+
"scripts": {
|
|
78
|
+
"dev": "nuxi dev playground",
|
|
79
|
+
"dev:build": "nuxi build playground",
|
|
80
|
+
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
|
|
81
|
+
"lint": "eslint .",
|
|
82
|
+
"lint:fix": "eslint . --fix",
|
|
83
|
+
"test": "vitest run",
|
|
84
|
+
"test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit",
|
|
85
|
+
"test:watch": "vitest watch"
|
|
90
86
|
}
|
|
91
|
-
}
|
|
87
|
+
}
|