Skip to content

Commit

Permalink
refactor: request token
Browse files Browse the repository at this point in the history
* refactor: request token

* chore: fix import

* up

* up

* Merge branch 'main' into refactor/request-token

* [autofix.ci] apply automated fixes

* chore: fix types issue

* chore: lint

---------

Co-authored-by: Sébastien Chopin <seb@nuxt.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
  • Loading branch information
3 people committed Sep 2, 2024
1 parent 8d3af7e commit 925f688
Show file tree
Hide file tree
Showing 18 changed files with 318 additions and 406 deletions.
41 changes: 17 additions & 24 deletions src/runtime/server/lib/oauth/auth0.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { H3Event } from 'h3'
import { eventHandler, getQuery, getRequestURL, sendRedirect } from 'h3'
import { withQuery, parsePath } from 'ufo'
import { eventHandler, getQuery, sendRedirect } from 'h3'
import { withQuery } from 'ufo'
import { defu } from 'defu'
import { handleMissingConfiguration, handleAccessTokenErrorResponse } from '../utils'
import { handleMissingConfiguration, handleAccessTokenErrorResponse, getOAuthRedirectURL, requestAccessToken } from '../utils'
import { useRuntimeConfig } from '#imports'
import type { OAuthConfig } from '#auth-utils'

