nuxt-auth-utils 0.5.5 → 0.5.6
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 +2 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +5 -0
- package/dist/runtime/server/lib/oauth/instagram.d.ts +6 -6
- package/dist/runtime/server/lib/oauth/instagram.js +10 -6
- package/dist/runtime/server/lib/oauth/seznam.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/seznam.js +2 -2
- package/dist/runtime/server/lib/oauth/strava.d.ts +116 -0
- package/dist/runtime/server/lib/oauth/strava.js +73 -0
- package/dist/runtime/server/lib/oauth/workos.d.ts +9 -4
- package/dist/runtime/server/lib/oauth/workos.js +6 -7
- package/dist/runtime/server/lib/oauth/zitadel.js +0 -1
- package/dist/runtime/types/oauth-config.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -224,6 +224,7 @@ It can also be set using environment variables:
|
|
|
224
224
|
- Seznam
|
|
225
225
|
- Spotify
|
|
226
226
|
- Steam
|
|
227
|
+
- Strava
|
|
227
228
|
- TikTok
|
|
228
229
|
- Twitch
|
|
229
230
|
- VK
|
|
@@ -231,6 +232,7 @@ It can also be set using environment variables:
|
|
|
231
232
|
- X (Twitter)
|
|
232
233
|
- XSUAA
|
|
233
234
|
- Yandex
|
|
235
|
+
- Zitadel
|
|
234
236
|
|
|
235
237
|
You can add your favorite provider by creating a new file in [src/runtime/server/lib/oauth/](./src/runtime/server/lib/oauth/).
|
|
236
238
|
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -12,21 +12,21 @@ export interface OAuthInstagramConfig {
|
|
|
12
12
|
clientSecret?: string;
|
|
13
13
|
/**
|
|
14
14
|
* Instagram OAuth Scope
|
|
15
|
-
* @
|
|
15
|
+
* @required [ 'business_basic' ]
|
|
16
16
|
* @see https://developers.facebook.com/docs/instagram-basic-display-api/overview#permissions
|
|
17
|
-
* @example [ '
|
|
17
|
+
* @example [ 'business_basic', 'business_manage_messages' ],
|
|
18
18
|
*/
|
|
19
|
-
scope?:
|
|
19
|
+
scope?: ('business_basic' | 'business_content_publish' | 'business_manage_comments' | 'business_manage_messages')[];
|
|
20
20
|
/**
|
|
21
21
|
* Instagram OAuth User Fields
|
|
22
22
|
* @default [ 'id', 'username'],
|
|
23
23
|
* @see https://developers.facebook.com/docs/instagram-basic-display-api/reference/user#fields
|
|
24
|
-
* @example [ 'id', 'username', 'account_type', '
|
|
24
|
+
* @example [ 'id', 'username', 'user_id', 'account_type', 'profile_picture_url' ],
|
|
25
25
|
*/
|
|
26
|
-
fields?:
|
|
26
|
+
fields?: ('id' | 'user_id' | 'username' | 'name' | 'account_type' | 'profile_picture_url' | 'followers_count' | 'follows_count' | 'media_count')[];
|
|
27
27
|
/**
|
|
28
28
|
* Instagram OAuth Authorization URL
|
|
29
|
-
* @default 'https://
|
|
29
|
+
* @default 'https://www.instagram.com/oauth/authorize'
|
|
30
30
|
*/
|
|
31
31
|
authorizationURL?: string;
|
|
32
32
|
/**
|
|
@@ -10,8 +10,8 @@ export function defineOAuthInstagramEventHandler({
|
|
|
10
10
|
}) {
|
|
11
11
|
return eventHandler(async (event) => {
|
|
12
12
|
config = defu(config, useRuntimeConfig(event).oauth?.instagram, {
|
|
13
|
-
scope: ["
|
|
14
|
-
authorizationURL: "https://
|
|
13
|
+
scope: ["business_basic"],
|
|
14
|
+
authorizationURL: "https://www.instagram.com/oauth/authorize",
|
|
15
15
|
tokenURL: "https://api.instagram.com/oauth/access_token",
|
|
16
16
|
authorizationParams: {}
|
|
17
17
|
});
|
|
@@ -20,7 +20,11 @@ export function defineOAuthInstagramEventHandler({
|
|
|
20
20
|
const error = createError({
|
|
21
21
|
statusCode: 401,
|
|
22
22
|
message: `Instagram login failed: ${query.error || "Unknown error"}`,
|
|
23
|
-
data:
|
|
23
|
+
data: {
|
|
24
|
+
error: query.error,
|
|
25
|
+
error_reason: query.error_reason,
|
|
26
|
+
error_description: query.error_description
|
|
27
|
+
}
|
|
24
28
|
});
|
|
25
29
|
if (!onError) throw error;
|
|
26
30
|
return onError(event, error);
|
|
@@ -36,7 +40,7 @@ export function defineOAuthInstagramEventHandler({
|
|
|
36
40
|
withQuery(config.authorizationURL, {
|
|
37
41
|
client_id: config.clientId,
|
|
38
42
|
redirect_uri: redirectURL,
|
|
39
|
-
scope: config.scope.join(
|
|
43
|
+
scope: config.scope.join(),
|
|
40
44
|
response_type: "code"
|
|
41
45
|
})
|
|
42
46
|
);
|
|
@@ -55,9 +59,9 @@ export function defineOAuthInstagramEventHandler({
|
|
|
55
59
|
}
|
|
56
60
|
const accessToken = tokens.access_token;
|
|
57
61
|
config.fields = config.fields || ["id", "username"];
|
|
58
|
-
const fields = config.fields.join(
|
|
62
|
+
const fields = config.fields.join();
|
|
59
63
|
const user = await $fetch(
|
|
60
|
-
`https://graph.instagram.com/
|
|
64
|
+
`https://graph.instagram.com/v21.0/me?fields=${fields}&access_token=${accessToken}`
|
|
61
65
|
);
|
|
62
66
|
if (!user) {
|
|
63
67
|
throw new Error("Instagram login failed: no user found");
|
|
@@ -92,4 +92,4 @@ export interface OAuthSeznamUser {
|
|
|
92
92
|
*/
|
|
93
93
|
gender?: string | null;
|
|
94
94
|
}
|
|
95
|
-
export declare function
|
|
95
|
+
export declare function defineOAuthSeznamEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthSeznamConfig, OAuthSeznamUser>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
|
|
@@ -3,9 +3,9 @@ import { eventHandler, getQuery, sendRedirect } from "h3";
|
|
|
3
3
|
import { withQuery } from "ufo";
|
|
4
4
|
import { getOAuthRedirectURL, handleAccessTokenErrorResponse, handleMissingConfiguration, requestAccessToken } from "../utils.js";
|
|
5
5
|
import { useRuntimeConfig } from "#imports";
|
|
6
|
-
export function
|
|
6
|
+
export function defineOAuthSeznamEventHandler({ config, onSuccess, onError }) {
|
|
7
7
|
return eventHandler(async (event) => {
|
|
8
|
-
config = defu(config, useRuntimeConfig(event).oauth?.
|
|
8
|
+
config = defu(config, useRuntimeConfig(event).oauth?.seznam, {
|
|
9
9
|
authorizationURL: "https://login.szn.cz/api/v1/oauth/auth",
|
|
10
10
|
tokenURL: "https://login.szn.cz/api/v1/oauth/token",
|
|
11
11
|
userURL: "https://login.szn.cz/api/v1/user"
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { OAuthConfig } from '#auth-utils';
|
|
2
|
+
export interface OAuthStravaConfig {
|
|
3
|
+
/**
|
|
4
|
+
* Strava OAuth Client ID
|
|
5
|
+
* @default process.env.NUXT_OAUTH_STRAVA_CLIENT_ID
|
|
6
|
+
*/
|
|
7
|
+
clientId?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Strava OAuth Client Secret
|
|
10
|
+
* @default process.env.NUXT_OAUTH_STRAVA_CLIENT_SECRET
|
|
11
|
+
*/
|
|
12
|
+
clientSecret?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Strava OAuth Scope
|
|
15
|
+
* @default []
|
|
16
|
+
* @see https://developers.strava.com/docs/authentication/ # Details About Requesting Access
|
|
17
|
+
* @example ['read', 'read_all', 'profile:read_all', 'profile:write', 'activity:read', 'activity:read_all', 'activity:write']
|
|
18
|
+
*/
|
|
19
|
+
scope?: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Redirect URL to allow overriding for situations like prod failing to determine public hostname
|
|
22
|
+
* @default process.env.NUXT_OAUTH_STRAVA_REDIRECT_URL or current URL
|
|
23
|
+
*/
|
|
24
|
+
redirectURL?: string;
|
|
25
|
+
/**
|
|
26
|
+
* To show the authorization prompt to the user, 'force' will always show the prompt
|
|
27
|
+
* @default 'auto'
|
|
28
|
+
* @see https://developers.strava.com/docs/authentication/ # Details About Requesting Access
|
|
29
|
+
*/
|
|
30
|
+
approvalPrompt?: 'auto' | 'force';
|
|
31
|
+
}
|
|
32
|
+
export interface OAuthStravaUser {
|
|
33
|
+
/**
|
|
34
|
+
* The unique identifier of the athlete
|
|
35
|
+
*/
|
|
36
|
+
id: number;
|
|
37
|
+
/**
|
|
38
|
+
* The username of the athlete
|
|
39
|
+
*/
|
|
40
|
+
username: string;
|
|
41
|
+
/**
|
|
42
|
+
* Resource state, indicates level of detail.
|
|
43
|
+
* - Meta (1): Basic information
|
|
44
|
+
* - Summary (2): Summary information
|
|
45
|
+
* - Detail (3): Detailed information
|
|
46
|
+
* @see https://developers.strava.com/docs/reference/#api-models-DetailedAthlete
|
|
47
|
+
*/
|
|
48
|
+
resource_state: 1 | 2 | 3;
|
|
49
|
+
/**
|
|
50
|
+
* The athlete's first name
|
|
51
|
+
*/
|
|
52
|
+
firstname: string;
|
|
53
|
+
/**
|
|
54
|
+
* The athlete's last name
|
|
55
|
+
*/
|
|
56
|
+
lastname: string;
|
|
57
|
+
/**
|
|
58
|
+
* The athlete's bio
|
|
59
|
+
*/
|
|
60
|
+
bio: string;
|
|
61
|
+
/**
|
|
62
|
+
* The athlete's city
|
|
63
|
+
*/
|
|
64
|
+
city: string;
|
|
65
|
+
/**
|
|
66
|
+
* The athlete's state or geographical region
|
|
67
|
+
*/
|
|
68
|
+
state: string;
|
|
69
|
+
/**
|
|
70
|
+
* The athlete's country
|
|
71
|
+
*/
|
|
72
|
+
country: string;
|
|
73
|
+
/**
|
|
74
|
+
* The athlete's sex
|
|
75
|
+
*/
|
|
76
|
+
sex: string;
|
|
77
|
+
/**
|
|
78
|
+
* Whether the athlete has any Summit subscription
|
|
79
|
+
* @see https://developers.strava.com/docs/reference/#api-models-DetailedAthlete
|
|
80
|
+
*/
|
|
81
|
+
summit: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* The time at which the athlete was created
|
|
84
|
+
*/
|
|
85
|
+
created_at: Date;
|
|
86
|
+
/**
|
|
87
|
+
* The time at which the athlete was last updated
|
|
88
|
+
*/
|
|
89
|
+
updated_at: Date;
|
|
90
|
+
/**
|
|
91
|
+
* The athlete's weight
|
|
92
|
+
*/
|
|
93
|
+
weight: number;
|
|
94
|
+
/**
|
|
95
|
+
* URL to a 124x124 pixel profile picture
|
|
96
|
+
*/
|
|
97
|
+
profile_medium: string;
|
|
98
|
+
/**
|
|
99
|
+
* URL to a 62x62 pixel profile picture
|
|
100
|
+
*/
|
|
101
|
+
profile: string;
|
|
102
|
+
/**
|
|
103
|
+
* The athlete's timezone
|
|
104
|
+
*/
|
|
105
|
+
timezone: string;
|
|
106
|
+
}
|
|
107
|
+
export interface OAuthStravaTokens {
|
|
108
|
+
token_type: 'Bearer';
|
|
109
|
+
expires_at: number;
|
|
110
|
+
expires_in: number;
|
|
111
|
+
access_token: string;
|
|
112
|
+
refresh_token: string;
|
|
113
|
+
athlete: OAuthStravaUser;
|
|
114
|
+
error?: string;
|
|
115
|
+
}
|
|
116
|
+
export declare function defineOAuthStravaEventHandler({ config, onSuccess, onError, }: OAuthConfig<OAuthStravaConfig, OAuthStravaUser>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { eventHandler, getQuery, sendRedirect } from "h3";
|
|
2
|
+
import { withQuery } from "ufo";
|
|
3
|
+
import { defu } from "defu";
|
|
4
|
+
import {
|
|
5
|
+
getOAuthRedirectURL,
|
|
6
|
+
handleAccessTokenErrorResponse,
|
|
7
|
+
handleMissingConfiguration,
|
|
8
|
+
requestAccessToken
|
|
9
|
+
} from "../utils.js";
|
|
10
|
+
import { useRuntimeConfig, createError } from "#imports";
|
|
11
|
+
export function defineOAuthStravaEventHandler({
|
|
12
|
+
config,
|
|
13
|
+
onSuccess,
|
|
14
|
+
onError
|
|
15
|
+
}) {
|
|
16
|
+
return eventHandler(async (event) => {
|
|
17
|
+
config = defu(config, useRuntimeConfig(event).oauth?.strava);
|
|
18
|
+
const query = getQuery(event);
|
|
19
|
+
if (query.error) {
|
|
20
|
+
const error = createError({
|
|
21
|
+
statusCode: 401,
|
|
22
|
+
message: `Strava login failed: ${query.error || "Unknown error"}`,
|
|
23
|
+
data: query
|
|
24
|
+
});
|
|
25
|
+
if (!onError) throw error;
|
|
26
|
+
return onError(event, error);
|
|
27
|
+
}
|
|
28
|
+
if (!config.clientId || !config.clientSecret) {
|
|
29
|
+
return handleMissingConfiguration(
|
|
30
|
+
event,
|
|
31
|
+
"strava",
|
|
32
|
+
["clientId", "clientSecret"],
|
|
33
|
+
onError
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
const authorizationURL = "https://www.strava.com/oauth/authorize";
|
|
37
|
+
const tokenURL = "https://www.strava.com/oauth/token";
|
|
38
|
+
const redirectURL = config.redirectURL || getOAuthRedirectURL(event);
|
|
39
|
+
if (!query.code) {
|
|
40
|
+
return sendRedirect(
|
|
41
|
+
event,
|
|
42
|
+
withQuery(authorizationURL, {
|
|
43
|
+
client_id: config.clientId,
|
|
44
|
+
redirect_uri: redirectURL,
|
|
45
|
+
response_type: "code",
|
|
46
|
+
approval_prompt: config.approvalPrompt || "auto",
|
|
47
|
+
scope: config.scope
|
|
48
|
+
})
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
const tokens = await requestAccessToken(tokenURL, {
|
|
52
|
+
body: {
|
|
53
|
+
client_id: config.clientId,
|
|
54
|
+
client_secret: config.clientSecret,
|
|
55
|
+
code: query.code,
|
|
56
|
+
grant_type: "authorization_code",
|
|
57
|
+
redirect_uri: redirectURL
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
if (tokens.error) {
|
|
61
|
+
return handleAccessTokenErrorResponse(event, "strava", tokens, onError);
|
|
62
|
+
}
|
|
63
|
+
const user = await $fetch("https://www.strava.com/api/v3/athlete", {
|
|
64
|
+
headers: {
|
|
65
|
+
Authorization: `Bearer ${tokens.access_token}`
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
return onSuccess(event, {
|
|
69
|
+
user,
|
|
70
|
+
tokens
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
}
|
|
@@ -5,22 +5,27 @@ import type { OAuthConfig } from '#auth-utils';
|
|
|
5
5
|
*/
|
|
6
6
|
export interface OAuthWorkOSConfig {
|
|
7
7
|
/**
|
|
8
|
-
* WorkOS OAuth Client ID
|
|
8
|
+
* WorkOS OAuth Client ID *required
|
|
9
9
|
* @default process.env.NUXT_OAUTH_WORKOS_CLIENT_ID
|
|
10
10
|
*/
|
|
11
11
|
clientId?: string;
|
|
12
12
|
/**
|
|
13
|
-
* WorkOS OAuth Client Secret (API Key)
|
|
13
|
+
* WorkOS OAuth Client Secret (API Key) *required
|
|
14
14
|
* @default process.env.NUXT_OAUTH_WORKOS_CLIENT_SECRET
|
|
15
15
|
*/
|
|
16
16
|
clientSecret?: string;
|
|
17
17
|
/**
|
|
18
|
-
* WorkOS OAuth
|
|
18
|
+
* WorkOS OAuth Organization ID *not required
|
|
19
|
+
* @default process.env.NUXT_OAUTH_WORKOS_ORGANIZATION_ID
|
|
20
|
+
*/
|
|
21
|
+
organizationId?: string;
|
|
22
|
+
/**
|
|
23
|
+
* WorkOS OAuth Connection ID *not required
|
|
19
24
|
* @default process.env.NUXT_OAUTH_WORKOS_CONNECTION_ID
|
|
20
25
|
*/
|
|
21
26
|
connectionId?: string;
|
|
22
27
|
/**
|
|
23
|
-
* WorkOS OAuth screen hint
|
|
28
|
+
* WorkOS OAuth screen hint *not required
|
|
24
29
|
* @default 'sign-in'
|
|
25
30
|
*/
|
|
26
31
|
screenHint?: 'sign-in' | 'sign-up';
|
|
@@ -21,14 +21,13 @@ export function defineOAuthWorkOSEventHandler({ config, onSuccess, onError }) {
|
|
|
21
21
|
response_type: "code",
|
|
22
22
|
provider: "authkit",
|
|
23
23
|
client_id: config.clientId,
|
|
24
|
-
redirect_uri: redirectURL,
|
|
25
|
-
connection_id: config.connectionId,
|
|
26
|
-
screen_hint: config.screenHint
|
|
24
|
+
redirect_uri: redirectURL || void 0,
|
|
25
|
+
connection_id: config.connectionId || void 0,
|
|
26
|
+
screen_hint: config.screenHint || "sign-in",
|
|
27
|
+
organization_id: config.organizationId || void 0
|
|
27
28
|
})
|
|
28
29
|
);
|
|
29
30
|
}
|
|
30
|
-
const ip_address = getRequestIP(event);
|
|
31
|
-
const user_agent = getRequestHeader(event, "user-agent");
|
|
32
31
|
const authenticateResponse = await requestAccessToken("https://api.workos.com/user_management/authenticate", {
|
|
33
32
|
headers: {
|
|
34
33
|
"Content-Type": "application/json"
|
|
@@ -38,8 +37,8 @@ export function defineOAuthWorkOSEventHandler({ config, onSuccess, onError }) {
|
|
|
38
37
|
client_id: config.clientId,
|
|
39
38
|
client_secret: config.clientSecret,
|
|
40
39
|
redirect_uri: redirectURL,
|
|
41
|
-
ip_address,
|
|
42
|
-
user_agent,
|
|
40
|
+
ip_address: getRequestIP(event),
|
|
41
|
+
user_agent: getRequestHeader(event, "user-agent"),
|
|
43
42
|
code: query.code
|
|
44
43
|
}
|
|
45
44
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { H3Event, H3Error } from 'h3';
|
|
2
|
-
export type OAuthProvider = 'auth0' | 'authentik' | 'battledotnet' | 'cognito' | 'discord' | 'dropbox' | 'facebook' | 'github' | 'gitlab' | 'google' | 'instagram' | 'keycloak' | 'linear' | 'linkedin' | 'microsoft' | 'paypal' | 'polar' | 'spotify' | 'seznam' | 'steam' | 'tiktok' | 'twitch' | 'vk' | 'workos' | 'x' | 'xsuaa' | 'yandex' | 'zitadel' | (string & {});
|
|
2
|
+
export type OAuthProvider = 'auth0' | 'authentik' | 'battledotnet' | 'cognito' | 'discord' | 'dropbox' | 'facebook' | 'github' | 'gitlab' | 'google' | 'instagram' | 'keycloak' | 'linear' | 'linkedin' | 'microsoft' | 'paypal' | 'polar' | 'spotify' | 'seznam' | 'steam' | 'strava' | 'tiktok' | 'twitch' | 'vk' | 'workos' | 'x' | 'xsuaa' | 'yandex' | 'zitadel' | (string & {});
|
|
3
3
|
export type OnError = (event: H3Event, error: H3Error) => Promise<void> | void;
|
|
4
4
|
export interface OAuthConfig<TConfig, TUser = any, TTokens = any> {
|
|
5
5
|
config?: TConfig;
|