nuxt-auth-utils 0.2.0 → 0.2.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 +1 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +9 -1
- package/dist/runtime/app/components/AuthState.vue +3 -4
- package/dist/runtime/server/lib/oauth/x.d.ts +6 -1
- package/dist/runtime/server/lib/oauth/x.js +24 -0
- package/dist/runtime/server/lib/oauth/yandex.d.ts +41 -0
- package/dist/runtime/server/lib/oauth/yandex.js +84 -0
- package/dist/runtime/server/utils/oauth.d.ts +2 -0
- package/dist/runtime/server/utils/oauth.js +3 -1
- package/package.json +2 -1
package/README.md
CHANGED
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -43,7 +43,11 @@ const module = defineNuxtModule({
|
|
|
43
43
|
const envPath = join(nuxt.options.rootDir, ".env");
|
|
44
44
|
const envContent = await readFile(envPath, "utf-8").catch(() => "");
|
|
45
45
|
if (!envContent.includes("NUXT_SESSION_PASSWORD")) {
|
|
46
|
-
await writeFile(
|
|
46
|
+
await writeFile(
|
|
47
|
+
envPath,
|
|
48
|
+
`${envContent ? envContent + "\n" : envContent}NUXT_SESSION_PASSWORD=${runtimeConfig.session.password}`,
|
|
49
|
+
"utf-8"
|
|
50
|
+
);
|
|
47
51
|
}
|
|
48
52
|
}
|
|
49
53
|
runtimeConfig.oauth = defu(runtimeConfig.oauth, {});
|
|
@@ -122,6 +126,10 @@ const module = defineNuxtModule({
|
|
|
122
126
|
clientSecret: "",
|
|
123
127
|
domain: ""
|
|
124
128
|
});
|
|
129
|
+
runtimeConfig.oauth.yandex = defu(runtimeConfig.oauth.yandex, {
|
|
130
|
+
clientId: "",
|
|
131
|
+
clientSecret: ""
|
|
132
|
+
});
|
|
125
133
|
}
|
|
126
134
|
});
|
|
127
135
|
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
<script setup>
|
|
1
|
+
<script lang="ts" setup>
|
|
2
2
|
import { useUserSession } from '#imports'
|
|
3
3
|
|
|
4
|
-
const
|
|
5
|
-
const { ready } = userSession
|
|
4
|
+
const { loggedIn, user, clear, ready } = useUserSession()
|
|
6
5
|
</script>
|
|
7
6
|
|
|
8
7
|
<template>
|
|
9
8
|
<slot
|
|
10
9
|
v-if="ready"
|
|
11
|
-
v-bind="
|
|
10
|
+
v-bind="{ loggedIn, user, clear }"
|
|
12
11
|
/>
|
|
13
12
|
<slot
|
|
14
13
|
v-else
|
|
@@ -14,9 +14,14 @@ export interface OAuthXConfig {
|
|
|
14
14
|
* X OAuth Scope
|
|
15
15
|
* @default []
|
|
16
16
|
* @see https://developer.x.com/en/docs/authentication/oauth-2-0/user-access-token
|
|
17
|
-
* @example [
|
|
17
|
+
* @example ['tweet.read', 'users.read', 'offline.access'],
|
|
18
18
|
*/
|
|
19
19
|
scope?: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Require email from user
|
|
22
|
+
* @default false
|
|
23
|
+
*/
|
|
24
|
+
emailRequired?: boolean;
|
|
20
25
|
/**
|
|
21
26
|
* X OAuth Authorization URL
|
|
22
27
|
* @default 'https://twitter.com/i/oauth2/authorize'
|
|
@@ -90,6 +90,30 @@ export function xEventHandler({
|
|
|
90
90
|
).catch((error) => {
|
|
91
91
|
return error;
|
|
92
92
|
});
|
|
93
|
+
if (config.emailRequired) {
|
|
94
|
+
const emailData = await $fetch("https://api.twitter.com/1.1/account/verify_credentials.json", {
|
|
95
|
+
headers: {
|
|
96
|
+
Authorization: `Bearer ${accessToken}`
|
|
97
|
+
},
|
|
98
|
+
query: {
|
|
99
|
+
include_email: "true",
|
|
100
|
+
skip_status: "true"
|
|
101
|
+
}
|
|
102
|
+
}).catch((error) => {
|
|
103
|
+
return error;
|
|
104
|
+
});
|
|
105
|
+
if (emailData && emailData.email) {
|
|
106
|
+
user.email = emailData.email;
|
|
107
|
+
} else {
|
|
108
|
+
const error = createError({
|
|
109
|
+
statusCode: 401,
|
|
110
|
+
message: "Twitter login failed: no user email found"
|
|
111
|
+
});
|
|
112
|
+
if (!onError)
|
|
113
|
+
throw error;
|
|
114
|
+
return onError(event, error);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
93
117
|
return onSuccess(event, {
|
|
94
118
|
tokens,
|
|
95
119
|
user: user?.data
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { OAuthConfig } from '#auth-utils';
|
|
2
|
+
export interface OAuthYandexConfig {
|
|
3
|
+
/**
|
|
4
|
+
* Yandex OAuth Client ID
|
|
5
|
+
* @default process.env.NUXT_OAUTH_YANDEX_CLIENT_ID
|
|
6
|
+
*/
|
|
7
|
+
clientId?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Yandex OAuth Client Secret
|
|
10
|
+
* @default process.env.NUXT_OAUTH_YANDEX_CLIENT_SECRET
|
|
11
|
+
*/
|
|
12
|
+
clientSecret?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Yandex OAuth Scope
|
|
15
|
+
* @default []
|
|
16
|
+
* @see https://yandex.ru/dev/id/doc/en/codes/code-url#optional
|
|
17
|
+
* @example ["login:avatar", "login:birthday", "login:email", "login:info", "login:default_phone"]
|
|
18
|
+
*/
|
|
19
|
+
scope?: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Require email from user, adds the ['login:email'] scope if not present
|
|
22
|
+
* @default false
|
|
23
|
+
*/
|
|
24
|
+
emailRequired?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Yandex OAuth Authorization URL
|
|
27
|
+
* @default 'https://oauth.yandex.ru/authorize'
|
|
28
|
+
*/
|
|
29
|
+
authorizationURL?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Yandex OAuth Token URL
|
|
32
|
+
* @default 'https://oauth.yandex.ru/token'
|
|
33
|
+
*/
|
|
34
|
+
tokenURL?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Yandex OAuth User URL
|
|
37
|
+
* @default 'https://login.yandex.ru/info'
|
|
38
|
+
*/
|
|
39
|
+
userURL?: string;
|
|
40
|
+
}
|
|
41
|
+
export declare function yandexEventHandler({ config, onSuccess, onError, }: OAuthConfig<OAuthYandexConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import {
|
|
2
|
+
eventHandler,
|
|
3
|
+
createError,
|
|
4
|
+
getQuery,
|
|
5
|
+
getRequestURL,
|
|
6
|
+
sendRedirect
|
|
7
|
+
} from "h3";
|
|
8
|
+
import { withQuery, parseURL, stringifyParsedURL } from "ufo";
|
|
9
|
+
import { defu } from "defu";
|
|
10
|
+
import { useRuntimeConfig } from "#imports";
|
|
11
|
+
export function yandexEventHandler({
|
|
12
|
+
config,
|
|
13
|
+
onSuccess,
|
|
14
|
+
onError
|
|
15
|
+
}) {
|
|
16
|
+
return eventHandler(async (event) => {
|
|
17
|
+
config = defu(config, useRuntimeConfig(event).oauth?.yandex, {
|
|
18
|
+
authorizationURL: "https://oauth.yandex.ru/authorize",
|
|
19
|
+
tokenURL: "https://oauth.yandex.ru/token",
|
|
20
|
+
userURL: "https://login.yandex.ru/info"
|
|
21
|
+
});
|
|
22
|
+
const { code } = getQuery(event);
|
|
23
|
+
if (!config.clientId || !config.clientSecret) {
|
|
24
|
+
const error = createError({
|
|
25
|
+
statusCode: 500,
|
|
26
|
+
message: "Missing NUXT_OAUTH_YANDEX_CLIENT_ID or NUXT_OAUTH_YANDEX_CLIENT_SECRET env variables."
|
|
27
|
+
});
|
|
28
|
+
if (!onError)
|
|
29
|
+
throw error;
|
|
30
|
+
return onError(event, error);
|
|
31
|
+
}
|
|
32
|
+
const redirectUrl = getRequestURL(event).href;
|
|
33
|
+
if (!code) {
|
|
34
|
+
config.scope = config.scope || [];
|
|
35
|
+
if (config.emailRequired && !config.scope.includes("login:email")) {
|
|
36
|
+
config.scope.push("login:email");
|
|
37
|
+
}
|
|
38
|
+
return sendRedirect(
|
|
39
|
+
event,
|
|
40
|
+
withQuery(config.authorizationURL, {
|
|
41
|
+
response_type: "code",
|
|
42
|
+
client_id: config.clientId,
|
|
43
|
+
redirect_uri: redirectUrl,
|
|
44
|
+
scope: config.scope.join(" ")
|
|
45
|
+
})
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
const tokens = await $fetch(config.tokenURL, {
|
|
49
|
+
method: "POST",
|
|
50
|
+
headers: {
|
|
51
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
52
|
+
},
|
|
53
|
+
body: new URLSearchParams({
|
|
54
|
+
client_id: config.clientId,
|
|
55
|
+
client_secret: config.clientSecret,
|
|
56
|
+
grant_type: "authorization_code",
|
|
57
|
+
redirect_uri: stringifyParsedURL(parseURL(redirectUrl)),
|
|
58
|
+
code
|
|
59
|
+
}).toString()
|
|
60
|
+
}).catch((error) => {
|
|
61
|
+
return { error };
|
|
62
|
+
});
|
|
63
|
+
if (tokens.error) {
|
|
64
|
+
const error = createError({
|
|
65
|
+
statusCode: 401,
|
|
66
|
+
message: `Yandex login failed: ${tokens.error?.data?.error_description || "Unknown error"}`,
|
|
67
|
+
data: tokens
|
|
68
|
+
});
|
|
69
|
+
if (!onError)
|
|
70
|
+
throw error;
|
|
71
|
+
return onError(event, error);
|
|
72
|
+
}
|
|
73
|
+
const accessToken = tokens.access_token;
|
|
74
|
+
const user = await $fetch(config.userURL, {
|
|
75
|
+
headers: {
|
|
76
|
+
Authorization: `OAuth ${accessToken}`
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
return onSuccess(event, {
|
|
80
|
+
tokens,
|
|
81
|
+
user
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
}
|
|
@@ -14,6 +14,7 @@ import { paypalEventHandler } from '../lib/oauth/paypal.js';
|
|
|
14
14
|
import { steamEventHandler } from '../lib/oauth/steam.js';
|
|
15
15
|
import { xEventHandler } from '../lib/oauth/x.js';
|
|
16
16
|
import { xsuaaEventHandler } from '../lib/oauth/xsuaa.js';
|
|
17
|
+
import { yandexEventHandler } from '../lib/oauth/yandex.js';
|
|
17
18
|
export declare const oauth: {
|
|
18
19
|
githubEventHandler: typeof githubEventHandler;
|
|
19
20
|
spotifyEventHandler: typeof spotifyEventHandler;
|
|
@@ -31,4 +32,5 @@ export declare const oauth: {
|
|
|
31
32
|
steamEventHandler: typeof steamEventHandler;
|
|
32
33
|
xEventHandler: typeof xEventHandler;
|
|
33
34
|
xsuaaEventHandler: typeof xsuaaEventHandler;
|
|
35
|
+
yandexEventHandler: typeof yandexEventHandler;
|
|
34
36
|
};
|
|
@@ -14,6 +14,7 @@ import { paypalEventHandler } from "../lib/oauth/paypal.js";
|
|
|
14
14
|
import { steamEventHandler } from "../lib/oauth/steam.js";
|
|
15
15
|
import { xEventHandler } from "../lib/oauth/x.js";
|
|
16
16
|
import { xsuaaEventHandler } from "../lib/oauth/xsuaa.js";
|
|
17
|
+
import { yandexEventHandler } from "../lib/oauth/yandex.js";
|
|
17
18
|
export const oauth = {
|
|
18
19
|
githubEventHandler,
|
|
19
20
|
spotifyEventHandler,
|
|
@@ -30,5 +31,6 @@ export const oauth = {
|
|
|
30
31
|
paypalEventHandler,
|
|
31
32
|
steamEventHandler,
|
|
32
33
|
xEventHandler,
|
|
33
|
-
xsuaaEventHandler
|
|
34
|
+
xsuaaEventHandler,
|
|
35
|
+
yandexEventHandler
|
|
34
36
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-auth-utils",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Minimalist Auth module for Nuxt with SSR",
|
|
5
5
|
"repository": "Atinux/nuxt-auth-utils",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
|
|
26
26
|
"release": "npm run lint && npm run test && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
|
|
27
27
|
"lint": "eslint .",
|
|
28
|
+
"lint:fix": "eslint . --fix",
|
|
28
29
|
"test": "vitest run",
|
|
29
30
|
"test:types": "vue-tsc --noEmit",
|
|
30
31
|
"test:types:playground": "cd playground && vue-tsc --noEmit",
|