From f11215f907589954aa2aeb6cd4b6933836292aa9 Mon Sep 17 00:00:00 2001 From: Eko Eryanto Date: Wed, 12 Feb 2025 19:19:37 +0700 Subject: [PATCH 1/3] feat: add u.id provider U.ID is unique because it provide legit National ID Card Number --- src/runtime/server/lib/oauth/uid.ts | 115 ++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 src/runtime/server/lib/oauth/uid.ts diff --git a/src/runtime/server/lib/oauth/uid.ts b/src/runtime/server/lib/oauth/uid.ts new file mode 100644 index 00000000..c29e00d6 --- /dev/null +++ b/src/runtime/server/lib/oauth/uid.ts @@ -0,0 +1,115 @@ +import type { OAuthConfig } from '#auth-utils' +import type { H3Event } from 'h3' +import { createError, useRuntimeConfig } from '#imports' +import { defu } from 'defu' +import { eventHandler, getQuery, sendRedirect } from 'h3' +import { withQuery } from 'ufo' +import { getOAuthRedirectURL, handleAccessTokenErrorResponse, handleMissingConfiguration, requestAccessToken } from '../utils' + +export interface OAuthUidConfig { + /** + * U.id OAuth Client ID + * @default process.env.NUXT_OAUTH_UID_CLIENT_ID + */ + clientId?: string + /** + * U.id OAuth Client Secret + * @default process.env.NUXT_OAUTH_UID_CLIENT_SECRET + */ + clientSecret?: string + /** + * U.id OAuth Domain + * @default process.env.NUXT_OAUTH_UID_DOMAIN + */ + domain?: string + /** + * Redirect URL to allow overriding for situations like prod failing to determine public hostname + * @default process.env.NUXT_OAUTH_UID_REDIRECT_URL or current URL + */ + redirectURL?: string +} + +export function defineOAuthUidEventHandler({ config, onSuccess, onError }: OAuthConfig) { + return eventHandler(async (event: H3Event) => { + config = defu(config, useRuntimeConfig(event).oauth?.uid, { domain: 'api-v2.u.id' }) as OAuthUidConfig + + const query = getQuery<{ code?: string, error?: string }>(event) + + if (query.error) { + const error = createError({ + statusCode: 401, + message: `Uid login failed: ${query.error || 'Unknown error'}`, + data: query, + }) + if (!onError) + throw error + return onError(event, error) + } + + if (!config.clientId || !config.clientSecret) { + return handleMissingConfiguration(event, 'uid', ['clientId', 'clientSecret'], onError) + } + + + const authorizationURL = `https://u.id/oauth/authorize/` + const tokenURL = `https://${config.domain}/api/oauth/token/` + const redirectURL = config.redirectURL || getOAuthRedirectURL(event) + + if (!query.code) { + // Redirect to Uid OAuth page + + return sendRedirect( + event, + withQuery(authorizationURL, { + response_type: 'code', + client_id: config.clientId, + redirect_uri: redirectURL, + scope: ['openid', 'profile', 'email'].join(' '), + }), + ) + } + + const tokens = await requestAccessToken(tokenURL, { + headers: { + 'Authorization': `Basic ${Buffer.from(`${config.clientId}:${config.clientSecret}`).toString('base64')}`, + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: { + grant_type: 'authorization_code', + client_id: config.clientId, + redirect_uri: redirectURL, + code: query.code, + }, + }) + + if (tokens.error) { + return handleAccessTokenErrorResponse(event, 'uid', tokens, onError) + } + + const accessToken = tokens.access_token + // Fetch user info + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const user: any = await $fetch(`https://${config.domain}/api/v2/user_info/`, { + headers: { + Authorization: `Bearer ${accessToken}`, + Accept: 'application/json', + }, + }) + + if (!user) { + const error = createError({ + statusCode: 500, + message: 'Could not get Uid user', + data: tokens, + }) + if (!onError) + throw error + return onError(event, error) + } + + return onSuccess(event, { + user, + tokens, + }) + }) +} From 8f3f7c29b276f0aee11ff46ba947bc66b9ad6586 Mon Sep 17 00:00:00 2001 From: Eko Eryanto Date: Wed, 12 Feb 2025 19:32:07 +0700 Subject: [PATCH 2/3] update access token retrieval --- src/runtime/server/lib/oauth/uid.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/server/lib/oauth/uid.ts b/src/runtime/server/lib/oauth/uid.ts index c29e00d6..8cae026c 100644 --- a/src/runtime/server/lib/oauth/uid.ts +++ b/src/runtime/server/lib/oauth/uid.ts @@ -71,12 +71,12 @@ export function defineOAuthUidEventHandler({ config, onSuccess, onError }: OAuth const tokens = await requestAccessToken(tokenURL, { headers: { - 'Authorization': `Basic ${Buffer.from(`${config.clientId}:${config.clientSecret}`).toString('base64')}`, - 'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Type': 'application/json', }, body: { grant_type: 'authorization_code', client_id: config.clientId, + client_secret: config.clientSecret, redirect_uri: redirectURL, code: query.code, }, From 2954c42eabfced2c53c9ca4fb61b3f41062ab717 Mon Sep 17 00:00:00 2001 From: Eko Eryanto Date: Wed, 12 Feb 2025 19:32:53 +0700 Subject: [PATCH 3/3] clientId to number --- src/runtime/server/lib/oauth/uid.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/server/lib/oauth/uid.ts b/src/runtime/server/lib/oauth/uid.ts index 8cae026c..8e306d81 100644 --- a/src/runtime/server/lib/oauth/uid.ts +++ b/src/runtime/server/lib/oauth/uid.ts @@ -75,7 +75,7 @@ export function defineOAuthUidEventHandler({ config, onSuccess, onError }: OAuth }, body: { grant_type: 'authorization_code', - client_id: config.clientId, + client_id: +config.clientId, client_secret: config.clientSecret, redirect_uri: redirectURL, code: query.code,