nuxt-auth-utils 0.2.0 → 0.3.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.
Files changed (41) hide show
  1. package/README.md +41 -4
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +10 -1
  4. package/dist/runtime/app/components/AuthState.vue +3 -4
  5. package/dist/runtime/server/lib/oauth/auth0.d.ts +1 -1
  6. package/dist/runtime/server/lib/oauth/auth0.js +1 -1
  7. package/dist/runtime/server/lib/oauth/battledotnet.d.ts +1 -1
  8. package/dist/runtime/server/lib/oauth/battledotnet.js +1 -1
  9. package/dist/runtime/server/lib/oauth/cognito.d.ts +1 -1
  10. package/dist/runtime/server/lib/oauth/cognito.js +1 -1
  11. package/dist/runtime/server/lib/oauth/discord.d.ts +1 -1
  12. package/dist/runtime/server/lib/oauth/discord.js +1 -1
  13. package/dist/runtime/server/lib/oauth/facebook.d.ts +1 -1
  14. package/dist/runtime/server/lib/oauth/facebook.js +1 -1
  15. package/dist/runtime/server/lib/oauth/github.d.ts +1 -1
  16. package/dist/runtime/server/lib/oauth/github.js +1 -1
  17. package/dist/runtime/server/lib/oauth/google.d.ts +1 -1
  18. package/dist/runtime/server/lib/oauth/google.js +1 -1
  19. package/dist/runtime/server/lib/oauth/keycloak.d.ts +1 -1
  20. package/dist/runtime/server/lib/oauth/keycloak.js +1 -1
  21. package/dist/runtime/server/lib/oauth/linkedin.d.ts +1 -1
  22. package/dist/runtime/server/lib/oauth/linkedin.js +1 -1
  23. package/dist/runtime/server/lib/oauth/microsoft.d.ts +1 -1
  24. package/dist/runtime/server/lib/oauth/microsoft.js +1 -1
  25. package/dist/runtime/server/lib/oauth/paypal.d.ts +1 -1
  26. package/dist/runtime/server/lib/oauth/paypal.js +1 -1
  27. package/dist/runtime/server/lib/oauth/spotify.d.ts +1 -1
  28. package/dist/runtime/server/lib/oauth/spotify.js +1 -1
  29. package/dist/runtime/server/lib/oauth/steam.d.ts +1 -1
  30. package/dist/runtime/server/lib/oauth/steam.js +1 -1
  31. package/dist/runtime/server/lib/oauth/twitch.d.ts +1 -1
  32. package/dist/runtime/server/lib/oauth/twitch.js +1 -1
  33. package/dist/runtime/server/lib/oauth/x.d.ts +7 -2
  34. package/dist/runtime/server/lib/oauth/x.js +25 -1
  35. package/dist/runtime/server/lib/oauth/xsuaa.d.ts +1 -1
  36. package/dist/runtime/server/lib/oauth/xsuaa.js +1 -1
  37. package/dist/runtime/server/lib/oauth/yandex.d.ts +41 -0
  38. package/dist/runtime/server/lib/oauth/yandex.js +84 -0
  39. package/package.json +2 -1
  40. package/dist/runtime/server/utils/oauth.d.ts +0 -34
  41. package/dist/runtime/server/utils/oauth.js +0 -34