Expand Down Expand Up @@ -70,16 +70,17 @@ export function oauthAuth0EventHandler({ config, onSuccess, onError }: OAuthConf
config = defu(config, useRuntimeConfig(event).oauth?.auth0, {
authorizationParams: {},
}) as OAuthAuth0Config
const { code } = getQuery(event)

if (!config.clientId || !config.clientSecret || !config.domain) {
return handleMissingConfiguration(event, 'auth0', ['clientId', 'clientSecret', 'domain'], onError)
}
const authorizationURL = `https://${config.domain}/authorize`
const tokenURL = `https://${config.domain}/oauth/token`

const redirectURL = config.redirectURL || getRequestURL(event).href
if (!code) {
const query = getQuery<{ code?: string }>(event)
const redirectURL = config.redirectURL || getOAuthRedirectURL(event)

if (!query.code) {
config.scope = config.scope || ['openid', 'offline_access']
if (config.emailRequired && !config.scope.includes('email')) {
config.scope.push('email')
Expand All @@ -100,25 +101,17 @@ export function oauthAuth0EventHandler({ config, onSuccess, onError }: OAuthConf
)
}

// TODO: improve typing
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const tokens: any = await $fetch(
tokenURL as string,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: {
grant_type: 'authorization_code',
client_id: config.clientId,
client_secret: config.clientSecret,
redirect_uri: parsePath(redirectURL).pathname,
code,
},
const tokens = await requestAccessToken(tokenURL as string, {
headers: {
'Content-Type': 'application/json',
},
body: {
grant_type: 'authorization_code',
client_id: config.clientId,
client_secret: config.clientSecret,
redirect_uri: redirectURL,
code: query.code,
},
).catch((error) => {
return { error }
})

if (tokens.error) {
Expand Down
47 changes: 18 additions & 29 deletions src/runtime/server/lib/oauth/battledotnet.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { randomUUID } from 'node:crypto'
import type { H3Event } from 'h3'
import { eventHandler, createError, getQuery, getRequestURL, sendRedirect } from 'h3'
import { withQuery, parsePath } from 'ufo'
import { eventHandler, getQuery, sendRedirect } from 'h3'
import { withQuery } from 'ufo'
import { defu } from 'defu'
import { handleAccessTokenErrorResponse, handleMissingConfiguration } from '../utils'
import { useRuntimeConfig } from '#imports'
import { randomUUID } from 'uncrypto'
import { handleMissingConfiguration, handleAccessTokenErrorResponse, getOAuthRedirectURL, requestAccessToken } from '../utils'
import { useRuntimeConfig, createError } from '#imports'
import type { OAuthConfig } from '#auth-utils'

export interface OAuthBattledotnetConfig {
Expand Down Expand Up @@ -62,8 +62,7 @@ export function oauthBattledotnetEventHandler({ config, onSuccess, onError }: OA
authorizationParams: {},
}) as OAuthBattledotnetConfig

const query = getQuery(event)
const { code } = query
const query = getQuery<{ code?: string, error?: string }>(event)

if (query.error) {
const error = createError({
Expand All @@ -80,8 +79,9 @@ export function oauthBattledotnetEventHandler({ config, onSuccess, onError }: OA
)
}

const redirectURL = config.redirectURL || getRequestURL(event).href
if (!code) {
const redirectURL = config.redirectURL || getOAuthRedirectURL(event)

if (!query.code) {
config.scope = config.scope || ['openid']
config.region = config.region || 'EU'

Expand Down Expand Up @@ -109,27 +109,16 @@ export function oauthBattledotnetEventHandler({ config, onSuccess, onError }: OA
config.scope.push('openid')
}

const authCode = Buffer.from(`${config.clientId}:${config.clientSecret}`).toString('base64')

// TODO: improve typing
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const tokens: any = await $fetch(
config.tokenURL as string,
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Basic ${authCode}`,
},
params: {
code,
grant_type: 'authorization_code',
scope: config.scope.join(' '),
redirect_uri: parsePath(redirectURL).pathname,
},
const tokens = await requestAccessToken(config.tokenURL as string, {
headers: {
Authorization: `Basic ${Buffer.from(`${config.clientId}:${config.clientSecret}`).toString('base64')}`,
},
params: {
grant_type: 'authorization_code',
scope: config.scope.join(' '),
redirect_uri: redirectURL,
code: query.code,
},
).catch((error) => {
return { error }
})

if (tokens.error) {
Expand Down
31 changes: 15 additions & 16 deletions src/runtime/server/lib/oauth/cognito.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { H3Event } from 'h3'
import { eventHandler, getQuery, getRequestURL, sendRedirect } from 'h3'
import { withQuery, parsePath } from 'ufo'
import { eventHandler, getQuery, sendRedirect } from 'h3'
import { withQuery } from 'ufo'
import { defu } from 'defu'
import { handleAccessTokenErrorResponse, handleMissingConfiguration } from '../utils'
import { handleMissingConfiguration, handleAccessTokenErrorResponse, getOAuthRedirectURL, requestAccessToken } from '../utils'
import { useRuntimeConfig } from '#imports'
import type { OAuthConfig } from '#auth-utils'

Expand Down Expand Up @@ -54,7 +54,6 @@ export function oauthCognitoEventHandler({ config, onSuccess, onError }: OAuthCo
config = defu(config, useRuntimeConfig(event).oauth?.cognito, {
authorizationParams: {},
}) as OAuthCognitoConfig
const { code } = getQuery(event)

if (!config.clientId || !config.clientSecret || !config.userPoolId || !config.region) {
return handleMissingConfiguration(event, 'cognito', ['clientId', 'clientSecret', 'userPoolId', 'region'], onError)
Expand All @@ -65,8 +64,10 @@ export function oauthCognitoEventHandler({ config, onSuccess, onError }: OAuthCo
const authorizationURL = `https://${urlBase}/oauth2/authorize`
const tokenURL = `https://${urlBase}/oauth2/token`

const redirectURL = config.redirectURL || getRequestURL(event).href
if (!code) {
const query = getQuery<{ code?: string }>(event)
const redirectURL = config.redirectURL || getOAuthRedirectURL(event)

if (!query.code) {
config.scope = config.scope || ['openid', 'profile']
// Redirect to Cognito login page
return sendRedirect(
Expand All @@ -81,20 +82,18 @@ export function oauthCognitoEventHandler({ config, onSuccess, onError }: OAuthCo
)
}

// TODO: improve typing
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const tokens: any = await $fetch(
const tokens = await requestAccessToken(
tokenURL as string,
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
body: {
grant_type: 'authorization_code',
client_id: config.clientId,
client_secret: config.clientSecret,
redirect_uri: redirectURL,
code: query.code,
},
body: `grant_type=authorization_code&client_id=${config.clientId}&client_secret=${config.clientSecret}&redirect_uri=${parsePath(redirectURL).pathname}&code=${code}`,
},
).catch((error) => {
return { error }
})
)

if (tokens.error) {
return handleAccessTokenErrorResponse(event, 'cognito', tokens, onError)
Expand Down
40 changes: 14 additions & 26 deletions src/runtime/server/lib/oauth/discord.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { H3Event } from 'h3'
import { eventHandler, getQuery, getRequestURL, sendRedirect } from 'h3'
import { withQuery, parseURL, stringifyParsedURL } from 'ufo'
import { eventHandler, getQuery, sendRedirect } from 'h3'
import { withQuery } from 'ufo'
import { defu } from 'defu'
import { handleAccessTokenErrorResponse, handleMissingConfiguration } from '../utils'
import { handleMissingConfiguration, handleAccessTokenErrorResponse, getOAuthRedirectURL, requestAccessToken } from '../utils'
import { useRuntimeConfig } from '#imports'
import type { OAuthConfig } from '#auth-utils'

Expand Down Expand Up @@ -67,14 +67,15 @@ export function oauthDiscordEventHandler({ config, onSuccess, onError }: OAuthCo
profileRequired: true,
authorizationParams: {},
}) as OAuthDiscordConfig
const { code } = getQuery(event)
const query = getQuery<{ code?: string }>(event)

if (!config.clientId || !config.clientSecret) {
return handleMissingConfiguration(event, 'discord', ['clientId', 'clientSecret'], onError)
}

const redirectURL = config.redirectURL || getRequestURL(event).href
if (!code) {
const redirectURL = config.redirectURL || getOAuthRedirectURL(event)

if (!query.code) {
config.scope = config.scope || []
if (config.emailRequired && !config.scope.includes('email')) {
config.scope.push('email')
Expand All @@ -96,27 +97,14 @@ export function oauthDiscordEventHandler({ config, onSuccess, onError }: OAuthCo
)
}

const parsedRedirectUrl = parseURL(redirectURL)
parsedRedirectUrl.search = ''
// TODO: improve typing
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const tokens: any = await $fetch(
config.tokenURL as string,
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
client_id: config.clientId,
client_secret: config.clientSecret,
grant_type: 'authorization_code',
redirect_uri: stringifyParsedURL(parsedRedirectUrl),
code: code as string,
}).toString(),
const tokens = await requestAccessToken(config.tokenURL as string, {
body: {
client_id: config.clientId,
client_secret: config.clientSecret,
grant_type: 'authorization_code',
redirect_uri: redirectURL,
code: query.code,
},
).catch((error) => {
return { error }
})

if (tokens.error) {
Expand Down
24 changes: 9 additions & 15 deletions src/runtime/server/lib/oauth/facebook.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import type { H3Event } from 'h3'
import {
eventHandler,
createError,
getQuery,
getRequestURL,
sendRedirect,
} from 'h3'
import { eventHandler, getQuery, sendRedirect } from 'h3'
import { withQuery } from 'ufo'
import { defu } from 'defu'
import { handleAccessTokenErrorResponse, handleMissingConfiguration } from '../utils'
import { useRuntimeConfig } from '#imports'
import { handleMissingConfiguration, handleAccessTokenErrorResponse, getOAuthRedirectURL, requestAccessToken } from '../utils'
import { useRuntimeConfig, createError } from '#imports'
import type { OAuthConfig } from '#auth-utils'

export interface OAuthFacebookConfig {
Expand Down Expand Up @@ -74,7 +68,8 @@ export function oauthFacebookEventHandler({
tokenURL: 'https://graph.facebook.com/v19.0/oauth/access_token',
authorizationParams: {},
}) as OAuthFacebookConfig
const query = getQuery(event)

const query = getQuery<{ code?: string, error?: string }>(event)

if (query.error) {
const error = createError({
Expand All @@ -90,7 +85,8 @@ export function oauthFacebookEventHandler({
return handleMissingConfiguration(event, 'facebook', ['clientId'], onError)
}

const redirectURL = config.redirectURL || getRequestURL(event).href
const redirectURL = config.redirectURL || getOAuthRedirectURL(event)

if (!query.code) {
config.scope = config.scope || []
// Redirect to Facebook Oauth page
Expand All @@ -104,13 +100,11 @@ export function oauthFacebookEventHandler({
)
}

// TODO: improve typing
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const tokens: any = await $fetch(config.tokenURL as string, {
method: 'POST',
const tokens = await requestAccessToken(config.tokenURL as string, {
body: {
client_id: config.clientId,
client_secret: config.clientSecret,
grant_type: 'authorization_code',
redirect_uri: redirectURL,
code: query.code,
},
Expand Down
34 changes: 16 additions & 18 deletions src/runtime/server/lib/oauth/github.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { H3Event } from 'h3'
import { eventHandler, createError, getQuery, getRequestURL, sendRedirect } from 'h3'
import { eventHandler, getQuery, sendRedirect } from 'h3'
import { withQuery } from 'ufo'
import { defu } from 'defu'
import { handleAccessTokenErrorResponse, handleMissingConfiguration } from '../utils'
import { useRuntimeConfig } from '#imports'
import { handleMissingConfiguration, handleAccessTokenErrorResponse, getOAuthRedirectURL, requestAccessToken } from '../utils'
import { useRuntimeConfig, createError } from '#imports'
import type { OAuthConfig } from '#auth-utils'

export interface OAuthGitHubConfig {
Expand Down Expand Up @@ -64,7 +64,8 @@ export function oauthGitHubEventHandler({ config, onSuccess, onError }: OAuthCon
tokenURL: 'https://github.com/login/oauth/access_token',
authorizationParams: {},
}) as OAuthGitHubConfig
const query = getQuery(event)

const query = getQuery<{ code?: string, error?: string }>(event)

if (query.error) {
const error = createError({
Expand All @@ -80,13 +81,14 @@ export function oauthGitHubEventHandler({ config, onSuccess, onError }: OAuthCon
return handleMissingConfiguration(event, 'github', ['clientId', 'clientSecret'], onError)
}

const redirectURL = config.redirectURL || getOAuthRedirectURL(event)

if (!query.code) {
config.scope = config.scope || []
if (config.emailRequired && !config.scope.includes('user:email')) {
config.scope.push('user:email')
}
// Redirect to GitHub Oauth page
const redirectURL = config.redirectURL || getRequestURL(event).href

return sendRedirect(
event,
withQuery(config.authorizationURL as string, {
Expand All @@ -98,19 +100,15 @@ export function oauthGitHubEventHandler({ config, onSuccess, onError }: OAuthCon
)
}

// TODO: improve typing
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const tokens: any = await $fetch(
config.tokenURL as string,
{
method: 'POST',
body: {
client_id: config.clientId,
client_secret: config.clientSecret,
code: query.code,
},
const tokens = await requestAccessToken(config.tokenURL as string, {
body: {
grant_type: 'authorization_code',
client_id: config.clientId,
client_secret: config.clientSecret,
redirect_uri: redirectURL,
code: query.code,
},
)
})

if (tokens.error) {
return handleAccessTokenErrorResponse(event, 'github', tokens, onError)
Expand Down
Loading

0 comments on commit 925f688

Please sign in to comment.