diff --git a/packages/elements-core/src/hooks/useBundleRefsIntoDocument.ts b/packages/elements-core/src/hooks/useBundleRefsIntoDocument.ts index 31cb06c24..ecce473f9 100644 --- a/packages/elements-core/src/hooks/useBundleRefsIntoDocument.ts +++ b/packages/elements-core/src/hooks/useBundleRefsIntoDocument.ts @@ -9,6 +9,7 @@ import * as React from 'react'; interface Options { baseUrl?: string; + withCredentials?: boolean; } /** @@ -18,6 +19,7 @@ export function useBundleRefsIntoDocument(document: unknown, options?: Options) const [bundledData, setBundledData] = React.useState(document); const baseUrl = options?.baseUrl; + const withCredentials = options?.withCredentials; React.useEffect(() => { if (!isObject(document)) { @@ -26,7 +28,7 @@ export function useBundleRefsIntoDocument(document: unknown, options?: Options) } let isMounted = true; - doBundle(document, baseUrl) + doBundle(document, baseUrl, withCredentials) .then(res => { if (isMounted) { setBundledData({ ...res }); // this hmm....library mutates document so a shallow copy is required to force a rerender in all cases @@ -45,13 +47,18 @@ export function useBundleRefsIntoDocument(document: unknown, options?: Options) return () => { isMounted = false; }; - }, [document, baseUrl]); + }, [document, baseUrl, withCredentials]); return bundledData; } -const commonBundleOptions = { continueOnError: true }; -const doBundle = (data: object, baseUrl?: string) => { +const doBundle = (data: object, baseUrl?: string, withCredentials?: boolean) => { + const commonBundleOptions: $RefParser.Options = { + continueOnError: true, + resolve: { + http: <$RefParser.HTTPResolverOptions>{ withCredentials }, + }, + }; if (!baseUrl) { return $RefParser.bundle(data, commonBundleOptions); } else { diff --git a/packages/elements/src/containers/API.tsx b/packages/elements/src/containers/API.tsx index a5364e9ac..7d5f87f60 100644 --- a/packages/elements/src/containers/API.tsx +++ b/packages/elements/src/containers/API.tsx @@ -112,6 +112,13 @@ export interface CommonAPIProps extends RoutingProps { */ tryItCorsProxy?: string; + /** + * Whether to include CORS credentials (cookies, authorization headers, TLS client certificates) + * in remote ref requests + * @default: false + */ + withCredentials?: boolean; + /** * The amount of references deep should be presented. * @default undefined @@ -145,6 +152,7 @@ export const APIImpl: React.FC = props => { hideExport, tryItCredentialsPolicy, tryItCorsProxy, + withCredentials, maxRefDepth, renderExtensionAddon, basePath, @@ -170,7 +178,7 @@ export const APIImpl: React.FC = props => { const document = apiDescriptionDocument || fetchedDocument || ''; const parsedDocument = useParsedValue(document); - const bundledDocument = useBundleRefsIntoDocument(parsedDocument, { baseUrl: apiDescriptionUrl }); + const bundledDocument = useBundleRefsIntoDocument(parsedDocument, { baseUrl: apiDescriptionUrl, withCredentials }); const serviceNode = React.useMemo(() => transformOasToServiceNode(bundledDocument), [bundledDocument]); const exportProps = useExportDocumentProps({ originalDocument: document, bundledDocument }); diff --git a/packages/elements/src/web-components/components.ts b/packages/elements/src/web-components/components.ts index f153812a8..df6cd51b2 100644 --- a/packages/elements/src/web-components/components.ts +++ b/packages/elements/src/web-components/components.ts @@ -20,6 +20,7 @@ export const ApiElement = createElementClass(API, { logo: { type: 'string' }, tryItCredentialsPolicy: { type: 'string' }, tryItCorsProxy: { type: 'string' }, + withCredentials: { type: 'boolean' }, maxRefDepth: { type: 'number' }, renderExtensionAddon: { type: 'function' }, outerRouter: { type: 'boolean' },