OpenAPI: Improve auth handling

This commit is contained in:
Fuma Nama
2025-05-26 21:26:45 +08:00
parent 6cca4fc727
commit 0a90cb9331
4 changed files with 90 additions and 45 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'fumadocs-openapi': patch
---
Improve auth handling
+57 -26
View File
@@ -185,7 +185,7 @@ export default function Client({
if (authorization && value.authorization) {
authInfo.saveInfo(value.authorization);
writeAuthHeader(
writeAuthInfo(
authorization,
value.authorization,
value.header,
@@ -264,35 +264,67 @@ function FormBody({
return paramTypes.map((param) => parameters.filter((v) => v.in === param));
}, [parameters]);
function renderAuth() {
if (!authorization) return null;
const schema: RequestSchema =
authorization.type === 'http' && authorization.scheme === 'basic'
? {
type: 'object',
required: ['username', 'password'],
properties: {
username: {
type: 'string',
},
password: {
type: 'string',
},
const auth = useMemo(():
| {
in: string;
field: RequestSchema;
}
| undefined => {
if (!authorization) return;
if (authorization.type === 'http' && authorization.scheme === 'basic') {
return {
in: 'header',
field: {
type: 'object',
required: ['username', 'password'],
description: authorization.description,
properties: {
username: {
type: 'string',
},
}
: {
type: 'string',
description: 'The Authorization access token',
};
password: {
type: 'string',
},
},
},
};
} else if (
authorization.type === 'http' ||
authorization.type === 'oauth2'
) {
return {
in: 'header',
field: {
type: 'string',
description:
authorization.description ?? `The Authorization access token.`,
},
};
} else if (authorization.type === 'apiKey') {
return {
in: authorization.in,
field: {
type: 'string',
description: authorization.description ?? 'The API key.',
},
};
}
// TODO: handle OpenID connect
}, [authorization]);
function renderAuth() {
if (!auth) return null;
if (fields?.auth)
return renderCustomField('authorization', schema, fields.auth);
return renderCustomField('authorization', auth.field, fields.auth);
return (
<FieldSet
fieldName="authorization"
name="Authorization"
field={schema}
field={auth.field}
isRequired
/>
);
@@ -303,12 +335,11 @@ function FormBody({
{params.map((param, i) => {
const name = paramNames[i];
const type = paramTypes[i];
if (type !== 'header' && param.length === 0) return;
if (type === 'header' && !authorization && param.length === 0) return;
if ((!auth || type !== auth.in) && param.length === 0) return;
return (
<CollapsiblePanel key={name} title={name}>
{type === 'header' ? renderAuth() : null}
{auth && type === auth.in ? renderAuth() : null}
{param.map((field) => {
const fieldName = `${type}.${field.name}` as const;
@@ -563,7 +594,7 @@ function CollapsiblePanel({
);
}
function writeAuthHeader(
function writeAuthInfo(
authorization: Security,
input: FormValues['authorization'],
header: Record<string, unknown>,
+27 -18
View File
@@ -35,24 +35,6 @@ export function createBrowserFetcher(
? new URL(options.proxyUrl, window.location.origin)
: null;
if (typeof document !== 'undefined') {
for (const key in options.cookie) {
const value = options.cookie[key];
if (!value) continue;
document.cookie = [
`${key}=${value}`,
'HttpOnly',
proxyUrl &&
proxyUrl.origin !== window.location.origin &&
`domain=${proxyUrl.host}`,
'path=/',
]
.filter(Boolean)
.join(';');
}
}
let url = getPathnameFromInput(route, options.path, options.query);
if (proxyUrl) {
@@ -73,6 +55,33 @@ export function createBrowserFetcher(
body = await adapter.encode(options);
}
// cookies
for (const key in options.cookie) {
const value = options.cookie[key];
if (!value) continue;
const cookie = {
[key]: value,
domain:
proxyUrl && proxyUrl.origin !== window.location.origin
? `domain=${proxyUrl.host}`
: undefined,
path: '/',
'max-age': 30,
};
let str = '';
for (const [key, value] of Object.entries(cookie)) {
if (value) {
if (str.length > 0) str += '; ';
str += `${key}=${value}`;
}
}
document.cookie = str;
}
return fetch(url, {
method: options.method,
cache: 'no-cache',
+1 -1
View File
@@ -135,7 +135,7 @@ function getAuthorizationField(
if (!item) {
console.warn(
`Cannot find suitable security scheme for API Playground from ${JSON.stringify(security, null, 2)}. Only schemes with one requirement are allowed.`,
`Cannot find suitable security scheme for API Playground from ${JSON.stringify(security, null, 2)}. Only schemes with one requirement are allowed at the moment.`,
);
return;
}