nuxt-auth-utils 0.5.17 → 0.5.18
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 +4 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +19 -0
- package/dist/runtime/server/lib/oauth/github.d.ts +5 -0
- package/dist/runtime/server/lib/oauth/github.js +3 -2
- package/dist/runtime/server/lib/oauth/heroku.d.ts +41 -0
- package/dist/runtime/server/lib/oauth/heroku.js +75 -0
- package/dist/runtime/server/lib/oauth/salesforce.d.ts +46 -0
- package/dist/runtime/server/lib/oauth/salesforce.js +74 -0
- package/dist/runtime/server/lib/oauth/slack.d.ts +41 -0
- package/dist/runtime/server/lib/oauth/slack.js +74 -0
- package/dist/runtime/types/oauth-config.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ Add Authentication to Nuxt applications with secured & sealed cookies sessions.
|
|
|
16
16
|
## Features
|
|
17
17
|
|
|
18
18
|
- [Hybrid Rendering](#hybrid-rendering) support (SSR / CSR / SWR / Prerendering)
|
|
19
|
-
- [
|
|
19
|
+
- [40+ OAuth Providers](#supported-oauth-providers)
|
|
20
20
|
- [Password Hashing](#password-hashing)
|
|
21
21
|
- [WebAuthn (passkey)](#webauthn-passkey)
|
|
22
22
|
- [`useUserSession()` Vue composable](#vue-composable)
|
|
@@ -226,6 +226,7 @@ It can also be set using environment variables:
|
|
|
226
226
|
- GitLab
|
|
227
227
|
- Gitea
|
|
228
228
|
- Google
|
|
229
|
+
- Heroku
|
|
229
230
|
- Hubspot
|
|
230
231
|
- Instagram
|
|
231
232
|
- Kick
|
|
@@ -237,7 +238,9 @@ It can also be set using environment variables:
|
|
|
237
238
|
- Microsoft
|
|
238
239
|
- PayPal
|
|
239
240
|
- Polar
|
|
241
|
+
- Salesforce
|
|
240
242
|
- Seznam
|
|
243
|
+
- Slack
|
|
241
244
|
- Spotify
|
|
242
245
|
- Steam
|
|
243
246
|
- Strava
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -334,6 +334,25 @@ const module = defineNuxtModule({
|
|
|
334
334
|
clientId: "",
|
|
335
335
|
clientSecret: ""
|
|
336
336
|
});
|
|
337
|
+
runtimeConfig.oauth.salesforce = defu(runtimeConfig.oauth.salesforce, {
|
|
338
|
+
clientId: "",
|
|
339
|
+
clientSecret: "",
|
|
340
|
+
redirectURL: "",
|
|
341
|
+
baseURL: "",
|
|
342
|
+
scope: ""
|
|
343
|
+
});
|
|
344
|
+
runtimeConfig.oauth.slack = defu(runtimeConfig.oauth.slack, {
|
|
345
|
+
clientId: "",
|
|
346
|
+
clientSecret: "",
|
|
347
|
+
redirectURL: "",
|
|
348
|
+
scope: ""
|
|
349
|
+
});
|
|
350
|
+
runtimeConfig.oauth.heroku = defu(runtimeConfig.oauth.heroku, {
|
|
351
|
+
clientId: "",
|
|
352
|
+
clientSecret: "",
|
|
353
|
+
redirectURL: "",
|
|
354
|
+
scope: ""
|
|
355
|
+
});
|
|
337
356
|
}
|
|
338
357
|
});
|
|
339
358
|
|
|
@@ -32,6 +32,11 @@ export interface OAuthGitHubConfig {
|
|
|
32
32
|
* @default 'https://github.com/login/oauth/access_token'
|
|
33
33
|
*/
|
|
34
34
|
tokenURL?: string;
|
|
35
|
+
/**
|
|
36
|
+
* GitHub API URL
|
|
37
|
+
* @default 'https://api.github.com'
|
|
38
|
+
*/
|
|
39
|
+
apiURL?: string;
|
|
35
40
|
/**
|
|
36
41
|
* Extra authorization parameters to provide to the authorization URL
|
|
37
42
|
* @see https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps#1-request-a-users-github-identity
|
|
@@ -8,6 +8,7 @@ export function defineOAuthGitHubEventHandler({ config, onSuccess, onError }) {
|
|
|
8
8
|
config = defu(config, useRuntimeConfig(event).oauth?.github, {
|
|
9
9
|
authorizationURL: "https://github.com/login/oauth/authorize",
|
|
10
10
|
tokenURL: "https://github.com/login/oauth/access_token",
|
|
11
|
+
apiURL: "https://api.github.com",
|
|
11
12
|
authorizationParams: {}
|
|
12
13
|
});
|
|
13
14
|
const query = getQuery(event);
|
|
@@ -52,14 +53,14 @@ export function defineOAuthGitHubEventHandler({ config, onSuccess, onError }) {
|
|
|
52
53
|
return handleAccessTokenErrorResponse(event, "github", tokens, onError);
|
|
53
54
|
}
|
|
54
55
|
const accessToken = tokens.access_token;
|
|
55
|
-
const user = await $fetch(
|
|
56
|
+
const user = await $fetch(`${config.apiURL}/user`, {
|
|
56
57
|
headers: {
|
|
57
58
|
"User-Agent": `Github-OAuth-${config.clientId}`,
|
|
58
59
|
"Authorization": `token ${accessToken}`
|
|
59
60
|
}
|
|
60
61
|
});
|
|
61
62
|
if (!user.email && config.emailRequired) {
|
|
62
|
-
const emails = await $fetch(
|
|
63
|
+
const emails = await $fetch(`${config.apiURL}/user/emails`, {
|
|
63
64
|
headers: {
|
|
64
65
|
"User-Agent": `Github-OAuth-${config.clientId}`,
|
|
65
66
|
"Authorization": `token ${accessToken}`
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { OAuthConfig } from '#auth-utils';
|
|
2
|
+
export interface OAuthHerokuConfig {
|
|
3
|
+
/**
|
|
4
|
+
* Heroku OAuth Client ID
|
|
5
|
+
* @default process.env.NUXT_OAUTH_HEROKU_CLIENT_ID
|
|
6
|
+
*/
|
|
7
|
+
clientId?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Heroku OAuth Client Secret
|
|
10
|
+
* @default process.env.NUXT_OAUTH_HEROKU_CLIENT_SECRET
|
|
11
|
+
*/
|
|
12
|
+
clientSecret?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Heroku OAuth Scope
|
|
15
|
+
* @default ['identity']
|
|
16
|
+
* @see https://devcenter.heroku.com/articles/oauth#scopes
|
|
17
|
+
* @example ['identity']
|
|
18
|
+
*/
|
|
19
|
+
scope?: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Heroku OAuth Authorization URL
|
|
22
|
+
* @default 'https://id.heroku.com/oauth/authorize'
|
|
23
|
+
*/
|
|
24
|
+
authorizationURL?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Heroku OAuth Authorization URL
|
|
27
|
+
* @default 'https://id.heroku.com/oauth/token'
|
|
28
|
+
*/
|
|
29
|
+
tokenURL?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Extra authorization parameters to provide to the authorization URL
|
|
32
|
+
* @default {}
|
|
33
|
+
*/
|
|
34
|
+
authorizationParams?: Record<string, string>;
|
|
35
|
+
/**
|
|
36
|
+
* Redirect URL to allow overriding for situations like prod failing to determine public hostname
|
|
37
|
+
* @default process.env.NUXT_OAUTH_HEROKU_REDIRECT_URL or current URL
|
|
38
|
+
*/
|
|
39
|
+
redirectURL?: string;
|
|
40
|
+
}
|
|
41
|
+
export declare function defineOAuthHerokuEventHandler({ config, onSuccess, onError, }: OAuthConfig<OAuthHerokuConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { eventHandler, getQuery, sendRedirect } from "h3";
|
|
2
|
+
import { withQuery } from "ufo";
|
|
3
|
+
import { defu } from "defu";
|
|
4
|
+
import { handleMissingConfiguration, handleAccessTokenErrorResponse, getOAuthRedirectURL, requestAccessToken, handleState, handleInvalidState } from "../utils.js";
|
|
5
|
+
import { useRuntimeConfig, createError } from "#imports";
|
|
6
|
+
export function defineOAuthHerokuEventHandler({
|
|
7
|
+
config,
|
|
8
|
+
onSuccess,
|
|
9
|
+
onError
|
|
10
|
+
}) {
|
|
11
|
+
return eventHandler(async (event) => {
|
|
12
|
+
const runtimeConfig = useRuntimeConfig(event).oauth?.heroku;
|
|
13
|
+
const baseURL = "https://id.heroku.com";
|
|
14
|
+
config = defu(config, runtimeConfig, {
|
|
15
|
+
authorizationURL: `${baseURL}/oauth/authorize`,
|
|
16
|
+
tokenURL: `${baseURL}/oauth/token`,
|
|
17
|
+
authorizationParams: {}
|
|
18
|
+
});
|
|
19
|
+
const query = getQuery(event);
|
|
20
|
+
if (query.error) {
|
|
21
|
+
const error = createError({
|
|
22
|
+
statusCode: 401,
|
|
23
|
+
message: `Heroku login failed: ${query.error || "Unknown error"}`,
|
|
24
|
+
data: query
|
|
25
|
+
});
|
|
26
|
+
if (!onError) throw error;
|
|
27
|
+
return onError(event, error);
|
|
28
|
+
}
|
|
29
|
+
if (!config.clientId || !config.clientSecret) {
|
|
30
|
+
return handleMissingConfiguration(event, "heroku", ["clientId", "clientSecret"], onError);
|
|
31
|
+
}
|
|
32
|
+
const redirectURL = config.redirectURL || getOAuthRedirectURL(event);
|
|
33
|
+
const state = await handleState(event);
|
|
34
|
+
if (!query.code) {
|
|
35
|
+
config.scope = config.scope || ["identity"];
|
|
36
|
+
return sendRedirect(
|
|
37
|
+
event,
|
|
38
|
+
withQuery(config.authorizationURL, {
|
|
39
|
+
response_type: "code",
|
|
40
|
+
client_id: config.clientId,
|
|
41
|
+
redirect_uri: redirectURL,
|
|
42
|
+
scope: config.scope.join(" "),
|
|
43
|
+
state,
|
|
44
|
+
...config.authorizationParams
|
|
45
|
+
})
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
if (query.state !== state) {
|
|
49
|
+
handleInvalidState(event, "heroku", onError);
|
|
50
|
+
}
|
|
51
|
+
const tokens = await requestAccessToken(config.tokenURL, {
|
|
52
|
+
body: {
|
|
53
|
+
grant_type: "authorization_code",
|
|
54
|
+
client_id: config.clientId,
|
|
55
|
+
client_secret: config.clientSecret,
|
|
56
|
+
redirect_uri: redirectURL,
|
|
57
|
+
code: query.code
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
if (tokens.error) {
|
|
61
|
+
return handleAccessTokenErrorResponse(event, "heroku", tokens, onError);
|
|
62
|
+
}
|
|
63
|
+
const accessToken = tokens.access_token;
|
|
64
|
+
const user = await $fetch(`https://api.heroku.com/account`, {
|
|
65
|
+
headers: {
|
|
66
|
+
Accept: "application/vnd.heroku+json; version=3",
|
|
67
|
+
Authorization: `Bearer ${accessToken}`
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
return onSuccess(event, {
|
|
71
|
+
user,
|
|
72
|
+
tokens
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { OAuthConfig } from '#auth-utils';
|
|
2
|
+
export interface OAuthSalesforceConfig {
|
|
3
|
+
/**
|
|
4
|
+
* Salesforce OAuth Client ID
|
|
5
|
+
* @default process.env.NUXT_OAUTH_SALESFORCE_CLIENT_ID
|
|
6
|
+
*/
|
|
7
|
+
clientId?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Salesforce OAuth Client Secret
|
|
10
|
+
* @default process.env.NUXT_OAUTH_SALESFORCE_CLIENT_SECRET
|
|
11
|
+
*/
|
|
12
|
+
clientSecret?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Salesforce OAuth Scope
|
|
15
|
+
* @default ['id']
|
|
16
|
+
* @see https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_oauth_tokens_scopes.htm
|
|
17
|
+
* @example ['id']
|
|
18
|
+
*/
|
|
19
|
+
scope?: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Salesforce MyDomain URL
|
|
22
|
+
* @default 'https://login.salesforce.com'
|
|
23
|
+
*/
|
|
24
|
+
baseURL?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Salesforce OAuth Authorization URL
|
|
27
|
+
* @default 'https://login.salesforce.com/services/oauth2/authorize'
|
|
28
|
+
*/
|
|
29
|
+
authorizationURL?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Salesforce OAuth Authorization URL
|
|
32
|
+
* @default 'https://login.salesforce.com/services/oauth2/token'
|
|
33
|
+
*/
|
|
34
|
+
tokenURL?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Extra authorization parameters to provide to the authorization URL
|
|
37
|
+
* @default {}
|
|
38
|
+
*/
|
|
39
|
+
authorizationParams?: Record<string, string>;
|
|
40
|
+
/**
|
|
41
|
+
* Redirect URL to allow overriding for situations like prod failing to determine public hostname
|
|
42
|
+
* @default process.env.NUXT_OAUTH_SALESFORCE_REDIRECT_URL or current URL
|
|
43
|
+
*/
|
|
44
|
+
redirectURL?: string;
|
|
45
|
+
}
|
|
46
|
+
export declare function defineOAuthSalesforceEventHandler({ config, onSuccess, onError, }: OAuthConfig<OAuthSalesforceConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { eventHandler, getQuery, sendRedirect } from "h3";
|
|
2
|
+
import { withQuery } from "ufo";
|
|
3
|
+
import { defu } from "defu";
|
|
4
|
+
import { handleMissingConfiguration, handleAccessTokenErrorResponse, getOAuthRedirectURL, requestAccessToken, handleState, handleInvalidState } from "../utils.js";
|
|
5
|
+
import { useRuntimeConfig, createError } from "#imports";
|
|
6
|
+
export function defineOAuthSalesforceEventHandler({
|
|
7
|
+
config,
|
|
8
|
+
onSuccess,
|
|
9
|
+
onError
|
|
10
|
+
}) {
|
|
11
|
+
return eventHandler(async (event) => {
|
|
12
|
+
const runtimeConfig = useRuntimeConfig(event).oauth?.salesforce;
|
|
13
|
+
const baseURL = config?.baseURL || "https://login.salesforce.com";
|
|
14
|
+
config = defu(config, runtimeConfig, {
|
|
15
|
+
authorizationURL: `${baseURL}/services/oauth2/authorize`,
|
|
16
|
+
tokenURL: `${baseURL}/services/oauth2/token`,
|
|
17
|
+
authorizationParams: {}
|
|
18
|
+
});
|
|
19
|
+
const query = getQuery(event);
|
|
20
|
+
if (query.error) {
|
|
21
|
+
const error = createError({
|
|
22
|
+
statusCode: 401,
|
|
23
|
+
message: `Salesforce login failed: ${query.error || "Unknown error"}`,
|
|
24
|
+
data: query
|
|
25
|
+
});
|
|
26
|
+
if (!onError) throw error;
|
|
27
|
+
return onError(event, error);
|
|
28
|
+
}
|
|
29
|
+
if (!config.clientId || !config.clientSecret) {
|
|
30
|
+
return handleMissingConfiguration(event, "salesforce", ["clientId", "clientSecret"], onError);
|
|
31
|
+
}
|
|
32
|
+
const redirectURL = config.redirectURL || getOAuthRedirectURL(event);
|
|
33
|
+
const state = await handleState(event);
|
|
34
|
+
if (!query.code) {
|
|
35
|
+
config.scope = config.scope || ["id"];
|
|
36
|
+
return sendRedirect(
|
|
37
|
+
event,
|
|
38
|
+
withQuery(config.authorizationURL, {
|
|
39
|
+
response_type: "code",
|
|
40
|
+
client_id: config.clientId,
|
|
41
|
+
redirect_uri: redirectURL,
|
|
42
|
+
scope: config.scope.join(" "),
|
|
43
|
+
state,
|
|
44
|
+
...config.authorizationParams
|
|
45
|
+
})
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
if (query.state !== state) {
|
|
49
|
+
handleInvalidState(event, "salesforce", onError);
|
|
50
|
+
}
|
|
51
|
+
const tokens = await requestAccessToken(config.tokenURL, {
|
|
52
|
+
body: {
|
|
53
|
+
grant_type: "authorization_code",
|
|
54
|
+
client_id: config.clientId,
|
|
55
|
+
client_secret: config.clientSecret,
|
|
56
|
+
redirect_uri: redirectURL,
|
|
57
|
+
code: query.code
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
if (tokens.error) {
|
|
61
|
+
return handleAccessTokenErrorResponse(event, "salesforce", tokens, onError);
|
|
62
|
+
}
|
|
63
|
+
const accessToken = tokens.access_token;
|
|
64
|
+
const user = await $fetch(`${baseURL}/services/oauth2/userinfo`, {
|
|
65
|
+
headers: {
|
|
66
|
+
Authorization: `Bearer ${accessToken}`
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
return onSuccess(event, {
|
|
70
|
+
user,
|
|
71
|
+
tokens
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { OAuthConfig } from '#auth-utils';
|
|
2
|
+
export interface OAuthSlackConfig {
|
|
3
|
+
/**
|
|
4
|
+
* Slack OAuth Client ID
|
|
5
|
+
* @default process.env.NUXT_OAUTH_SLACK_CLIENT_ID
|
|
6
|
+
*/
|
|
7
|
+
clientId?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Slack OAuth Client Secret
|
|
10
|
+
* @default process.env.NUXT_OAUTH_SLACK_CLIENT_SECRET
|
|
11
|
+
*/
|
|
12
|
+
clientSecret?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Slack OAuth Scope
|
|
15
|
+
* @default ['openid', 'email', 'profile']
|
|
16
|
+
* @see https://api.slack.com/scopes?filter=user
|
|
17
|
+
* @example ['openid']
|
|
18
|
+
*/
|
|
19
|
+
scope?: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Slack OAuth Authorization URL
|
|
22
|
+
* @default 'https://slack.com/openid/connect/authorize'
|
|
23
|
+
*/
|
|
24
|
+
authorizationURL?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Slack OAuth Authorization URL
|
|
27
|
+
* @default 'https://slack.com/api/openid.connect.token'
|
|
28
|
+
*/
|
|
29
|
+
tokenURL?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Extra authorization parameters to provide to the authorization URL
|
|
32
|
+
* @default {}
|
|
33
|
+
*/
|
|
34
|
+
authorizationParams?: Record<string, string>;
|
|
35
|
+
/**
|
|
36
|
+
* Redirect URL to allow overriding for situations like prod failing to determine public hostname
|
|
37
|
+
* @default process.env.NUXT_OAUTH_SLACK_REDIRECT_URL or current URL
|
|
38
|
+
*/
|
|
39
|
+
redirectURL?: string;
|
|
40
|
+
}
|
|
41
|
+
export declare function defineOAuthSlackEventHandler({ config, onSuccess, onError, }: OAuthConfig<OAuthSlackConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { eventHandler, getQuery, sendRedirect } from "h3";
|
|
2
|
+
import { withQuery } from "ufo";
|
|
3
|
+
import { defu } from "defu";
|
|
4
|
+
import { handleMissingConfiguration, handleAccessTokenErrorResponse, getOAuthRedirectURL, requestAccessToken, handleState, handleInvalidState } from "../utils.js";
|
|
5
|
+
import { useRuntimeConfig, createError } from "#imports";
|
|
6
|
+
export function defineOAuthSlackEventHandler({
|
|
7
|
+
config,
|
|
8
|
+
onSuccess,
|
|
9
|
+
onError
|
|
10
|
+
}) {
|
|
11
|
+
return eventHandler(async (event) => {
|
|
12
|
+
const runtimeConfig = useRuntimeConfig(event).oauth?.slack;
|
|
13
|
+
const baseURL = "https://slack.com";
|
|
14
|
+
config = defu(config, runtimeConfig, {
|
|
15
|
+
authorizationURL: `${baseURL}/openid/connect/authorize`,
|
|
16
|
+
tokenURL: `${baseURL}/api/openid.connect.token`,
|
|
17
|
+
authorizationParams: {}
|
|
18
|
+
});
|
|
19
|
+
const query = getQuery(event);
|
|
20
|
+
if (query.error) {
|
|
21
|
+
const error = createError({
|
|
22
|
+
statusCode: 401,
|
|
23
|
+
message: `Slack login failed: ${query.error || "Unknown error"}`,
|
|
24
|
+
data: query
|
|
25
|
+
});
|
|
26
|
+
if (!onError) throw error;
|
|
27
|
+
return onError(event, error);
|
|
28
|
+
}
|
|
29
|
+
if (!config.clientId || !config.clientSecret) {
|
|
30
|
+
return handleMissingConfiguration(event, "slack", ["clientId", "clientSecret"], onError);
|
|
31
|
+
}
|
|
32
|
+
const redirectURL = config.redirectURL || getOAuthRedirectURL(event);
|
|
33
|
+
const state = await handleState(event);
|
|
34
|
+
if (!query.code) {
|
|
35
|
+
config.scope = config.scope || ["openid", "email", "profile"];
|
|
36
|
+
return sendRedirect(
|
|
37
|
+
event,
|
|
38
|
+
withQuery(config.authorizationURL, {
|
|
39
|
+
response_type: "code",
|
|
40
|
+
client_id: config.clientId,
|
|
41
|
+
redirect_uri: redirectURL,
|
|
42
|
+
scope: config.scope.join(" "),
|
|
43
|
+
state,
|
|
44
|
+
...config.authorizationParams
|
|
45
|
+
})
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
if (query.state !== state) {
|
|
49
|
+
handleInvalidState(event, "slack", onError);
|
|
50
|
+
}
|
|
51
|
+
const tokens = await requestAccessToken(config.tokenURL, {
|
|
52
|
+
body: {
|
|
53
|
+
grant_type: "authorization_code",
|
|
54
|
+
client_id: config.clientId,
|
|
55
|
+
client_secret: config.clientSecret,
|
|
56
|
+
redirect_uri: redirectURL,
|
|
57
|
+
code: query.code
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
if (tokens.error) {
|
|
61
|
+
return handleAccessTokenErrorResponse(event, "slack", tokens, onError);
|
|
62
|
+
}
|
|
63
|
+
const accessToken = tokens.access_token;
|
|
64
|
+
const user = await $fetch(`${baseURL}/api/openid.connect.userInfo`, {
|
|
65
|
+
headers: {
|
|
66
|
+
Authorization: `Bearer ${accessToken}`
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
return onSuccess(event, {
|
|
70
|
+
user,
|
|
71
|
+
tokens
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { H3Event, H3Error } from 'h3';
|
|
2
2
|
export type ATProtoProvider = 'bluesky';
|
|
3
|
-
export type OAuthProvider = ATProtoProvider | 'atlassian' | 'auth0' | 'authentik' | 'azureb2c' | 'battledotnet' | 'cognito' | 'discord' | 'dropbox' | 'facebook' | 'gitea' | 'github' | 'gitlab' | 'google' | 'hubspot' | 'instagram' | 'kick' | 'keycloak' | 'line' | 'linear' | 'linkedin' | 'microsoft' | 'paypal' | 'polar' | 'spotify' | 'seznam' | 'steam' | 'strava' | 'tiktok' | 'twitch' | 'vk' | 'workos' | 'x' | 'xsuaa' | 'yandex' | 'zitadel' | 'apple' | 'livechat' | (string & {});
|
|
3
|
+
export type OAuthProvider = ATProtoProvider | 'atlassian' | 'auth0' | 'authentik' | 'azureb2c' | 'battledotnet' | 'cognito' | 'discord' | 'dropbox' | 'facebook' | 'gitea' | 'github' | 'gitlab' | 'google' | 'hubspot' | 'instagram' | 'kick' | 'keycloak' | 'line' | 'linear' | 'linkedin' | 'microsoft' | 'paypal' | 'polar' | 'spotify' | 'seznam' | 'steam' | 'strava' | 'tiktok' | 'twitch' | 'vk' | 'workos' | 'x' | 'xsuaa' | 'yandex' | 'zitadel' | 'apple' | 'livechat' | 'salesforce' | 'slack' | 'heroku' | (string & {});
|
|
4
4
|
export type OnError = (event: H3Event, error: H3Error) => Promise<void> | void;
|
|
5
5
|
export interface OAuthConfig<TConfig, TUser = any, TTokens = any> {
|
|
6
6
|
config?: TConfig;
|