diff --git a/README.md b/README.md index 42269e7..96e870f 100644 --- a/README.md +++ b/README.md @@ -364,7 +364,7 @@ You can theoretically register a hook that overwrites internal session fields li | optionalClaims | `string[]` (optional) | - | Claims to be extracted from the id token | | logoutUrl | `string` (optional) | '' | Logout endpoint URL | | scopeInTokenRequest | `boolean` (optional) | false | Include scope in token request | -| tokenRequestType | `'form'` \| `'json'` (optional) | `'form'` | Token request type | +| tokenRequestType | `'form'` \| `'form-urlencoded'` \| `'json'` (optional) | `'form'` | Token request type | | audience | `string` (optional) | - | Audience used for token validation (not included in requests by default, use additionalTokenParameters or additionalAuthParameters to add it) | | requiredProperties | `string`[] | - | Required properties of the configuration that will be validated at runtime. | | filterUserinfo | `string[]`(optional) | - | Filter userinfo response to only include these properties. | diff --git a/src/runtime/server/lib/oidc.ts b/src/runtime/server/lib/oidc.ts index 287dfdb..67ea793 100644 --- a/src/runtime/server/lib/oidc.ts +++ b/src/runtime/server/lib/oidc.ts @@ -6,7 +6,7 @@ import { useRuntimeConfig, useStorage } from '#imports' import { validateConfig } from '../utils/config' import { generateRandomUrlSafeString, generatePkceVerifier, generatePkceCodeChallenge, parseJwtToken, encryptToken, validateToken, genBase64FromString } from '../utils/security' import { getUserSessionId, clearUserSession } from '../utils/session' -import { configMerger, convertObjectToSnakeCase, generateFormDataRequest, oidcErrorHandler, useOidcLogger } from '../utils/oidc' +import { configMerger, convertObjectToSnakeCase, convertTokenRequestToType, getTokenRequestContentType, oidcErrorHandler, useOidcLogger } from '../utils/oidc' import { SignJWT } from 'jose' import * as providerPresets from '../../providers' import type { H3Event } from 'h3' @@ -135,6 +135,9 @@ export function callbackEventHandler({ onSuccess, onError }: OAuthConfig typeof entry[1] === 'string') + return new URLSearchParams(requestEntries).toString() +} + +export function convertTokenRequestToType( + requestValues: RefreshTokenRequest | TokenRequest, + requestType: OidcProviderConfig['tokenRequestType'] = 'form', +) { + switch (requestType) { + case 'json': + return requestValues + case 'form-urlencoded': + return generateFormUrlEncodedRequest(requestValues) + default: + return generateFormDataRequest(requestValues) + } +} + +export function getTokenRequestContentType( + requestType: OidcProviderConfig['tokenRequestType'] = 'form', +) { + return ( + { + json: 'application/json', + form: 'multipart/form-data', + 'form-urlencoded': 'application/x-www-form-urlencoded', + }[requestType] + ) +} + export function convertObjectToSnakeCase(object: Record) { return Object.entries(object).reduce((acc, [key, value]) => { acc[snakeCase(key)] = value diff --git a/src/runtime/types/oidc.ts b/src/runtime/types/oidc.ts index 1e10630..6c68f94 100644 --- a/src/runtime/types/oidc.ts +++ b/src/runtime/types/oidc.ts @@ -98,7 +98,7 @@ export interface OidcProviderConfig { * Token request type * @default 'form' */ - tokenRequestType?: 'form' | 'json' + tokenRequestType?: 'form' | 'json' | 'form-urlencoded' /** * Audience used for token validation (not included in requests by default, use additionalTokenParameters or additionalAuthParameters to add it) */