package/README.md CHANGED
@@ -21,6 +21,8 @@ Add Authentication to Nuxt applications with secured & sealed cookies sessions.
21
21
  - [`<AuthState>` component](#authstate-component)
22
22
  - [Extendable with hooks](#extend-session)
23
23
 
24
+ 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.
25
+
24
26
  ## Requirements
25
27
 
26
28
  This module only works with a Nuxt server running as it uses server API routes (`nuxt build`).
@@ -56,7 +58,7 @@ Nuxt Auth Utils automatically adds some plugins to fetch the current user sessio
56
58
 
57
59
  ```vue
58
60
  <script setup>
59
- const { loggedIn, user, session, clear } = useUserSession()
61
+ const { loggedIn, user, session, fetch, clear } = useUserSession()
60
62
  </script>
61
63
 
62
64
  <template>
@@ -72,6 +74,37 @@ const { loggedIn, user, session, clear } = useUserSession()
72
74
  </template>
73
75
  ```
74
76
 
77
+ **TypeScript Signature:**
78
+
79
+ ```ts
80
+ interface UserSessionComposable {
81
+ /**
82
+ * Computed indicating if the auth session is ready
83
+ */
84
+ ready: ComputedRef<boolean>
85
+ /**
86
+ * Computed indicating if the user is logged in.
87
+ */
88
+ loggedIn: ComputedRef<boolean>
89
+ /**
90
+ * The user object if logged in, null otherwise.
91
+ */
92
+ user: ComputedRef<User | null>
93
+ /**
94
+ * The session object.
95
+ */
96
+ session: Ref<UserSession>
97
+ /**
98
+ * Fetch the user session from the server.
99
+ */
100
+ fetch: () => Promise<void>
101
+ /**
102
+ * Clear the user session and remove the session cookie.
103
+ */
104
+ clear: () => Promise<void>
105
+ }
106
+ ```
107
+
75
108
  ## Server Utils
76
109
 
77
110
  The following helpers are auto-imported in your `server/` directory.
@@ -122,9 +155,9 @@ export {}
122
155
 
123
156
  ### OAuth Event Handlers
124
157
 
125
- All helpers are exposed from the `oauth` global variable and can be used in your server routes or API routes.
158
+ All handlers can be auto-imported and used in your server routes or API routes.
126
159
 
127
- The pattern is `oauth.<provider>EventHandler({ onSuccess, config?, onError? })`, example: `oauth.githubEventHandler`.
160
+ The pattern is `oauth<Provider>EventHandler({ onSuccess, config?, onError? })`, example: `authGitHubEventHandler`.
128
161
 
129
162
  The helper returns an event handler that automatically redirects to the provider authorization page and then calls `onSuccess` or `onError` depending on the result.
130
163
 
@@ -134,6 +167,7 @@ The `config` can be defined directly from the `runtimeConfig` in your `nuxt.conf
134
167
  export default defineNuxtConfig({
135
168
  runtimeConfig: {
136
169
  oauth: {
170
+ // provider in lowercase (github, google, etc.)
137
171
  <provider>: {
138
172
  clientId: '...',
139
173
  clientSecret: '...'
@@ -148,6 +182,8 @@ It can also be set using environment variables:
148
182
  - `NUXT_OAUTH_<PROVIDER>_CLIENT_ID`
149
183
  - `NUXT_OAUTH_<PROVIDER>_CLIENT_SECRET`
150
184
 
185
+ > Provider is in uppercase (GITHUB, GOOGLE, etc.)
186
+
151
187
  #### Supported OAuth Providers
152
188
 
153
189
  - Auth0
@@ -166,6 +202,7 @@ It can also be set using environment variables:
166
202
  - Twitch
167
203
  - X (Twitter)
168
204
  - XSUAA
205
+ - Yandex
169
206
 
170
207
  You can add your favorite provider by creating a new file in [src/runtime/server/lib/oauth/](./src/runtime/server/lib/oauth/).
171
208
 
@@ -174,7 +211,7 @@ You can add your favorite provider by creating a new file in [src/runtime/server
174
211
  Example: `~/server/routes/auth/github.get.ts`
175
212
 
176
213
  ```ts
177
- export default oauth.githubEventHandler({
214
+ export default oauthGitHubEventHandler({
178
215
  config: {
179
216
  emailRequired: true
180
217
  },
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.3.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "0.7.1",
7
7
  "unbuild": "2.0.0"
package/dist/module.mjs CHANGED
@@ -19,6 +19,7 @@ const module = defineNuxtModule({
19
19
  addPlugin(resolver.resolve("./runtime/app/plugins/session.server"));
20
20
  addPlugin(resolver.resolve("./runtime/app/plugins/session.client"));
21
21
  addServerPlugin(resolver.resolve("./runtime/server/plugins/oauth"));
22
+ addServerImportsDir(resolver.resolve("./runtime/server/lib/oauth"));
22
23
  addServerImportsDir(resolver.resolve("./runtime/server/utils"));
23
24
  addServerHandler({
24
25
  handler: resolver.resolve("./runtime/server/api/session.delete"),
@@ -43,7 +44,11 @@ const module = defineNuxtModule({
43
44
  const envPath = join(nuxt.options.rootDir, ".env");
44
45
  const envContent = await readFile(envPath, "utf-8").catch(() => "");
45
46
  if (!envContent.includes("NUXT_SESSION_PASSWORD")) {
46
- await writeFile(envPath, `${envContent ? envContent + "\n" : envContent}NUXT_SESSION_PASSWORD=${runtimeConfig.session.password}`, "utf-8");
47
+ await writeFile(
48
+ envPath,
49
+ `${envContent ? envContent + "\n" : envContent}NUXT_SESSION_PASSWORD=${runtimeConfig.session.password}`,
50
+ "utf-8"
51
+ );
47
52
  }
48
53
  }
49
54
  runtimeConfig.oauth = defu(runtimeConfig.oauth, {});
@@ -122,6 +127,10 @@ const module = defineNuxtModule({
122
127
  clientSecret: "",
123
128
  domain: ""
124
129
  });
130
+ runtimeConfig.oauth.yandex = defu(runtimeConfig.oauth.yandex, {
131
+ clientId: "",
132
+ clientSecret: ""
133
+ });
125
134
  }
126
135
  });
127
136
 
@@ -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
@@ -52,4 +52,4 @@ export interface OAuthAuth0Config {
52
52
  */
53
53
  authorizationParams?: Record<string, string>;
54
54
  }
55
- export declare function auth0EventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthAuth0Config>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
55
+ export declare function oauthAuth0EventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthAuth0Config>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
@@ -2,7 +2,7 @@ import { eventHandler, createError, getQuery, getRequestURL, sendRedirect } from
2
2
  import { withQuery, parsePath } from "ufo";
3
3
  import { defu } from "defu";
4
4
  import { useRuntimeConfig } from "#imports";
5
- export function auth0EventHandler({ config, onSuccess, onError }) {
5
+ export function oauthAuth0EventHandler({ config, onSuccess, onError }) {
6
6
  return eventHandler(async (event) => {
7
7
  config = defu(config, useRuntimeConfig(event).oauth?.auth0, {
8
8
  authorizationParams: {}
@@ -40,4 +40,4 @@ export interface OAuthBattledotnetConfig {
40
40
  */
41
41
  authorizationParams?: Record<string, string>;
42
42
  }
43
- export declare function battledotnetEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthBattledotnetConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
43
+ export declare function oauthBattledotnetEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthBattledotnetConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
@@ -3,7 +3,7 @@ import { eventHandler, createError, getQuery, getRequestURL, sendRedirect } from
3
3
  import { withQuery, parsePath } from "ufo";
4
4
  import { defu } from "defu";
5
5
  import { useRuntimeConfig } from "#imports";
6
- export function battledotnetEventHandler({ config, onSuccess, onError }) {
6
+ export function oauthBattledotnetEventHandler({ config, onSuccess, onError }) {
7
7
  return eventHandler(async (event) => {
8
8
  config = defu(config, useRuntimeConfig(event).oauth?.battledotnet, {
9
9
  authorizationURL: "https://oauth.battle.net/authorize",
@@ -31,4 +31,4 @@ export interface OAuthCognitoConfig {
31
31
  */
32
32
  authorizationParams?: Record<string, string>;
33
33
  }
34
- export declare function cognitoEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthCognitoConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
34
+ export declare function oauthCognitoEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthCognitoConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
@@ -2,7 +2,7 @@ import { eventHandler, createError, getQuery, getRequestURL, sendRedirect } from
2
2
  import { withQuery, parsePath } from "ufo";
3
3
  import { defu } from "defu";
4
4
  import { useRuntimeConfig } from "#imports";
5
- export function cognitoEventHandler({ config, onSuccess, onError }) {
5
+ export function oauthCognitoEventHandler({ config, onSuccess, onError }) {
6
6
  return eventHandler(async (event) => {
7
7
  config = defu(config, useRuntimeConfig(event).oauth?.cognito, {
8
8
  authorizationParams: {}
@@ -45,4 +45,4 @@ export interface OAuthDiscordConfig {
45
45
  */
46
46
  authorizationParams?: Record<string, string>;
47
47
  }
48
- export declare function discordEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthDiscordConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
48
+ export declare function oauthDiscordEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthDiscordConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
@@ -2,7 +2,7 @@ import { eventHandler, createError, getQuery, getRequestURL, sendRedirect } from
2
2
  import { withQuery, parseURL, stringifyParsedURL } from "ufo";
3
3
  import { defu } from "defu";
4
4
  import { useRuntimeConfig } from "#imports";
5
- export function discordEventHandler({ config, onSuccess, onError }) {
5
+ export function oauthDiscordEventHandler({ config, onSuccess, onError }) {
6
6
  return eventHandler(async (event) => {
7
7
  config = defu(config, useRuntimeConfig(event).oauth?.discord, {
8
8
  authorizationURL: "https://discord.com/oauth2/authorize",
@@ -40,4 +40,4 @@ export interface OAuthFacebookConfig {
40
40
  */
41
41
  authorizationParams?: Record<string, string>;
42
42
  }
43
- export declare function facebookEventHandler({ config, onSuccess, onError, }: OAuthConfig<OAuthFacebookConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
43
+ export declare function oauthFacebookEventHandler({ config, onSuccess, onError, }: OAuthConfig<OAuthFacebookConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
@@ -8,7 +8,7 @@ import {
8
8
  import { withQuery } from "ufo";
9
9
  import { defu } from "defu";
10
10
  import { useRuntimeConfig } from "#imports";
11
- export function facebookEventHandler({
11
+ export function oauthFacebookEventHandler({
12
12
  config,
13
13
  onSuccess,
14
14
  onError
@@ -39,4 +39,4 @@ export interface OAuthGitHubConfig {
39
39
  */
40
40
  authorizationParams?: Record<string, string>;
41
41
  }
42
- export declare function githubEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthGitHubConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
42
+ export declare function oauthGitHubEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthGitHubConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
@@ -2,7 +2,7 @@ import { eventHandler, createError, getQuery, getRequestURL, sendRedirect } from
2
2
  import { withQuery } from "ufo";
3
3
  import { defu } from "defu";
4
4
  import { useRuntimeConfig } from "#imports";
5
- export function githubEventHandler({ config, onSuccess, onError }) {
5
+ export function oauthGitHubEventHandler({ config, onSuccess, onError }) {
6
6
  return eventHandler(async (event) => {
7
7
  config = defu(config, useRuntimeConfig(event).oauth?.github, {
8
8
  authorizationURL: "https://github.com/login/oauth/authorize",
@@ -39,4 +39,4 @@ export interface OAuthGoogleConfig {
39
39
  */
40
40
  authorizationParams?: Record<string, string>;
41
41
  }
42
- export declare function googleEventHandler({ config, onSuccess, onError, }: OAuthConfig<OAuthGoogleConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
42
+ export declare function oauthGoogleEventHandler({ config, onSuccess, onError, }: OAuthConfig<OAuthGoogleConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
@@ -8,7 +8,7 @@ import {
8
8
  import { withQuery, parsePath } from "ufo";
9
9
  import { defu } from "defu";
10
10
  import { useRuntimeConfig } from "#imports";
11
- export function googleEventHandler({
11
+ export function oauthGoogleEventHandler({
12
12
  config,
13
13
  onSuccess,
14
14
  onError
@@ -33,4 +33,4 @@ export interface OAuthKeycloakConfig {
33
33
  */
34
34
  authorizationParams?: Record<string, string>;
35
35
  }
36
- export declare function keycloakEventHandler({ config, onSuccess, onError, }: OAuthConfig<OAuthKeycloakConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
36
+ export declare function oauthKeycloakEventHandler({ config, onSuccess, onError, }: OAuthConfig<OAuthKeycloakConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
@@ -8,7 +8,7 @@ import {
8
8
  import { withQuery, parsePath } from "ufo";
9
9
  import { defu } from "defu";
10
10
  import { useRuntimeConfig } from "#imports";
11
- export function keycloakEventHandler({
11
+ export function oauthKeycloakEventHandler({
12
12
  config,
13
13
  onSuccess,
14
14
  onError
@@ -45,5 +45,5 @@ interface OAuthConfig {
45
45
  }) => Promise<void> | void;
46
46
  onError?: (event: H3Event, error: H3Error) => Promise<void> | void;
47
47
  }
48
- export declare function linkedinEventHandler({ config, onSuccess, onError }: OAuthConfig): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
48
+ export declare function oauthLinkedInEventHandler({ config, onSuccess, onError }: OAuthConfig): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
49
49
  export {};
@@ -2,7 +2,7 @@ import { eventHandler, createError, getQuery, getRequestURL, sendRedirect } from
2
2
  import { withQuery, parseURL, stringifyParsedURL } from "ufo";
3
3
  import { defu } from "defu";
4
4
  import { useRuntimeConfig } from "#imports";
5
- export function linkedinEventHandler({ config, onSuccess, onError }) {
5
+ export function oauthLinkedInEventHandler({ config, onSuccess, onError }) {
6
6
  return eventHandler(async (event) => {
7
7
  config = defu(config, useRuntimeConfig(event).oauth?.linkedin, {
8
8
  authorizationURL: "https://www.linkedin.com/oauth/v2/authorization",
@@ -59,5 +59,5 @@ interface OAuthConfig {
59
59
  }) => Promise<void> | void;
60
60
  onError?: (event: H3Event, error: H3Error) => Promise<void> | void;
61
61
  }
62
- export declare function microsoftEventHandler({ config, onSuccess, onError }: OAuthConfig): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
62
+ export declare function oauthMicrosoftEventHandler({ config, onSuccess, onError }: OAuthConfig): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
63
63
  export {};
@@ -2,7 +2,7 @@ import { eventHandler, createError, getQuery, getRequestURL, sendRedirect } from
2
2
  import { withQuery, parsePath } from "ufo";
3
3
  import { defu } from "defu";
4
4
  import { useRuntimeConfig } from "#imports";
5
- export function microsoftEventHandler({ config, onSuccess, onError }) {
5
+ export function oauthMicrosoftEventHandler({ config, onSuccess, onError }) {
6
6
  return eventHandler(async (event) => {
7
7
  config = defu(config, useRuntimeConfig(event).oauth?.microsoft, {
8
8
  authorizationParams: {}
@@ -44,4 +44,4 @@ export interface OAuthPaypalConfig {
44
44
  */
45
45
  authorizationParams?: Record<string, string>;
46
46
  }
47
- export declare function paypalEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthPaypalConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
47
+ export declare function oauthPaypalEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthPaypalConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
@@ -2,7 +2,7 @@ import { eventHandler, createError, getQuery, getRequestURL, sendRedirect } from
2
2
  import { withQuery, parsePath } from "ufo";
3
3
  import { defu } from "defu";
4
4
  import { useRuntimeConfig } from "#imports";
5
- export function paypalEventHandler({ config, onSuccess, onError }) {
5
+ export function oauthPaypalEventHandler({ config, onSuccess, onError }) {
6
6
  return eventHandler(async (event) => {
7
7
  config = defu(config, useRuntimeConfig(event).oauth?.paypal, {
8
8
  sandbox: import.meta.dev,
@@ -39,4 +39,4 @@ export interface OAuthSpotifyConfig {
39
39
  */
40
40
  authorizationParams?: Record<string, string>;
41
41
  }
42
- export declare function spotifyEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthSpotifyConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
42
+ export declare function oauthSpotifyEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthSpotifyConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
@@ -2,7 +2,7 @@ import { eventHandler, createError, getQuery, getRequestURL, sendRedirect } from
2
2
  import { withQuery, parsePath } from "ufo";
3
3
  import { defu } from "defu";
4
4
  import { useRuntimeConfig } from "#imports";
5
- export function spotifyEventHandler({ config, onSuccess, onError }) {
5
+ export function oauthSpotifyEventHandler({ config, onSuccess, onError }) {
6
6
  return eventHandler(async (event) => {
7
7
  config = defu(config, useRuntimeConfig(event).oauth?.spotify, {
8
8
  authorizationURL: "https://accounts.spotify.com/authorize",
@@ -12,4 +12,4 @@ export interface OAuthSteamConfig {
12
12
  */
13
13
  authorizationURL?: string;
14
14
  }
15
- export declare function steamEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthSteamConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
15
+ export declare function oauthSteamEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthSteamConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
@@ -2,7 +2,7 @@ import { eventHandler, createError, getQuery, getRequestURL, sendRedirect } from
2
2
  import { withQuery } from "ufo";
3
3
  import { defu } from "defu";
4
4
  import { useRuntimeConfig } from "#imports";
5
- export function steamEventHandler({ config, onSuccess, onError }) {
5
+ export function oauthSteamEventHandler({ config, onSuccess, onError }) {
6
6
  return eventHandler(async (event) => {
7
7
  config = defu(config, useRuntimeConfig(event).oauth?.steam, {
8
8
  authorizationURL: "https://steamcommunity.com/openid/login"
@@ -39,4 +39,4 @@ export interface OAuthTwitchConfig {
39
39
  */
40
40
  authorizationParams?: Record<string, string>;
41
41
  }
42
- export declare function twitchEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthTwitchConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
42
+ export declare function oauthTwitchEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthTwitchConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
@@ -2,7 +2,7 @@ import { eventHandler, createError, getQuery, getRequestURL, sendRedirect } from
2
2
  import { withQuery, parsePath } from "ufo";
3
3
  import { defu } from "defu";
4
4
  import { useRuntimeConfig } from "#imports";
5
- export function twitchEventHandler({ config, onSuccess, onError }) {
5
+ export function oauthTwitchEventHandler({ config, onSuccess, onError }) {
6
6
  return eventHandler(async (event) => {
7
7
  config = defu(config, useRuntimeConfig(event).oauth?.twitch, {
8
8
  authorizationURL: "https://id.twitch.tv/oauth2/authorize",
@@ -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'
@@ -38,4 +43,4 @@ export interface OAuthXConfig {
38
43
  */
39
44
  authorizationParams: Record<string, string>;
40
45
  }
41
- export declare function xEventHandler({ config, onSuccess, onError, }: OAuthConfig<OAuthXConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
46
+ export declare function oauthXEventHandler({ config, onSuccess, onError, }: OAuthConfig<OAuthXConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
@@ -9,7 +9,7 @@ import {
9
9
  import { withQuery, parsePath } from "ufo";
10
10
  import { defu } from "defu";
11
11
  import { useRuntimeConfig } from "#imports";
12
- export function xEventHandler({
12
+ export function oauthXEventHandler({
13
13
  config,
14
14
  onSuccess,
15
15
  onError
@@ -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
@@ -23,4 +23,4 @@ export interface OAuthXSUAAConfig {
23
23
  */
24
24
  scope?: string[];
25
25
  }
26
- export declare function xsuaaEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthXSUAAConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
26
+ export declare function oauthXSUAAEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthXSUAAConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
@@ -2,7 +2,7 @@ import { eventHandler, createError, getQuery, getRequestURL, sendRedirect } from
2
2
  import { withQuery, parsePath } from "ufo";
3
3
  import { defu } from "defu";
4
4
  import { useRuntimeConfig } from "#imports";
5
- export function xsuaaEventHandler({ config, onSuccess, onError }) {
5
+ export function oauthXSUAAEventHandler({ config, onSuccess, onError }) {
6
6
  return eventHandler(async (event) => {
7
7
  config = defu(config, useRuntimeConfig(event).oauth?.xsuaa);
8
8
  const { code } = getQuery(event);
@@ -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 oauthYandexEventHandler({ 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 oauthYandexEventHandler({
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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-auth-utils",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
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",
@@ -1,34 +0,0 @@
1
- import { githubEventHandler } from '../lib/oauth/github.js';
2
- import { googleEventHandler } from '../lib/oauth/google.js';
3
- import { spotifyEventHandler } from '../lib/oauth/spotify.js';
4
- import { twitchEventHandler } from '../lib/oauth/twitch.js';
5
- import { auth0EventHandler } from '../lib/oauth/auth0.js';
6
- import { microsoftEventHandler } from '../lib/oauth/microsoft.js';
7
- import { discordEventHandler } from '../lib/oauth/discord.js';
8
- import { battledotnetEventHandler } from '../lib/oauth/battledotnet.js';
9
- import { keycloakEventHandler } from '../lib/oauth/keycloak.js';
10
- import { linkedinEventHandler } from '../lib/oauth/linkedin.js';
11
- import { cognitoEventHandler } from '../lib/oauth/cognito.js';
12
- import { facebookEventHandler } from '../lib/oauth/facebook.js';
13
- import { paypalEventHandler } from '../lib/oauth/paypal.js';
14
- import { steamEventHandler } from '../lib/oauth/steam.js';
15
- import { xEventHandler } from '../lib/oauth/x.js';
16
- import { xsuaaEventHandler } from '../lib/oauth/xsuaa.js';
17
- export declare const oauth: {
18
- githubEventHandler: typeof githubEventHandler;
19
- spotifyEventHandler: typeof spotifyEventHandler;
20
- googleEventHandler: typeof googleEventHandler;
21
- twitchEventHandler: typeof twitchEventHandler;
22
- auth0EventHandler: typeof auth0EventHandler;
23
- microsoftEventHandler: typeof microsoftEventHandler;
24
- discordEventHandler: typeof discordEventHandler;
25
- battledotnetEventHandler: typeof battledotnetEventHandler;
26
- keycloakEventHandler: typeof keycloakEventHandler;
27
- linkedinEventHandler: typeof linkedinEventHandler;
28
- cognitoEventHandler: typeof cognitoEventHandler;
29
- facebookEventHandler: typeof facebookEventHandler;
30
- paypalEventHandler: typeof paypalEventHandler;
31
- steamEventHandler: typeof steamEventHandler;
32
- xEventHandler: typeof xEventHandler;
33
- xsuaaEventHandler: typeof xsuaaEventHandler;
34
- };
@@ -1,34 +0,0 @@
1
- import { githubEventHandler } from "../lib/oauth/github.js";
2
- import { googleEventHandler } from "../lib/oauth/google.js";
3
- import { spotifyEventHandler } from "../lib/oauth/spotify.js";
4
- import { twitchEventHandler } from "../lib/oauth/twitch.js";
5
- import { auth0EventHandler } from "../lib/oauth/auth0.js";
6
- import { microsoftEventHandler } from "../lib/oauth/microsoft.js";
7
- import { discordEventHandler } from "../lib/oauth/discord.js";
8
- import { battledotnetEventHandler } from "../lib/oauth/battledotnet.js";
9
- import { keycloakEventHandler } from "../lib/oauth/keycloak.js";
10
- import { linkedinEventHandler } from "../lib/oauth/linkedin.js";
11
- import { cognitoEventHandler } from "../lib/oauth/cognito.js";
12
- import { facebookEventHandler } from "../lib/oauth/facebook.js";
13
- import { paypalEventHandler } from "../lib/oauth/paypal.js";
14
- import { steamEventHandler } from "../lib/oauth/steam.js";
15
- import { xEventHandler } from "../lib/oauth/x.js";
16
- import { xsuaaEventHandler } from "../lib/oauth/xsuaa.js";
17
- export const oauth = {
18
- githubEventHandler,
19
- spotifyEventHandler,
20
- googleEventHandler,
21
- twitchEventHandler,
22
- auth0EventHandler,
23
- microsoftEventHandler,
24
- discordEventHandler,
25
- battledotnetEventHandler,
26
- keycloakEventHandler,
27
- linkedinEventHandler,
28
- cognitoEventHandler,
29
- facebookEventHandler,
30
- paypalEventHandler,
31
- steamEventHandler,
32
- xEventHandler,
33
- xsuaaEventHandler
34
- };