diff --git a/docs/docs/adapters/index.md b/docs/docs/adapters/index.md index 6735712b..e3dcbd0b 100644 --- a/docs/docs/adapters/index.md +++ b/docs/docs/adapters/index.md @@ -10,3 +10,4 @@ Adapters are a set of helper functions to provide framework specific integration - [Express](./express.md) - If you're using Express, you can use the `@jmondi/oauth2-server/express` adapter. - [Fastify](./fastify.md) - If you're using Fastify, you can use the `@jmondi/oauth2-server/fastify` adapter. - [VanillaJS](./vanilla.md) - Adapts the Fetch [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) and [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) so you can use Honojs, Sveltekit, Nextjs or whatever tool your using that uses the native [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) and [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) `@jmondi/oauth2-server/vanilla` adapter. +- [Nuxt](./nuxt.md) - If you are using Nuxt, you can directly copy this code and use it as is. diff --git a/docs/docs/adapters/nuxt.md b/docs/docs/adapters/nuxt.md new file mode 100644 index 00000000..9ee9cf83 --- /dev/null +++ b/docs/docs/adapters/nuxt.md @@ -0,0 +1,113 @@ +# Nuxt + +This code is used to transform a Nuxt response or to construct a new Nuxt HTTP response. + +## Source Code + +```ts +import type { OAuthResponse } from '@jmondi/oauth2-server' +import { ErrorType, OAuthException, OAuthRequest } from '@jmondi/oauth2-server' +import { getHeaders, getQuery, readBody, sendError, type H3Event } from 'h3' + +export function responseWithH3(event: H3Event, oauthResponse: OAuthResponse, wrapResp?: string): void { + if (oauthResponse.status === 302) { + if (typeof oauthResponse.headers.location !== 'string' || oauthResponse.headers.location === '') { + throw new OAuthException(`missing redirect location`, ErrorType.InvalidRequest) + } + event.respondWith( + new Response(null, { + status: 302, + headers: { + Location: oauthResponse.headers.location + } + }) + ) + } + + let body = oauthResponse.body + if (wrapResp) { + body = { [wrapResp]: body } + } + + event.respondWith( + new Response(JSON.stringify(body), { + status: oauthResponse.status, + headers: oauthResponse.headers + }) + ) +} + +export async function requestFromH3(event: H3Event, updatedBody?: Record): Promise { + let query: Record = {} + let body: Record = {} + if (['GET', 'DELETE', 'HEAD', 'OPTIONS'].includes(event.method.toUpperCase())) { + query = getQuery(event) as Record + } + if (['POST', 'PUT', 'PATCH'].includes(event.method.toUpperCase())) { + if (updatedBody) { + body = updatedBody + } else { + body = await readBody(event) + } + } + return new OAuthRequest({ + query: query, + body: body, + headers: getHeaders(event) ?? {} + }) +} + +export function handleErrorWithH3(event: H3Event, e: unknown | OAuthException): void { + if (isOAuthError(e)) { + sendError(event, e) + return + } + throw e +} + +export function isOAuthError(error: unknown): error is OAuthException { + if (!error) return false + if (typeof error !== 'object') return false + return 'oauth' in error +} +``` + +## Functions + +```ts + function responseWithH3(event: H3Event, oauthResponse: OAuthResponse, wrapResp?: string): void +``` + +```ts +export async function requestFromH3(event: H3Event, updatedBody?: Record): Promise +``` + +```ts +export function handleErrorWithH3(event: H3Event, e: unknown | OAuthException) +``` + + +## Example + + +```ts +import { requestFromH3, handleErrorWithH3, responseWithH3 } from '../../tools/converts' + +export default defineEventHandler(async (event) => { + const body = await readBody(event) + body.grant_type = 'password' + body.client_id = useRuntimeConfig().oauth.client.clientId + body.client_secret = useRuntimeConfig().oauth.client.secret + try { + // Here is an instance of new AuthorizationServer. + const oauthServer = useOAuthServer() + // A transformation is applied here. + const oauthResponse = await oauthServer.respondToAccessTokenRequest(await requestFromH3(event, body)) + // The response is directly forwarded here. + responseWithH3(event, oauthResponse, 'data') + } catch (e) { + console.error(e) + handleErrorWithH3(event, e) + } +}) +``` \ No newline at end of file