nuxt-auth-utils 0.0.4 → 0.0.5
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 +13 -3
- package/dist/module.json +2 -2
- package/dist/module.mjs +17 -6
- package/dist/runtime/server/lib/oauth/auth0.d.ts +45 -0
- package/dist/runtime/server/lib/oauth/auth0.mjs +78 -0
- package/dist/runtime/server/lib/oauth/google.d.ts +45 -0
- package/dist/runtime/server/lib/oauth/google.mjs +82 -0
- package/dist/runtime/server/lib/oauth/twitch.d.ts +45 -0
- package/dist/runtime/server/lib/oauth/twitch.mjs +89 -0
- package/dist/runtime/server/utils/oauth.d.ts +6 -0
- package/dist/runtime/server/utils/oauth.mjs +7 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -7,14 +7,15 @@
|
|
|
7
7
|
|
|
8
8
|
Minimalist Authentication module for Nuxt exposing Vue composables and server utils.
|
|
9
9
|
|
|
10
|
-
- [
|
|
10
|
+
- [Release Notes](/CHANGELOG.md)
|
|
11
|
+
- [Demo](https://github.com/atinux/nuxt-todos-edge)
|
|
11
12
|
<!-- - [🏀 Online playground](https://stackblitz.com/github/your-org/nuxt-auth-utils?file=playground%2Fapp.vue) -->
|
|
12
13
|
<!-- - [📖 Documentation](https://example.com) -->
|
|
13
14
|
|
|
14
15
|
## Features
|
|
15
16
|
|
|
16
17
|
- Secured & sealed cookies sessions
|
|
17
|
-
- OAuth Providers
|
|
18
|
+
- [OAuth Providers](#supported-oauth-providers)
|
|
18
19
|
|
|
19
20
|
## Requirements
|
|
20
21
|
|
|
@@ -144,9 +145,15 @@ It can also be set using environment variables:
|
|
|
144
145
|
- `NUXT_OAUTH_<PROVIDER>_CLIENT_ID`
|
|
145
146
|
- `NUXT_OAUTH_<PROVIDER>_CLIENT_SECRET`
|
|
146
147
|
|
|
147
|
-
Supported
|
|
148
|
+
#### Supported OAuth Providers
|
|
149
|
+
|
|
148
150
|
- GitHub
|
|
149
151
|
- Spotify
|
|
152
|
+
- Google
|
|
153
|
+
- Twitch
|
|
154
|
+
- Auth0
|
|
155
|
+
|
|
156
|
+
You can add your favorite provider by creating a new file in [src/runtime/server/lib/oauth/](./src/runtime/server/lib/oauth/).
|
|
150
157
|
|
|
151
158
|
### Example
|
|
152
159
|
|
|
@@ -154,6 +161,9 @@ Example: `~/server/routes/auth/github.get.ts`
|
|
|
154
161
|
|
|
155
162
|
```ts
|
|
156
163
|
export default oauth.githubEventHandler({
|
|
164
|
+
config: {
|
|
165
|
+
emailRequired: true
|
|
166
|
+
},
|
|
157
167
|
async onSuccess(event, { user, tokens }) {
|
|
158
168
|
await setUserSession(event, {
|
|
159
169
|
user: {
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -4,20 +4,18 @@ import { defu } from 'defu';
|
|
|
4
4
|
|
|
5
5
|
const module = defineNuxtModule({
|
|
6
6
|
meta: {
|
|
7
|
-
name: "auth-
|
|
7
|
+
name: "auth-utils",
|
|
8
8
|
configKey: "auth"
|
|
9
9
|
},
|
|
10
10
|
// Default configuration options of the Nuxt module
|
|
11
11
|
defaults: {},
|
|
12
12
|
setup(options, nuxt) {
|
|
13
13
|
const resolver = createResolver(import.meta.url);
|
|
14
|
-
if (!process.env.NUXT_SESSION_PASSWORD) {
|
|
14
|
+
if (!process.env.NUXT_SESSION_PASSWORD && !nuxt.options._prepare) {
|
|
15
15
|
const randomPassword = sha256(`${Date.now()}${Math.random()}`).slice(0, 32);
|
|
16
16
|
process.env.NUXT_SESSION_PASSWORD = randomPassword;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
console.log(`NUXT_SESSION_PASSWORD=${randomPassword}`);
|
|
20
|
-
}
|
|
17
|
+
console.warn("No session password set, using a random password, please set NUXT_SESSION_PASSWORD in your .env file with at least 32 chars");
|
|
18
|
+
console.log(`NUXT_SESSION_PASSWORD=${randomPassword}`);
|
|
21
19
|
}
|
|
22
20
|
nuxt.options.alias["#auth-utils"] = resolver.resolve("./runtime/types/auth-utils-session");
|
|
23
21
|
addImportsDir(resolver.resolve("./runtime/composables"));
|
|
@@ -65,6 +63,19 @@ const module = defineNuxtModule({
|
|
|
65
63
|
clientId: "",
|
|
66
64
|
clientSecret: ""
|
|
67
65
|
});
|
|
66
|
+
runtimeConfig.oauth.google = defu(runtimeConfig.oauth.google, {
|
|
67
|
+
clientId: "",
|
|
68
|
+
clientSecret: ""
|
|
69
|
+
});
|
|
70
|
+
runtimeConfig.oauth.twitch = defu(runtimeConfig.oauth.twitch, {
|
|
71
|
+
clientId: "",
|
|
72
|
+
clientSecret: ""
|
|
73
|
+
});
|
|
74
|
+
runtimeConfig.oauth.auth0 = defu(runtimeConfig.oauth.auth0, {
|
|
75
|
+
clientId: "",
|
|
76
|
+
clientSecret: "",
|
|
77
|
+
domain: ""
|
|
78
|
+
});
|
|
68
79
|
}
|
|
69
80
|
});
|
|
70
81
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { H3Event, H3Error } from 'h3';
|
|
2
|
+
export interface OAuthAuth0Config {
|
|
3
|
+
/**
|
|
4
|
+
* Auth0 OAuth Client ID
|
|
5
|
+
* @default process.env.NUXT_OAUTH_AUTH0_CLIENT_ID
|
|
6
|
+
*/
|
|
7
|
+
clientId?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Auth0 OAuth Client Secret
|
|
10
|
+
* @default process.env.NUXT_OAUTH_AUTH0_CLIENT_SECRET
|
|
11
|
+
*/
|
|
12
|
+
clientSecret?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Auth0 OAuth Issuer
|
|
15
|
+
* @default process.env.NUXT_OAUTH_AUTH0_DOMAIN
|
|
16
|
+
*/
|
|
17
|
+
domain?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Auth0 OAuth Audience
|
|
20
|
+
* @default process.env.NUXT_OAUTH_AUTH0_AUDIENCE
|
|
21
|
+
*/
|
|
22
|
+
audience?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Auth0 OAuth Scope
|
|
25
|
+
* @default []
|
|
26
|
+
* @see https://auth0.com/docs/get-started/apis/scopes/openid-connect-scopes
|
|
27
|
+
* @example ['openid']
|
|
28
|
+
*/
|
|
29
|
+
scope?: string[];
|
|
30
|
+
/**
|
|
31
|
+
* Require email from user, adds the ['email'] scope if not present
|
|
32
|
+
* @default false
|
|
33
|
+
*/
|
|
34
|
+
emailRequired?: boolean;
|
|
35
|
+
}
|
|
36
|
+
interface OAuthConfig {
|
|
37
|
+
config?: OAuthAuth0Config;
|
|
38
|
+
onSuccess: (event: H3Event, result: {
|
|
39
|
+
user: any;
|
|
40
|
+
tokens: any;
|
|
41
|
+
}) => Promise<void> | void;
|
|
42
|
+
onError?: (event: H3Event, error: H3Error) => Promise<void> | void;
|
|
43
|
+
}
|
|
44
|
+
export declare function auth0EventHandler({ config, onSuccess, onError }: OAuthConfig): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { eventHandler, createError, getQuery, getRequestURL, sendRedirect } from "h3";
|
|
2
|
+
import { withQuery, parsePath } from "ufo";
|
|
3
|
+
import { ofetch } from "ofetch";
|
|
4
|
+
import { defu } from "defu";
|
|
5
|
+
import { useRuntimeConfig } from "#imports";
|
|
6
|
+
export function auth0EventHandler({ config, onSuccess, onError }) {
|
|
7
|
+
return eventHandler(async (event) => {
|
|
8
|
+
config = defu(config, useRuntimeConfig(event).oauth?.auth0);
|
|
9
|
+
const { code } = getQuery(event);
|
|
10
|
+
if (!config.clientId || !config.clientSecret || !config.domain) {
|
|
11
|
+
const error = createError({
|
|
12
|
+
statusCode: 500,
|
|
13
|
+
message: "Missing NUXT_OAUTH_AUTH0_CLIENT_ID or NUXT_OAUTH_AUTH0_CLIENT_SECRET or NUXT_OAUTH_AUTH0_DOMAIN env variables."
|
|
14
|
+
});
|
|
15
|
+
if (!onError)
|
|
16
|
+
throw error;
|
|
17
|
+
return onError(event, error);
|
|
18
|
+
}
|
|
19
|
+
const authorizationURL = `https://${config.domain}/authorize`;
|
|
20
|
+
const tokenURL = `https://${config.domain}/oauth/token`;
|
|
21
|
+
const redirectUrl = getRequestURL(event).href;
|
|
22
|
+
if (!code) {
|
|
23
|
+
config.scope = config.scope || ["openid", "offline_access"];
|
|
24
|
+
if (config.emailRequired && !config.scope.includes("email")) {
|
|
25
|
+
config.scope.push("email");
|
|
26
|
+
}
|
|
27
|
+
return sendRedirect(
|
|
28
|
+
event,
|
|
29
|
+
withQuery(authorizationURL, {
|
|
30
|
+
response_type: "code",
|
|
31
|
+
client_id: config.clientId,
|
|
32
|
+
redirect_uri: redirectUrl,
|
|
33
|
+
scope: config.scope.join(" "),
|
|
34
|
+
audience: config.audience || ""
|
|
35
|
+
})
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
const tokens = await ofetch(
|
|
39
|
+
tokenURL,
|
|
40
|
+
{
|
|
41
|
+
method: "POST",
|
|
42
|
+
headers: {
|
|
43
|
+
"Content-Type": "application/json"
|
|
44
|
+
},
|
|
45
|
+
body: {
|
|
46
|
+
grant_type: "authorization_code",
|
|
47
|
+
client_id: config.clientId,
|
|
48
|
+
client_secret: config.clientSecret,
|
|
49
|
+
redirect_uri: parsePath(redirectUrl).pathname,
|
|
50
|
+
code
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
).catch((error) => {
|
|
54
|
+
return { error };
|
|
55
|
+
});
|
|
56
|
+
if (tokens.error) {
|
|
57
|
+
const error = createError({
|
|
58
|
+
statusCode: 401,
|
|
59
|
+
message: `Auth0 login failed: ${tokens.error?.data?.error_description || "Unknown error"}`,
|
|
60
|
+
data: tokens
|
|
61
|
+
});
|
|
62
|
+
if (!onError)
|
|
63
|
+
throw error;
|
|
64
|
+
return onError(event, error);
|
|
65
|
+
}
|
|
66
|
+
const tokenType = tokens.token_type;
|
|
67
|
+
const accessToken = tokens.access_token;
|
|
68
|
+
const user = await ofetch(`https://${config.domain}/userinfo`, {
|
|
69
|
+
headers: {
|
|
70
|
+
Authorization: `${tokenType} ${accessToken}`
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
return onSuccess(event, {
|
|
74
|
+
tokens,
|
|
75
|
+
user
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { H3Event, H3Error } from 'h3';
|
|
2
|
+
export interface OAuthGoogleConfig {
|
|
3
|
+
/**
|
|
4
|
+
* Google OAuth Client ID
|
|
5
|
+
* @default process.env.NUXT_OAUTH_GOOGLE_CLIENT_ID
|
|
6
|
+
*/
|
|
7
|
+
clientId?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Google OAuth Client Secret
|
|
10
|
+
* @default process.env.NUXT_OAUTH_GOOGLE_CLIENT_SECRET
|
|
11
|
+
*/
|
|
12
|
+
clientSecret?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Google OAuth Scope
|
|
15
|
+
* @default []
|
|
16
|
+
* @see https://developers.google.com/identity/protocols/oauth2/scopes#google-sign-in
|
|
17
|
+
* @example ['email', 'openid', 'profile']
|
|
18
|
+
*/
|
|
19
|
+
scope?: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Google OAuth Authorization URL
|
|
22
|
+
* @default 'https://accounts.google.com/o/oauth2/v2/auth'
|
|
23
|
+
*/
|
|
24
|
+
authorizationURL?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Google OAuth Token URL
|
|
27
|
+
* @default 'https://oauth2.googleapis.com/token'
|
|
28
|
+
*/
|
|
29
|
+
tokenURL?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Redirect URL post authenticating via google
|
|
32
|
+
* @default '/auth/google'
|
|
33
|
+
*/
|
|
34
|
+
redirectUrl: '/auth/google';
|
|
35
|
+
}
|
|
36
|
+
interface OAuthConfig {
|
|
37
|
+
config?: OAuthGoogleConfig;
|
|
38
|
+
onSuccess: (event: H3Event, result: {
|
|
39
|
+
user: any;
|
|
40
|
+
tokens: any;
|
|
41
|
+
}) => Promise<void> | void;
|
|
42
|
+
onError?: (event: H3Event, error: H3Error) => Promise<void> | void;
|
|
43
|
+
}
|
|
44
|
+
export declare function googleEventHandler({ config, onSuccess, onError, }: OAuthConfig): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import {
|
|
2
|
+
eventHandler,
|
|
3
|
+
createError,
|
|
4
|
+
getQuery,
|
|
5
|
+
getRequestURL,
|
|
6
|
+
sendRedirect
|
|
7
|
+
} from "h3";
|
|
8
|
+
import { withQuery, parsePath } from "ufo";
|
|
9
|
+
import { ofetch } from "ofetch";
|
|
10
|
+
import { defu } from "defu";
|
|
11
|
+
import { useRuntimeConfig } from "#imports";
|
|
12
|
+
export function googleEventHandler({
|
|
13
|
+
config,
|
|
14
|
+
onSuccess,
|
|
15
|
+
onError
|
|
16
|
+
}) {
|
|
17
|
+
return eventHandler(async (event) => {
|
|
18
|
+
config = defu(config, useRuntimeConfig(event).oauth?.google, {
|
|
19
|
+
authorizationURL: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
20
|
+
tokenURL: "https://oauth2.googleapis.com/token"
|
|
21
|
+
});
|
|
22
|
+
const { code } = getQuery(event);
|
|
23
|
+
if (!config.clientId) {
|
|
24
|
+
const error = createError({
|
|
25
|
+
statusCode: 500,
|
|
26
|
+
message: "Missing NUXT_OAUTH_GOOGLE_CLIENT_ID 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 || ["email", "profile"];
|
|
35
|
+
return sendRedirect(
|
|
36
|
+
event,
|
|
37
|
+
withQuery(config.authorizationURL, {
|
|
38
|
+
response_type: "code",
|
|
39
|
+
client_id: config.clientId,
|
|
40
|
+
redirect_uri: redirectUrl,
|
|
41
|
+
scope: config.scope.join(" ")
|
|
42
|
+
})
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
const body = {
|
|
46
|
+
grant_type: "authorization_code",
|
|
47
|
+
redirect_uri: parsePath(redirectUrl).pathname,
|
|
48
|
+
client_id: config.clientId,
|
|
49
|
+
client_secret: config.clientSecret,
|
|
50
|
+
code
|
|
51
|
+
};
|
|
52
|
+
const tokens = await ofetch(config.tokenURL, {
|
|
53
|
+
method: "POST",
|
|
54
|
+
body
|
|
55
|
+
}).catch((error) => {
|
|
56
|
+
return { error };
|
|
57
|
+
});
|
|
58
|
+
if (tokens.error) {
|
|
59
|
+
const error = createError({
|
|
60
|
+
statusCode: 401,
|
|
61
|
+
message: `Google login failed: ${tokens.error?.data?.error_description || "Unknown error"}`,
|
|
62
|
+
data: tokens
|
|
63
|
+
});
|
|
64
|
+
if (!onError)
|
|
65
|
+
throw error;
|
|
66
|
+
return onError(event, error);
|
|
67
|
+
}
|
|
68
|
+
const accessToken = tokens.access_token;
|
|
69
|
+
const user = await ofetch(
|
|
70
|
+
"https://www.googleapis.com/oauth2/v3/userinfo",
|
|
71
|
+
{
|
|
72
|
+
headers: {
|
|
73
|
+
Authorization: `Bearer ${accessToken}`
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
return onSuccess(event, {
|
|
78
|
+
tokens,
|
|
79
|
+
user
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { H3Event, H3Error } from 'h3';
|
|
2
|
+
export interface OAuthTwitchConfig {
|
|
3
|
+
/**
|
|
4
|
+
* Twitch Client ID
|
|
5
|
+
* @default process.env.NUXT_OAUTH_TWITCH_CLIENT_ID
|
|
6
|
+
*/
|
|
7
|
+
clientId?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Twitch OAuth Client Secret
|
|
10
|
+
* @default process.env.NUXT_OAUTH_TWITCH_CLIENT_SECRET
|
|
11
|
+
*/
|
|
12
|
+
clientSecret?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Twitch OAuth Scope
|
|
15
|
+
* @default []
|
|
16
|
+
* @see https://dev.twitch.tv/docs/authentication/scopes
|
|
17
|
+
* @example ['user:read:email']
|
|
18
|
+
*/
|
|
19
|
+
scope?: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Require email from user, adds the ['user:read:email'] scope if not present
|
|
22
|
+
* @default false
|
|
23
|
+
*/
|
|
24
|
+
emailRequired?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Twitch OAuth Authorization URL
|
|
27
|
+
* @default 'https://id.twitch.tv/oauth2/authorize'
|
|
28
|
+
*/
|
|
29
|
+
authorizationURL?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Twitch OAuth Token URL
|
|
32
|
+
* @default 'https://id.twitch.tv/oauth2/token'
|
|
33
|
+
*/
|
|
34
|
+
tokenURL?: string;
|
|
35
|
+
}
|
|
36
|
+
interface OAuthConfig {
|
|
37
|
+
config?: OAuthTwitchConfig;
|
|
38
|
+
onSuccess: (event: H3Event, result: {
|
|
39
|
+
user: any;
|
|
40
|
+
tokens: any;
|
|
41
|
+
}) => Promise<void> | void;
|
|
42
|
+
onError?: (event: H3Event, error: H3Error) => Promise<void> | void;
|
|
43
|
+
}
|
|
44
|
+
export declare function twitchEventHandler({ config, onSuccess, onError }: OAuthConfig): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { eventHandler, createError, getQuery, getRequestURL, sendRedirect } from "h3";
|
|
2
|
+
import { withQuery, parsePath } from "ufo";
|
|
3
|
+
import { ofetch } from "ofetch";
|
|
4
|
+
import { defu } from "defu";
|
|
5
|
+
import { useRuntimeConfig } from "#imports";
|
|
6
|
+
export function twitchEventHandler({ config, onSuccess, onError }) {
|
|
7
|
+
return eventHandler(async (event) => {
|
|
8
|
+
config = defu(config, useRuntimeConfig(event).oauth?.twitch, {
|
|
9
|
+
authorizationURL: "https://id.twitch.tv/oauth2/authorize",
|
|
10
|
+
tokenURL: "https://id.twitch.tv/oauth2/token"
|
|
11
|
+
});
|
|
12
|
+
const { code } = getQuery(event);
|
|
13
|
+
if (!config.clientId) {
|
|
14
|
+
const error = createError({
|
|
15
|
+
statusCode: 500,
|
|
16
|
+
message: "Missing NUXT_OAUTH_TWITCH_CLIENT_ID env variables."
|
|
17
|
+
});
|
|
18
|
+
if (!onError)
|
|
19
|
+
throw error;
|
|
20
|
+
return onError(event, error);
|
|
21
|
+
}
|
|
22
|
+
const redirectUrl = getRequestURL(event).href;
|
|
23
|
+
if (!code) {
|
|
24
|
+
config.scope = config.scope || [];
|
|
25
|
+
if (config.emailRequired && !config.scope.includes("user:read:email")) {
|
|
26
|
+
config.scope.push("user:read:email");
|
|
27
|
+
}
|
|
28
|
+
return sendRedirect(
|
|
29
|
+
event,
|
|
30
|
+
withQuery(config.authorizationURL, {
|
|
31
|
+
response_type: "code",
|
|
32
|
+
client_id: config.clientId,
|
|
33
|
+
redirect_uri: redirectUrl,
|
|
34
|
+
scope: config.scope.join("%20")
|
|
35
|
+
})
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
const tokens = await ofetch(
|
|
39
|
+
config.tokenURL,
|
|
40
|
+
{
|
|
41
|
+
method: "POST",
|
|
42
|
+
headers: {
|
|
43
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
44
|
+
},
|
|
45
|
+
params: {
|
|
46
|
+
grant_type: "authorization_code",
|
|
47
|
+
redirect_uri: parsePath(redirectUrl).pathname,
|
|
48
|
+
client_id: config.clientId,
|
|
49
|
+
client_secret: config.clientSecret,
|
|
50
|
+
code
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
).catch((error) => {
|
|
54
|
+
return { error };
|
|
55
|
+
});
|
|
56
|
+
if (tokens.error) {
|
|
57
|
+
const error = createError({
|
|
58
|
+
statusCode: 401,
|
|
59
|
+
message: `Twitch login failed: ${tokens.error?.data?.error_description || "Unknown error"}`,
|
|
60
|
+
data: tokens
|
|
61
|
+
});
|
|
62
|
+
if (!onError)
|
|
63
|
+
throw error;
|
|
64
|
+
return onError(event, error);
|
|
65
|
+
}
|
|
66
|
+
const accessToken = tokens.access_token;
|
|
67
|
+
const users = await ofetch("https://api.twitch.tv/helix/users", {
|
|
68
|
+
headers: {
|
|
69
|
+
"Client-ID": config.clientId,
|
|
70
|
+
Authorization: `Bearer ${accessToken}`
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
const user = users.data?.[0];
|
|
74
|
+
if (!user) {
|
|
75
|
+
const error = createError({
|
|
76
|
+
statusCode: 500,
|
|
77
|
+
message: "Could not get Twitch user",
|
|
78
|
+
data: tokens
|
|
79
|
+
});
|
|
80
|
+
if (!onError)
|
|
81
|
+
throw error;
|
|
82
|
+
return onError(event, error);
|
|
83
|
+
}
|
|
84
|
+
return onSuccess(event, {
|
|
85
|
+
tokens,
|
|
86
|
+
user
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { githubEventHandler } from '../lib/oauth/github';
|
|
2
|
+
import { googleEventHandler } from '../lib/oauth/google';
|
|
2
3
|
import { spotifyEventHandler } from '../lib/oauth/spotify';
|
|
4
|
+
import { twitchEventHandler } from '../lib/oauth/twitch';
|
|
5
|
+
import { auth0EventHandler } from '../lib/oauth/auth0';
|
|
3
6
|
export declare const oauth: {
|
|
4
7
|
githubEventHandler: typeof githubEventHandler;
|
|
5
8
|
spotifyEventHandler: typeof spotifyEventHandler;
|
|
9
|
+
googleEventHandler: typeof googleEventHandler;
|
|
10
|
+
twitchEventHandler: typeof twitchEventHandler;
|
|
11
|
+
auth0EventHandler: typeof auth0EventHandler;
|
|
6
12
|
};
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { githubEventHandler } from "../lib/oauth/github.mjs";
|
|
2
|
+
import { googleEventHandler } from "../lib/oauth/google.mjs";
|
|
2
3
|
import { spotifyEventHandler } from "../lib/oauth/spotify.mjs";
|
|
4
|
+
import { twitchEventHandler } from "../lib/oauth/twitch.mjs";
|
|
5
|
+
import { auth0EventHandler } from "../lib/oauth/auth0.mjs";
|
|
3
6
|
export const oauth = {
|
|
4
7
|
githubEventHandler,
|
|
5
|
-
spotifyEventHandler
|
|
8
|
+
spotifyEventHandler,
|
|
9
|
+
googleEventHandler,
|
|
10
|
+
twitchEventHandler,
|
|
11
|
+
auth0EventHandler
|
|
6
12
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-auth-utils",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "Minimalist Auth module for Nuxt with SSR",
|
|
5
5
|
"repository": "Atinux/nuxt-auth-utils",
|
|
6
6
|
"license": "MIT",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@nuxt/kit": "^3.8.1",
|
|
34
34
|
"defu": "^6.1.3",
|
|
35
|
+
"ofetch": "^1.3.3",
|
|
35
36
|
"ohash": "^1.1.3"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|