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 CHANGED
@@ -166,6 +166,7 @@ It can also be set using environment variables:
166
166
  - Twitch
167
167
  - X (Twitter)
168
168
  - XSUAA
169
+ - Yandex
169
170
 
170
171
  You can add your favorite provider by creating a new file in [src/runtime/server/lib/oauth/](./src/runtime/server/lib/oauth/).
171
172
 
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "auth-utils",
3
3
  "configKey": "auth",
4
- "version": "0.2.0",
4
+ "version": "0.2.1",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "0.7.1",
7
7
  "unbuild": "2.0.0"
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(envPath, `${envContent ? envContent + "\n" : envContent}NUXT_SESSION_PASSWORD=${runtimeConfig.session.password}`, "utf-8");
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 userSession = useUserSession()
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="userSession"
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 [ 'tweet.read','users.read','offline.access ],
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.0",
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",