@scalar/api-client 3.19.0 → 3.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/dist/style.css +55 -25
- package/dist/v2/blocks/request-block/RequestBlock.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.js +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js +21 -5
- package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBodyRaw.vue.d.ts.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBodyRaw.vue.js +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBodyRaw.vue.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBodyRaw.vue.script.js +42 -16
- package/dist/v2/blocks/response-block/components/ResponseBodyRaw.vue.script.js.map +1 -1
- package/dist/v2/blocks/response-block/helpers/media-types.d.ts.map +1 -1
- package/dist/v2/blocks/response-block/helpers/media-types.js +5 -0
- package/dist/v2/blocks/response-block/helpers/media-types.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2Metadata.vue.d.ts +16 -0
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2Metadata.vue.d.ts.map +1 -0
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2Metadata.vue.js +7 -0
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2Metadata.vue.js.map +1 -0
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2Metadata.vue.script.js +86 -0
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2Metadata.vue.script.js.map +1 -0
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.script.js +19 -2
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.d.ts +6 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.d.ts.map +1 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.js +25 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.js.map +1 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.d.ts +1 -2
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.js +2 -2
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js +13 -9
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.d.ts +9 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.d.ts.map +1 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.js +36 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.js.map +1 -0
- package/dist/v2/components/code-input/CodeInput.vue.d.ts +2 -2
- package/dist/v2/components/code-input/CodeInput.vue.d.ts.map +1 -1
- package/dist/v2/components/code-input/CodeInput.vue.js +1 -1
- package/dist/v2/components/code-input/CodeInput.vue.js.map +1 -1
- package/dist/v2/components/code-input/CodeInput.vue.script.js +40 -9
- package/dist/v2/components/code-input/CodeInput.vue.script.js.map +1 -1
- package/dist/v2/components/server/ServerDropdown.vue.d.ts.map +1 -1
- package/dist/v2/components/server/ServerDropdown.vue.js.map +1 -1
- package/dist/v2/components/server/ServerDropdown.vue.script.js +1 -1
- package/dist/v2/components/server/ServerDropdown.vue.script.js.map +1 -1
- package/dist/v2/constants.js +1 -1
- package/dist/v2/features/modal/helpers/resolve-route-parameters.d.ts +9 -3
- package/dist/v2/features/modal/helpers/resolve-route-parameters.d.ts.map +1 -1
- package/dist/v2/features/modal/helpers/resolve-route-parameters.js.map +1 -1
- package/dist/vue-styles.css +33 -23
- package/package.json +16 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RequestAuthTab.vue.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components/button'\nimport { ScalarIconButton } from '@scalar/components/icon-button'\nimport { useLoadingState } from '@scalar/components/loading'\nimport { ScalarMarkdownSummary } from '@scalar/components/markdown'\nimport { ScalarModal, useModal } from '@scalar/components/modal'\nimport { ScalarIconGear } from '@scalar/icons'\nimport { useToasts } from '@scalar/use-toasts'\nimport type {\n SecretsApiKey,\n SecretsHttp,\n} from '@scalar/workspace-store/entities/auth'\nimport type {\n ApiReferenceEvents,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport {\n getEnvironmentVariables,\n type MergedSecuritySchemes,\n type OAuthFlowsObjectSecret,\n type SecuritySchemeObjectSecret,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { getDocumentTypeLabel } from '@scalar/workspace-store/schemas/type-guards'\nimport type {\n ApiKeyObject,\n SecurityRequirementObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { capitalize, computed, ref } from 'vue'\n\nimport { refreshOauth2Token } from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth'\nimport { getVisibleOrderedFlowKeys } from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth-flows'\nimport {\n runOAuth2Authorize,\n storeOAuth2Tokens,\n} from '@/v2/blocks/scalar-auth-selector-block/helpers/run-oauth2-authorize'\nimport { getOauth2AcquisitionTarget } from '@/v2/blocks/scalar-auth-selector-block/helpers/security-scheme'\nimport {\n DataTable,\n DataTableCell,\n DataTableRow,\n} from '@/v2/components/data-table'\n\nimport OAuth2, { type OAuth2Options } from './OAuth2.vue'\nimport OpenIDConnect from './OpenIDConnect.vue'\nimport RequestAuthDataTableInput from './RequestAuthDataTableInput.vue'\n\ntype SecurityItem = {\n scheme: SecuritySchemeObjectSecret | undefined\n name: string\n scopes: string[]\n /** Ordered, non-hidden oauth2/openIdConnect flow keys for this scheme (empty for other types). */\n visibleFlowKeys: (keyof OAuthFlowsObjectSecret)[]\n}\n\nconst {\n environment,\n isStatic,\n proxyUrl,\n selectedSecuritySchemas,\n securitySchemes,\n server,\n eventBus,\n options,\n documentType = 'openapi',\n} = defineProps<{\n /** Current environment configuration */\n environment: XScalarEnvironment\n /** Controls the display of certain borders which are used when we are non-collapsible */\n isStatic: boolean\n /** Proxy URL */\n proxyUrl: string\n /** Selected security schemes*/\n selectedSecuritySchemas: SecurityRequirementObject\n /** Merged security schemes from the document and the config together with the auth store secrets */\n securitySchemes: MergedSecuritySchemes\n /** Current server configuration */\n server: ServerObject | null\n /** Event bus for authentication updates */\n eventBus: WorkspaceEventBus\n /** Any config options required for the OAuth2 flow */\n options?: OAuth2Options\n /** Type of the document the schemes belong to, used to label the missing-type warning */\n documentType?: 'openapi' | 'asyncapi'\n}>()\n\n/**\n * Human-readable name of the document type.\n * Used in the missing-type warning so it points at the correct document\n * (e.g. \"AsyncAPI\") instead of always naming OpenAPI.\n */\nconst documentTypeLabel = computed<string>(() =>\n getDocumentTypeLabel(documentType),\n)\n\nconst emits = defineEmits<{\n (\n e: 'update:selectedScopes',\n payload: Omit<ApiReferenceEvents['auth:update:selected-scopes'], 'meta'>,\n ): void\n (e: 'upsert:scope', payload: ApiReferenceEvents['auth:upsert:scopes']): void\n (e: 'delete:scope', payload: ApiReferenceEvents['auth:delete:scopes']): void\n}>()\n\n/**\n * Resolves security schemes from the OpenAPI document and combines them with their selected scopes.\n * Each item includes the scheme definition, name, and associated scopes.\n */\nconst security = computed<SecurityItem[]>(() =>\n Object.entries(selectedSecuritySchemas).map(([name, scopes = []]) => {\n const scheme = getResolvedRef(securitySchemes[name])\n return {\n scheme,\n name,\n scopes,\n // Compute the visible, ordered flow keys once per scheme so the tabs, the label, and the\n // active-flow tracking all agree on the same set (and we do not filter + sort on every access).\n visibleFlowKeys:\n scheme?.type === 'oauth2' || scheme?.type === 'openIdConnect'\n ? getVisibleOrderedFlowKeys(scheme.flows)\n : [],\n }\n }),\n)\n\n/** Tracks which OAuth2 flow is currently active when multiple flows are available. */\nconst activeFlow = ref<string>('')\n\n/**\n * Keeps the selected flow in sync with the currently visible flow keys. Validating against the\n * visible set (not every declared flow) means a selection that becomes hidden — e.g. the document\n * is updated to mark the active flow with `x-scalar-ignore` — resets, so the default (first visible)\n * flow activates instead of leaving no tab selected.\n */\nconst selectedFlow = computed<string>(() => {\n const visibleFlowKeys = security.value.flatMap((item) => item.visibleFlowKeys)\n\n return visibleFlowKeys.some((key) => key === activeFlow.value)\n ? activeFlow.value\n : ''\n})\n\nconst setActiveFlow = (flow: string): void => {\n activeFlow.value = flow\n}\n\n/** Determines if multiple auth schemes are configured, which affects the UI layout. */\nconst hasMultipleSchemes = computed<boolean>(() => security.value.length > 1)\n\n/**\n * Generates a human-readable label for the security scheme.\n * Intentionally omits the description here — it is rendered separately as\n * rich text via ScalarMarkdownSummary so markdown formatting is preserved.\n */\nconst generateLabel = (\n name: string,\n scheme: SecuritySchemeObjectSecret,\n): string => {\n const capitalizedName = capitalize(name)\n\n switch (scheme.type) {\n case 'apiKey':\n return `${capitalizedName}: ${scheme.in}`\n\n case 'openIdConnect':\n case 'oauth2': {\n const firstFlow = getVisibleOrderedFlowKeys(scheme.flows)[0]\n const currentFlow = selectedFlow.value || firstFlow\n if (!currentFlow) {\n return capitalizedName\n }\n return `${capitalizedName}: ${currentFlow}`\n }\n\n case 'http':\n return `${capitalizedName}: ${scheme.scheme}`\n\n default:\n return capitalizedName\n }\n}\n\n/**\n * Whether an API key scheme exposes an editable parameter name.\n *\n * OpenAPI `apiKey` and AsyncAPI `httpApiKey` (normalized to `apiKey`) name a query/header/cookie\n * parameter, so the Name input is shown. AsyncAPI `apiKey` places the key in the broker `user` or\n * `password` slot and has no parameter name, so the Name input is hidden and only the value is asked for.\n */\nconst apiKeyHasName = (scheme: { in?: string }): boolean =>\n scheme.in !== 'user' && scheme.in !== 'password'\n\n/**\n * The scheme's type when it is one we do not render inputs for (a type outside both the OpenAPI\n * and AsyncAPI security scheme unions). Read through a helper so the fallback template branch,\n * where the scheme type is narrowed to `never` after the supported cases, can still surface the type.\n */\nconst getUnsupportedSchemeType = (\n scheme: SecurityItem['scheme'],\n): string | undefined => scheme?.type\n\n/**\n * Determines if an OAuth2 flow tab should be active.\n * The first flow is active by default if no flow is explicitly selected.\n */\nconst isFlowActive = (flowKey: string, index: number): boolean =>\n selectedFlow.value === flowKey || (index === 0 && !selectedFlow.value)\n\n/** Computes the container class for static display mode. */\nconst getStaticBorderClass = (): string | false => isStatic && 'border-t'\n\nconst handleHttpSecretsUpdate = (\n payload: Omit<Partial<SecretsHttp>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: { type: 'http', ...payload },\n name,\n })\n\nconst handleApiKeySecretsUpdate = (\n payload: Omit<Partial<SecretsApiKey>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: { type: 'apiKey', ...payload },\n name,\n })\n\nconst handleApiKeySecuritySchemeUpdate = (\n payload: Omit<Partial<ApiKeyObject>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme', {\n payload: { type: 'apiKey', ...payload },\n name,\n })\n\n/** Handles scope selection updates for OAuth2 */\nconst handleScopesUpdate = (\n name: string,\n event: { scopes?: string[]; scope?: string; selected?: boolean },\n): void => {\n emits('update:selectedScopes', {\n id: Object.keys(selectedSecuritySchemas),\n name,\n ...event,\n })\n}\n\n/** Handles scope-definition upserts (add / rename / description change) */\nconst handleScopeUpsert = (\n name: string,\n event: Omit<ApiReferenceEvents['auth:upsert:scopes'], 'name'>,\n): void => {\n emits('upsert:scope', { ...event, name })\n}\n\n/** Handles scope-definition deletes */\nconst handleScopeDelete = (\n name: string,\n event: Omit<ApiReferenceEvents['auth:delete:scopes'], 'name'>,\n): void => {\n emits('delete:scope', { ...event, name })\n}\n\n/**\n * Computes dynamic classes for OAuth2 flow tabs based on active state.\n */\nconst getFlowTabClasses = (flowKey: string, index: number): string => {\n const baseClasses =\n 'floating-bg text-c-3 relative cursor-pointer border-b border-transparent py-1 text-base font-medium'\n const activeClasses = '!text-c-1 !rounded-none border-b !border-current'\n\n return isFlowActive(flowKey, index)\n ? `${baseClasses} ${activeClasses} ${isStatic ? 'opacity-100' : ''}`\n : baseClasses\n}\n\n/**\n * OAuth2 token-acquisition target (an oauth2 scheme with an interactive grant) sourced from\n * the merged schemes. When the active scheme is HTTP bearer, this powers the inline\n * \"Authorize via OAuth2\" shortcut: the flow's bearer token is written onto the bearer scheme,\n * so the panel never switches to oauth2.\n *\n * The shortcut is purely a convenience, so it is offered for any interactive oauth2 scheme —\n * including one that is also independently selectable in the dropdown (e.g. Scalar Galaxy's\n * `oAuth2`). Whether that oauth2 scheme is *hidden* from the dropdown is a separate decision made\n * in the selector; here we only surface the shortcut.\n */\nconst oauth2Target = computed(() => getOauth2AcquisitionTarget(securitySchemes))\n\n/** Resolved oauth2 scheme object, for embedding its config form behind the gear. */\nconst oauth2Scheme = computed(() =>\n oauth2Target.value\n ? getResolvedRef(securitySchemes[oauth2Target.value.name])\n : undefined,\n)\n\nconst acquisitionLoader = useLoadingState()\nconst { toast } = useToasts()\nconst configModal = useModal()\n/** Bearer scheme that opened the config modal, so its Authorize callback targets it. */\nconst configBearerName = ref<string | undefined>()\n\n/** Runs the OAuth2 flow and writes the resulting bearer token onto the bearer scheme. */\nconst handleAcquisitionAuthorize = async (\n bearerName: string,\n): Promise<void> => {\n const target = oauth2Target.value\n if (!target || acquisitionLoader.isLoading) {\n return\n }\n acquisitionLoader.start()\n const [error] = await runOAuth2Authorize({\n eventBus,\n bearerSchemeName: bearerName,\n oauth2Name: target.name,\n flows: target.flows,\n flowType: target.flowType,\n scopes: target.scopes,\n server,\n proxyUrl,\n environment,\n options,\n })\n await acquisitionLoader.clear()\n if (error) {\n toast(error?.message ?? 'Failed to authorize', 'error')\n }\n}\n\n/** Refreshes the OAuth2 token and rewrites it onto the bearer scheme. */\nconst handleAcquisitionRefresh = async (bearerName: string): Promise<void> => {\n const target = oauth2Target.value\n // Only the authorization-code flow carries a refresh token; implicit can't be refreshed.\n if (\n !target ||\n target.flowType !== 'authorizationCode' ||\n acquisitionLoader.isLoading\n ) {\n return\n }\n acquisitionLoader.start()\n const [error, tokens] = await refreshOauth2Token(\n target.flows,\n target.flowType,\n proxyUrl,\n server,\n getEnvironmentVariables(environment),\n options?.customFetch,\n )\n await acquisitionLoader.clear()\n if (tokens?.accessToken) {\n storeOAuth2Tokens(eventBus, {\n bearerSchemeName: bearerName,\n oauth2Name: target.name,\n flowType: target.flowType,\n tokens,\n })\n } else if (error) {\n toast(error?.message ?? 'Failed to refresh', 'error')\n }\n}\n\nconst openAcquisitionConfig = (bearerName: string): void => {\n configBearerName.value = bearerName\n configModal.show()\n}\n\n/** Closes the config modal and runs Authorize against the bearer scheme that opened it. */\nconst handleConfigAuthorize = (): void => {\n const bearerName = configBearerName.value\n configModal.hide()\n if (bearerName) {\n void handleAcquisitionAuthorize(bearerName)\n }\n}\n</script>\n<template>\n <template\n v-for=\"{ scheme, name, scopes, visibleFlowKeys } in security\"\n :key=\"name\">\n <!--\n Header row for AND'ed schemes: label (bold) and description (rich text) are\n combined.\n -->\n <DataTableRow v-if=\"hasMultipleSchemes && scheme\">\n <DataTableCell\n :aria-label=\"generateLabel(name, scheme)\"\n class=\"max-h-[auto]\">\n <div class=\"bg-b-1 min-w-0 flex-1 px-3 py-1.25\">\n <p class=\"text-c-1 leading-5.5 font-medium\">\n {{ generateLabel(name, scheme) }}\n </p>\n <ScalarMarkdownSummary\n v-if=\"scheme.description\"\n class=\"auth-description text-c-2 w-full\"\n :value=\"scheme.description\" />\n </div>\n </DataTableCell>\n </DataTableRow>\n\n <!-- Description: shown for single auth schemes with descriptions -->\n <DataTableRow v-if=\"scheme?.description && !hasMultipleSchemes\">\n <DataTableCell\n :aria-label=\"scheme.description\"\n class=\"max-h-[auto]\">\n <ScalarMarkdownSummary\n class=\"auth-description bg-b-1 text-c-2 min-w-0 flex-1 px-3 py-1.25\"\n :value=\"scheme.description\" />\n </DataTableCell>\n </DataTableRow>\n\n <!-- HTTP Authentication -->\n <template v-if=\"scheme?.type === 'http'\">\n <!-- Bearer Token -->\n <DataTableRow v-if=\"scheme.scheme === 'bearer'\">\n <RequestAuthDataTableInput\n :containerClass=\"getStaticBorderClass()\"\n :environment\n :modelValue=\"scheme['x-scalar-secret-token']\"\n placeholder=\"Token\"\n type=\"password\"\n @update:modelValue=\"\n (v) => handleHttpSecretsUpdate({ 'x-scalar-secret-token': v }, name)\n \">\n Bearer Token\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <!-- OAuth2 token-acquisition shortcut (shown when an interactive oauth2 flow exists) -->\n <DataTableRow v-if=\"scheme.scheme === 'bearer' && oauth2Target\">\n <div class=\"flex h-8 items-center gap-2 border-t px-3\">\n <span class=\"text-c-3 mr-auto text-xs\">Get a token</span>\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n :loader=\"acquisitionLoader\"\n size=\"sm\"\n type=\"button\"\n variant=\"outlined\"\n @click=\"handleAcquisitionAuthorize(name)\">\n Authorize via {{ oauth2Target.name }}\n </ScalarButton>\n <ScalarButton\n v-if=\"\n scheme['x-scalar-secret-token'] &&\n oauth2Target.flowType === 'authorizationCode'\n \"\n class=\"p-0 px-2 py-0.5\"\n :disabled=\"acquisitionLoader.isLoading\"\n size=\"sm\"\n type=\"button\"\n variant=\"outlined\"\n @click=\"handleAcquisitionRefresh(name)\">\n Refresh\n </ScalarButton>\n <ScalarIconButton\n :icon=\"ScalarIconGear\"\n :label=\"`Configure ${oauth2Target.name}`\"\n size=\"xs\"\n @click=\"openAcquisitionConfig(name)\" />\n </div>\n </DataTableRow>\n\n <!-- HTTP Basic Authentication -->\n <template v-else-if=\"scheme?.scheme === 'basic'\">\n <DataTableRow>\n <RequestAuthDataTableInput\n class=\"text-c-2\"\n :environment\n :modelValue=\"scheme['x-scalar-secret-username']\"\n placeholder=\"janedoe\"\n required\n @update:modelValue=\"\n (v) =>\n handleHttpSecretsUpdate({ 'x-scalar-secret-username': v }, name)\n \">\n Username\n </RequestAuthDataTableInput>\n </DataTableRow>\n <DataTableRow>\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"scheme['x-scalar-secret-password']\"\n placeholder=\"********\"\n type=\"password\"\n @update:modelValue=\"\n (v) =>\n handleHttpSecretsUpdate({ 'x-scalar-secret-password': v }, name)\n \">\n Password\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n </template>\n\n <!-- API Key Authentication -->\n <template v-else-if=\"scheme?.type === 'apiKey'\">\n <DataTableRow v-if=\"apiKeyHasName(scheme)\">\n <RequestAuthDataTableInput\n :containerClass=\"getStaticBorderClass()\"\n :environment\n :modelValue=\"scheme.name ?? ''\"\n placeholder=\"api-key\"\n @update:modelValue=\"\n (v) => handleApiKeySecuritySchemeUpdate({ name: v }, name)\n \">\n Name\n </RequestAuthDataTableInput>\n </DataTableRow>\n <DataTableRow>\n <RequestAuthDataTableInput\n :containerClass=\"\n apiKeyHasName(scheme) ? undefined : getStaticBorderClass()\n \"\n :environment\n :modelValue=\"scheme['x-scalar-secret-token']\"\n placeholder=\"QUxMIFlPVVIgQkFTRSBBUkUgQkVMT05HIFRPIFVT\"\n type=\"password\"\n @update:modelValue=\"\n (v) =>\n handleApiKeySecretsUpdate({ 'x-scalar-secret-token': v }, name)\n \">\n Value\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n\n <!-- OAuth 2.0 / OpenID Connect Authentication -->\n <template\n v-else-if=\"scheme?.type === 'oauth2' || scheme?.type === 'openIdConnect'\">\n <!-- OpenID Connect -->\n <OpenIDConnect\n v-if=\"scheme?.type === 'openIdConnect' && !visibleFlowKeys.length\"\n :customFetch=\"options?.customFetch\"\n :environment\n :eventBus\n :getStaticBorderClass\n :name\n :proxyUrl\n :scheme />\n\n <!-- Flow selector tabs: shown when multiple visible flows are available -->\n <DataTableRow v-if=\"visibleFlowKeys.length > 1\">\n <div class=\"flex min-h-8 border-t text-base\">\n <div class=\"flex h-8 max-w-full gap-2.5 overflow-x-auto px-3\">\n <button\n v-for=\"(key, ind) in visibleFlowKeys\"\n :key=\"key\"\n :class=\"getFlowTabClasses(key, ind)\"\n type=\"button\"\n @click=\"setActiveFlow(key)\">\n <span class=\"relative z-10\">{{ key }}</span>\n </button>\n </div>\n </div>\n </DataTableRow>\n\n <!-- OAuth2 flow configuration -->\n <template\n v-for=\"(key, ind) in visibleFlowKeys\"\n :key=\"key\">\n <OAuth2\n v-if=\"scheme.flows && isFlowActive(key, ind)\"\n :environment\n :eventBus\n :flows=\"scheme.flows\"\n :name\n :options\n :proxyUrl\n :scheme\n :selectedScopes=\"scopes\"\n :server\n :type=\"key\"\n @delete:scope=\"(event) => handleScopeDelete(name, event)\"\n @update:selectedScopes=\"(event) => handleScopesUpdate(name, event)\"\n @upsert:scope=\"(event) => handleScopeUpsert(name, event)\" />\n </template>\n </template>\n\n <!-- Browser WebSocket connections cannot apply these broker credentials. -->\n <div\n v-else-if=\"\n scheme?.type === 'userPassword' ||\n scheme?.type === 'plain' ||\n scheme?.type === 'scramSha256' ||\n scheme?.type === 'scramSha512' ||\n scheme?.type === 'X509' ||\n scheme?.type === 'symmetricEncryption' ||\n scheme?.type === 'asymmetricEncryption' ||\n scheme?.type === 'gssapi'\n \"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n Credentials for this AsyncAPI security scheme are not sent by the browser\n client.\n </div>\n\n <!-- Mutual TLS credentials are chosen during the browser-managed TLS handshake. -->\n <div\n v-else-if=\"scheme?.type === 'mutualTLS'\"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n Mutual TLS authenticates with a client certificate presented during the\n TLS handshake, so there is nothing to enter here.\n </div>\n\n <!-- Scheme has a type we do not render inputs for -->\n <div\n v-else-if=\"getUnsupportedSchemeType(scheme)\"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n The <code>{{ getUnsupportedSchemeType(scheme) }}</code> security scheme\n type is not supported yet.\n </div>\n\n <!-- Scheme is missing type -->\n <div\n v-else\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n The security scheme is missing a type, please double check your\n {{ documentTypeLabel }} document or Authentication Configuration\n </div>\n </template>\n\n <!-- OAuth2 configuration modal (opened from the bearer scheme's gear) -->\n <ScalarModal\n v-if=\"oauth2Target && oauth2Scheme\"\n :state=\"configModal\"\n size=\"sm\"\n :title=\"`Configure ${oauth2Target.name}`\">\n <DataTable\n :columns=\"['']\"\n presentational>\n <OAuth2\n hideActions\n :environment\n :eventBus\n :flows=\"oauth2Target.flows\"\n :name=\"oauth2Target.name\"\n :options\n :proxyUrl\n :scheme=\"oauth2Scheme\"\n :selectedScopes=\"oauth2Target.scopes\"\n :server\n :type=\"oauth2Target.flowType\"\n @delete:scope=\"(event) => handleScopeDelete(oauth2Target!.name, event)\"\n @update:selectedScopes=\"\n (event) => handleScopesUpdate(oauth2Target!.name, event)\n \"\n @upsert:scope=\"\n (event) => handleScopeUpsert(oauth2Target!.name, event)\n \" />\n </DataTable>\n <div class=\"flex h-8 items-center justify-end gap-2 border-t\">\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"configModal.hide()\">\n Cancel\n </ScalarButton>\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n :loader=\"acquisitionLoader\"\n size=\"sm\"\n @click=\"handleConfigAuthorize\">\n Authorize\n </ScalarButton>\n </div>\n </ScalarModal>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"RequestAuthTab.vue.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components/button'\nimport { ScalarIconButton } from '@scalar/components/icon-button'\nimport { useLoadingState } from '@scalar/components/loading'\nimport { ScalarMarkdownSummary } from '@scalar/components/markdown'\nimport { ScalarModal, useModal } from '@scalar/components/modal'\nimport { ScalarIconGear } from '@scalar/icons'\nimport { useToasts } from '@scalar/use-toasts'\nimport type {\n SecretsApiKey,\n SecretsHttp,\n} from '@scalar/workspace-store/entities/auth'\nimport type {\n ApiReferenceEvents,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport {\n getEnvironmentVariables,\n type MergedSecuritySchemes,\n type OAuthFlowsObjectSecret,\n type SecuritySchemeObjectSecret,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { getDocumentTypeLabel } from '@scalar/workspace-store/schemas/type-guards'\nimport type {\n ApiKeyObject,\n SecurityRequirementObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { capitalize, computed, ref } from 'vue'\n\nimport { refreshOauth2Token } from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth'\nimport { getVisibleOrderedFlowKeys } from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth-flows'\nimport {\n runOAuth2Authorize,\n storeOAuth2Tokens,\n} from '@/v2/blocks/scalar-auth-selector-block/helpers/run-oauth2-authorize'\nimport { getOauth2AcquisitionTarget } from '@/v2/blocks/scalar-auth-selector-block/helpers/security-scheme'\nimport {\n DataTable,\n DataTableCell,\n DataTableRow,\n} from '@/v2/components/data-table'\n\nimport OAuth2, { type OAuth2Options } from './OAuth2.vue'\nimport OAuth2Metadata from './OAuth2Metadata.vue'\nimport OpenIDConnect from './OpenIDConnect.vue'\nimport RequestAuthDataTableInput from './RequestAuthDataTableInput.vue'\n\ntype SecurityItem = {\n scheme: SecuritySchemeObjectSecret | undefined\n name: string\n scopes: string[]\n /** Ordered, non-hidden oauth2/openIdConnect flow keys for this scheme (empty for other types). */\n visibleFlowKeys: (keyof OAuthFlowsObjectSecret)[]\n}\n\nconst {\n environment,\n isStatic,\n proxyUrl,\n selectedSecuritySchemas,\n securitySchemes,\n server,\n eventBus,\n options,\n documentType = 'openapi',\n} = defineProps<{\n /** Current environment configuration */\n environment: XScalarEnvironment\n /** Controls the display of certain borders which are used when we are non-collapsible */\n isStatic: boolean\n /** Proxy URL */\n proxyUrl: string\n /** Selected security schemes*/\n selectedSecuritySchemas: SecurityRequirementObject\n /** Merged security schemes from the document and the config together with the auth store secrets */\n securitySchemes: MergedSecuritySchemes\n /** Current server configuration */\n server: ServerObject | null\n /** Event bus for authentication updates */\n eventBus: WorkspaceEventBus\n /** Any config options required for the OAuth2 flow */\n options?: OAuth2Options\n /** Type of the document the schemes belong to, used to label the missing-type warning */\n documentType?: 'openapi' | 'asyncapi'\n}>()\n\n/**\n * Human-readable name of the document type.\n * Used in the missing-type warning so it points at the correct document\n * (e.g. \"AsyncAPI\") instead of always naming OpenAPI.\n */\nconst documentTypeLabel = computed<string>(() =>\n getDocumentTypeLabel(documentType),\n)\n\nconst emits = defineEmits<{\n (\n e: 'update:selectedScopes',\n payload: Omit<ApiReferenceEvents['auth:update:selected-scopes'], 'meta'>,\n ): void\n (e: 'upsert:scope', payload: ApiReferenceEvents['auth:upsert:scopes']): void\n (e: 'delete:scope', payload: ApiReferenceEvents['auth:delete:scopes']): void\n}>()\n\n/**\n * Resolves security schemes from the OpenAPI document and combines them with their selected scopes.\n * Each item includes the scheme definition, name, and associated scopes.\n */\nconst security = computed<SecurityItem[]>(() =>\n Object.entries(selectedSecuritySchemas).map(([name, scopes = []]) => {\n const scheme = getResolvedRef(securitySchemes[name])\n return {\n scheme,\n name,\n scopes,\n // Compute the visible, ordered flow keys once per scheme so the tabs, the label, and the\n // active-flow tracking all agree on the same set (and we do not filter + sort on every access).\n visibleFlowKeys:\n scheme?.type === 'oauth2' || scheme?.type === 'openIdConnect'\n ? getVisibleOrderedFlowKeys(scheme.flows)\n : [],\n }\n }),\n)\n\n/** Tracks which OAuth2 flow is currently active when multiple flows are available. */\nconst activeFlow = ref<string>('')\n\n/**\n * Keeps the selected flow in sync with the currently visible flow keys. Validating against the\n * visible set (not every declared flow) means a selection that becomes hidden — e.g. the document\n * is updated to mark the active flow with `x-scalar-ignore` — resets, so the default (first visible)\n * flow activates instead of leaving no tab selected.\n */\nconst selectedFlow = computed<string>(() => {\n const visibleFlowKeys = security.value.flatMap((item) => item.visibleFlowKeys)\n\n return visibleFlowKeys.some((key) => key === activeFlow.value)\n ? activeFlow.value\n : ''\n})\n\nconst setActiveFlow = (flow: string): void => {\n activeFlow.value = flow\n}\n\n/** Determines if multiple auth schemes are configured, which affects the UI layout. */\nconst hasMultipleSchemes = computed<boolean>(() => security.value.length > 1)\n\n/**\n * Generates a human-readable label for the security scheme.\n * Intentionally omits the description here — it is rendered separately as\n * rich text via ScalarMarkdownSummary so markdown formatting is preserved.\n */\nconst generateLabel = (\n name: string,\n scheme: SecuritySchemeObjectSecret,\n): string => {\n const capitalizedName = capitalize(name)\n\n switch (scheme.type) {\n case 'apiKey':\n return `${capitalizedName}: ${scheme.in}`\n\n case 'openIdConnect':\n case 'oauth2': {\n const firstFlow = getVisibleOrderedFlowKeys(scheme.flows)[0]\n const currentFlow = selectedFlow.value || firstFlow\n if (!currentFlow) {\n return capitalizedName\n }\n return `${capitalizedName}: ${currentFlow}`\n }\n\n case 'http':\n return `${capitalizedName}: ${scheme.scheme}`\n\n default:\n return capitalizedName\n }\n}\n\n/**\n * Whether an API key scheme exposes an editable parameter name.\n *\n * OpenAPI `apiKey` and AsyncAPI `httpApiKey` (normalized to `apiKey`) name a query/header/cookie\n * parameter, so the Name input is shown. AsyncAPI `apiKey` places the key in the broker `user` or\n * `password` slot and has no parameter name, so the Name input is hidden and only the value is asked for.\n */\nconst apiKeyHasName = (scheme: { in?: string }): boolean =>\n scheme.in !== 'user' && scheme.in !== 'password'\n\n/**\n * The scheme's type when it is one we do not render inputs for (a type outside both the OpenAPI\n * and AsyncAPI security scheme unions). Read through a helper so the fallback template branch,\n * where the scheme type is narrowed to `never` after the supported cases, can still surface the type.\n */\nconst getUnsupportedSchemeType = (\n scheme: SecurityItem['scheme'],\n): string | undefined => scheme?.type\n\n/**\n * Determines if an OAuth2 flow tab should be active.\n * The first flow is active by default if no flow is explicitly selected.\n */\nconst isFlowActive = (flowKey: string, index: number): boolean =>\n selectedFlow.value === flowKey || (index === 0 && !selectedFlow.value)\n\n/** Computes the container class for static display mode. */\nconst getStaticBorderClass = (): string | false => isStatic && 'border-t'\n\nconst handleHttpSecretsUpdate = (\n payload: Omit<Partial<SecretsHttp>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: { type: 'http', ...payload },\n name,\n })\n\nconst handleApiKeySecretsUpdate = (\n payload: Omit<Partial<SecretsApiKey>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: { type: 'apiKey', ...payload },\n name,\n })\n\nconst handleApiKeySecuritySchemeUpdate = (\n payload: Omit<Partial<ApiKeyObject>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme', {\n payload: { type: 'apiKey', ...payload },\n name,\n })\n\n/** Handles scope selection updates for OAuth2 */\nconst handleScopesUpdate = (\n name: string,\n event: { scopes?: string[]; scope?: string; selected?: boolean },\n): void => {\n emits('update:selectedScopes', {\n id: Object.keys(selectedSecuritySchemas),\n name,\n ...event,\n })\n}\n\n/** Handles scope-definition upserts (add / rename / description change) */\nconst handleScopeUpsert = (\n name: string,\n event: Omit<ApiReferenceEvents['auth:upsert:scopes'], 'name'>,\n): void => {\n emits('upsert:scope', { ...event, name })\n}\n\n/** Handles scope-definition deletes */\nconst handleScopeDelete = (\n name: string,\n event: Omit<ApiReferenceEvents['auth:delete:scopes'], 'name'>,\n): void => {\n emits('delete:scope', { ...event, name })\n}\n\n/**\n * Computes dynamic classes for OAuth2 flow tabs based on active state.\n */\nconst getFlowTabClasses = (flowKey: string, index: number): string => {\n const baseClasses =\n 'floating-bg text-c-3 relative cursor-pointer border-b border-transparent py-1 text-base font-medium'\n const activeClasses = '!text-c-1 !rounded-none border-b !border-current'\n\n return isFlowActive(flowKey, index)\n ? `${baseClasses} ${activeClasses} ${isStatic ? 'opacity-100' : ''}`\n : baseClasses\n}\n\n/**\n * OAuth2 token-acquisition target (an oauth2 scheme with an interactive grant) sourced from\n * the merged schemes. When the active scheme is HTTP bearer, this powers the inline\n * \"Authorize via OAuth2\" shortcut: the flow's bearer token is written onto the bearer scheme,\n * so the panel never switches to oauth2.\n *\n * The shortcut is purely a convenience, so it is offered for any interactive oauth2 scheme —\n * including one that is also independently selectable in the dropdown (e.g. Scalar Galaxy's\n * `oAuth2`). Whether that oauth2 scheme is *hidden* from the dropdown is a separate decision made\n * in the selector; here we only surface the shortcut.\n */\nconst oauth2Target = computed(() => getOauth2AcquisitionTarget(securitySchemes))\n\n/** Resolved oauth2 scheme object, for embedding its config form behind the gear. */\nconst oauth2Scheme = computed(() =>\n oauth2Target.value\n ? getResolvedRef(securitySchemes[oauth2Target.value.name])\n : undefined,\n)\n\nconst acquisitionLoader = useLoadingState()\nconst { toast } = useToasts()\nconst configModal = useModal()\n/** Bearer scheme that opened the config modal, so its Authorize callback targets it. */\nconst configBearerName = ref<string | undefined>()\n\n/** Runs the OAuth2 flow and writes the resulting bearer token onto the bearer scheme. */\nconst handleAcquisitionAuthorize = async (\n bearerName: string,\n): Promise<void> => {\n const target = oauth2Target.value\n if (!target || acquisitionLoader.isLoading) {\n return\n }\n acquisitionLoader.start()\n const [error] = await runOAuth2Authorize({\n eventBus,\n bearerSchemeName: bearerName,\n oauth2Name: target.name,\n flows: target.flows,\n flowType: target.flowType,\n scopes: target.scopes,\n server,\n proxyUrl,\n environment,\n options,\n })\n await acquisitionLoader.clear()\n if (error) {\n toast(error?.message ?? 'Failed to authorize', 'error')\n }\n}\n\n/** Refreshes the OAuth2 token and rewrites it onto the bearer scheme. */\nconst handleAcquisitionRefresh = async (bearerName: string): Promise<void> => {\n const target = oauth2Target.value\n // Only the authorization-code flow carries a refresh token; implicit can't be refreshed.\n if (\n !target ||\n target.flowType !== 'authorizationCode' ||\n acquisitionLoader.isLoading\n ) {\n return\n }\n acquisitionLoader.start()\n const [error, tokens] = await refreshOauth2Token(\n target.flows,\n target.flowType,\n proxyUrl,\n server,\n getEnvironmentVariables(environment),\n options?.customFetch,\n )\n await acquisitionLoader.clear()\n if (tokens?.accessToken) {\n storeOAuth2Tokens(eventBus, {\n bearerSchemeName: bearerName,\n oauth2Name: target.name,\n flowType: target.flowType,\n tokens,\n })\n } else if (error) {\n toast(error?.message ?? 'Failed to refresh', 'error')\n }\n}\n\nconst openAcquisitionConfig = (bearerName: string): void => {\n configBearerName.value = bearerName\n configModal.show()\n}\n\n/** Closes the config modal and runs Authorize against the bearer scheme that opened it. */\nconst handleConfigAuthorize = (): void => {\n const bearerName = configBearerName.value\n configModal.hide()\n if (bearerName) {\n void handleAcquisitionAuthorize(bearerName)\n }\n}\n</script>\n<template>\n <template\n v-for=\"{ scheme, name, scopes, visibleFlowKeys } in security\"\n :key=\"name\">\n <!--\n Header row for AND'ed schemes: label (bold) and description (rich text) are\n combined.\n -->\n <DataTableRow v-if=\"hasMultipleSchemes && scheme\">\n <DataTableCell\n :aria-label=\"generateLabel(name, scheme)\"\n class=\"max-h-[auto]\">\n <div class=\"bg-b-1 min-w-0 flex-1 px-3 py-1.25\">\n <p class=\"text-c-1 leading-5.5 font-medium\">\n {{ generateLabel(name, scheme) }}\n </p>\n <ScalarMarkdownSummary\n v-if=\"scheme.description\"\n class=\"auth-description text-c-2 w-full\"\n :value=\"scheme.description\" />\n </div>\n </DataTableCell>\n </DataTableRow>\n\n <!-- Description: shown for single auth schemes with descriptions -->\n <DataTableRow v-if=\"scheme?.description && !hasMultipleSchemes\">\n <DataTableCell\n :aria-label=\"scheme.description\"\n class=\"max-h-[auto]\">\n <ScalarMarkdownSummary\n class=\"auth-description bg-b-1 text-c-2 min-w-0 flex-1 px-3 py-1.25\"\n :value=\"scheme.description\" />\n </DataTableCell>\n </DataTableRow>\n\n <!-- HTTP Authentication -->\n <template v-if=\"scheme?.type === 'http'\">\n <!-- Bearer Token -->\n <DataTableRow v-if=\"scheme.scheme === 'bearer'\">\n <RequestAuthDataTableInput\n :containerClass=\"getStaticBorderClass()\"\n :environment\n :modelValue=\"scheme['x-scalar-secret-token']\"\n placeholder=\"Token\"\n type=\"password\"\n @update:modelValue=\"\n (v) => handleHttpSecretsUpdate({ 'x-scalar-secret-token': v }, name)\n \">\n Bearer Token\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <!-- OAuth2 token-acquisition shortcut (shown when an interactive oauth2 flow exists) -->\n <DataTableRow v-if=\"scheme.scheme === 'bearer' && oauth2Target\">\n <div class=\"flex h-8 items-center gap-2 border-t px-3\">\n <span class=\"text-c-3 mr-auto text-xs\">Get a token</span>\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n :loader=\"acquisitionLoader\"\n size=\"sm\"\n type=\"button\"\n variant=\"outlined\"\n @click=\"handleAcquisitionAuthorize(name)\">\n Authorize via {{ oauth2Target.name }}\n </ScalarButton>\n <ScalarButton\n v-if=\"\n scheme['x-scalar-secret-token'] &&\n oauth2Target.flowType === 'authorizationCode'\n \"\n class=\"p-0 px-2 py-0.5\"\n :disabled=\"acquisitionLoader.isLoading\"\n size=\"sm\"\n type=\"button\"\n variant=\"outlined\"\n @click=\"handleAcquisitionRefresh(name)\">\n Refresh\n </ScalarButton>\n <ScalarIconButton\n :icon=\"ScalarIconGear\"\n :label=\"`Configure ${oauth2Target.name}`\"\n size=\"xs\"\n @click=\"openAcquisitionConfig(name)\" />\n </div>\n </DataTableRow>\n\n <!-- HTTP Basic Authentication -->\n <template v-else-if=\"scheme?.scheme === 'basic'\">\n <DataTableRow>\n <RequestAuthDataTableInput\n class=\"text-c-2\"\n :environment\n :modelValue=\"scheme['x-scalar-secret-username']\"\n placeholder=\"janedoe\"\n required\n @update:modelValue=\"\n (v) =>\n handleHttpSecretsUpdate({ 'x-scalar-secret-username': v }, name)\n \">\n Username\n </RequestAuthDataTableInput>\n </DataTableRow>\n <DataTableRow>\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"scheme['x-scalar-secret-password']\"\n placeholder=\"********\"\n type=\"password\"\n @update:modelValue=\"\n (v) =>\n handleHttpSecretsUpdate({ 'x-scalar-secret-password': v }, name)\n \">\n Password\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n </template>\n\n <!-- API Key Authentication -->\n <template v-else-if=\"scheme?.type === 'apiKey'\">\n <DataTableRow v-if=\"apiKeyHasName(scheme)\">\n <RequestAuthDataTableInput\n :containerClass=\"getStaticBorderClass()\"\n :environment\n :modelValue=\"scheme.name ?? ''\"\n placeholder=\"api-key\"\n @update:modelValue=\"\n (v) => handleApiKeySecuritySchemeUpdate({ name: v }, name)\n \">\n Name\n </RequestAuthDataTableInput>\n </DataTableRow>\n <DataTableRow>\n <RequestAuthDataTableInput\n :containerClass=\"\n apiKeyHasName(scheme) ? undefined : getStaticBorderClass()\n \"\n :environment\n :modelValue=\"scheme['x-scalar-secret-token']\"\n placeholder=\"QUxMIFlPVVIgQkFTRSBBUkUgQkVMT05HIFRPIFVT\"\n type=\"password\"\n @update:modelValue=\"\n (v) =>\n handleApiKeySecretsUpdate({ 'x-scalar-secret-token': v }, name)\n \">\n Value\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n\n <!-- OAuth 2.0 / OpenID Connect Authentication -->\n <template\n v-else-if=\"scheme?.type === 'oauth2' || scheme?.type === 'openIdConnect'\">\n <OAuth2Metadata\n v-if=\"\n scheme.type === 'oauth2' && (!isStatic || scheme.oauth2MetadataUrl)\n \"\n :customFetch=\"options?.customFetch\"\n :environment\n :eventBus\n :name\n :proxyUrl\n :scheme />\n\n <!-- OpenID Connect -->\n <OpenIDConnect\n v-if=\"scheme?.type === 'openIdConnect' && !visibleFlowKeys.length\"\n :customFetch=\"options?.customFetch\"\n :environment\n :eventBus\n :getStaticBorderClass\n :name\n :proxyUrl\n :scheme />\n\n <!-- Flow selector tabs: shown when multiple visible flows are available -->\n <DataTableRow v-if=\"visibleFlowKeys.length > 1\">\n <div class=\"flex min-h-8 border-t text-base\">\n <div class=\"flex h-8 max-w-full gap-2.5 overflow-x-auto px-3\">\n <button\n v-for=\"(key, ind) in visibleFlowKeys\"\n :key=\"key\"\n :class=\"getFlowTabClasses(key, ind)\"\n type=\"button\"\n @click=\"setActiveFlow(key)\">\n <span class=\"relative z-10\">{{ key }}</span>\n </button>\n </div>\n </div>\n </DataTableRow>\n\n <!-- OAuth2 flow configuration -->\n <template\n v-for=\"(key, ind) in visibleFlowKeys\"\n :key=\"key\">\n <OAuth2\n v-if=\"scheme.flows && isFlowActive(key, ind)\"\n :environment\n :eventBus\n :flows=\"scheme.flows\"\n :name\n :options\n :proxyUrl\n :scheme\n :selectedScopes=\"scopes\"\n :server\n :type=\"key\"\n @delete:scope=\"(event) => handleScopeDelete(name, event)\"\n @update:selectedScopes=\"(event) => handleScopesUpdate(name, event)\"\n @upsert:scope=\"(event) => handleScopeUpsert(name, event)\" />\n </template>\n </template>\n\n <!-- Browser WebSocket connections cannot apply these broker credentials. -->\n <div\n v-else-if=\"\n scheme?.type === 'userPassword' ||\n scheme?.type === 'plain' ||\n scheme?.type === 'scramSha256' ||\n scheme?.type === 'scramSha512' ||\n scheme?.type === 'X509' ||\n scheme?.type === 'symmetricEncryption' ||\n scheme?.type === 'asymmetricEncryption' ||\n scheme?.type === 'gssapi'\n \"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n Credentials for this AsyncAPI security scheme are not sent by the browser\n client.\n </div>\n\n <!-- Mutual TLS credentials are chosen during the browser-managed TLS handshake. -->\n <div\n v-else-if=\"scheme?.type === 'mutualTLS'\"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n Mutual TLS authenticates with a client certificate presented during the\n TLS handshake, so there is nothing to enter here.\n </div>\n\n <!-- Scheme has a type we do not render inputs for -->\n <div\n v-else-if=\"getUnsupportedSchemeType(scheme)\"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n The <code>{{ getUnsupportedSchemeType(scheme) }}</code> security scheme\n type is not supported yet.\n </div>\n\n <!-- Scheme is missing type -->\n <div\n v-else\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n The security scheme is missing a type, please double check your\n {{ documentTypeLabel }} document or Authentication Configuration\n </div>\n </template>\n\n <!-- OAuth2 configuration modal (opened from the bearer scheme's gear) -->\n <ScalarModal\n v-if=\"oauth2Target && oauth2Scheme\"\n :state=\"configModal\"\n size=\"sm\"\n :title=\"`Configure ${oauth2Target.name}`\">\n <DataTable\n :columns=\"['']\"\n presentational>\n <OAuth2\n hideActions\n :environment\n :eventBus\n :flows=\"oauth2Target.flows\"\n :name=\"oauth2Target.name\"\n :options\n :proxyUrl\n :scheme=\"oauth2Scheme\"\n :selectedScopes=\"oauth2Target.scopes\"\n :server\n :type=\"oauth2Target.flowType\"\n @delete:scope=\"(event) => handleScopeDelete(oauth2Target!.name, event)\"\n @update:selectedScopes=\"\n (event) => handleScopesUpdate(oauth2Target!.name, event)\n \"\n @upsert:scope=\"\n (event) => handleScopeUpsert(oauth2Target!.name, event)\n \" />\n </DataTable>\n <div class=\"flex h-8 items-center justify-end gap-2 border-t\">\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"configModal.hide()\">\n Cancel\n </ScalarButton>\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n :loader=\"acquisitionLoader\"\n size=\"sm\"\n @click=\"handleConfigAuthorize\">\n Authorize\n </ScalarButton>\n </div>\n </ScalarModal>\n</template>\n"],"mappings":""}
|
|
@@ -7,6 +7,7 @@ import { getVisibleOrderedFlowKeys } from "../helpers/oauth-flows.js";
|
|
|
7
7
|
import { runOAuth2Authorize, storeOAuth2Tokens } from "../helpers/run-oauth2-authorize.js";
|
|
8
8
|
import RequestAuthDataTableInput_default from "./RequestAuthDataTableInput.vue.js";
|
|
9
9
|
import OAuth2_default from "./OAuth2.vue.js";
|
|
10
|
+
import OAuth2Metadata_default from "./OAuth2Metadata.vue.js";
|
|
10
11
|
import OpenIDConnect_default from "./OpenIDConnect.vue.js";
|
|
11
12
|
import { Fragment, capitalize, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, openBlock, ref, renderList, toDisplayString, unref, withCtx } from "vue";
|
|
12
13
|
import { ScalarButton } from "@scalar/components/button";
|
|
@@ -409,11 +410,27 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
|
|
|
409
410
|
])]),
|
|
410
411
|
_: 2
|
|
411
412
|
}, 1024)], 64)) : scheme?.type === "oauth2" || scheme?.type === "openIdConnect" ? (openBlock(), createElementBlock(Fragment, { key: 4 }, [
|
|
412
|
-
scheme
|
|
413
|
+
scheme.type === "oauth2" && (!__props.isStatic || scheme.oauth2MetadataUrl) ? (openBlock(), createBlock(OAuth2Metadata_default, {
|
|
413
414
|
key: 0,
|
|
414
415
|
customFetch: __props.options?.customFetch,
|
|
415
416
|
environment: __props.environment,
|
|
416
417
|
eventBus: __props.eventBus,
|
|
418
|
+
name,
|
|
419
|
+
proxyUrl: __props.proxyUrl,
|
|
420
|
+
scheme
|
|
421
|
+
}, null, 8, [
|
|
422
|
+
"customFetch",
|
|
423
|
+
"environment",
|
|
424
|
+
"eventBus",
|
|
425
|
+
"name",
|
|
426
|
+
"proxyUrl",
|
|
427
|
+
"scheme"
|
|
428
|
+
])) : createCommentVNode("", true),
|
|
429
|
+
scheme?.type === "openIdConnect" && !visibleFlowKeys.length ? (openBlock(), createBlock(OpenIDConnect_default, {
|
|
430
|
+
key: 1,
|
|
431
|
+
customFetch: __props.options?.customFetch,
|
|
432
|
+
environment: __props.environment,
|
|
433
|
+
eventBus: __props.eventBus,
|
|
417
434
|
getStaticBorderClass,
|
|
418
435
|
name,
|
|
419
436
|
proxyUrl: __props.proxyUrl,
|
|
@@ -426,7 +443,7 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
|
|
|
426
443
|
"proxyUrl",
|
|
427
444
|
"scheme"
|
|
428
445
|
])) : createCommentVNode("", true),
|
|
429
|
-
visibleFlowKeys.length > 1 ? (openBlock(), createBlock(unref(DataTableRow_default), { key:
|
|
446
|
+
visibleFlowKeys.length > 1 ? (openBlock(), createBlock(unref(DataTableRow_default), { key: 2 }, {
|
|
430
447
|
default: withCtx(() => [createElementVNode("div", _hoisted_4, [createElementVNode("div", _hoisted_5, [(openBlock(true), createElementBlock(Fragment, null, renderList(visibleFlowKeys, (key, ind) => {
|
|
431
448
|
return openBlock(), createElementBlock("button", {
|
|
432
449
|
key,
|
package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.script.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RequestAuthTab.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components/button'\nimport { ScalarIconButton } from '@scalar/components/icon-button'\nimport { useLoadingState } from '@scalar/components/loading'\nimport { ScalarMarkdownSummary } from '@scalar/components/markdown'\nimport { ScalarModal, useModal } from '@scalar/components/modal'\nimport { ScalarIconGear } from '@scalar/icons'\nimport { useToasts } from '@scalar/use-toasts'\nimport type {\n SecretsApiKey,\n SecretsHttp,\n} from '@scalar/workspace-store/entities/auth'\nimport type {\n ApiReferenceEvents,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport {\n getEnvironmentVariables,\n type MergedSecuritySchemes,\n type OAuthFlowsObjectSecret,\n type SecuritySchemeObjectSecret,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { getDocumentTypeLabel } from '@scalar/workspace-store/schemas/type-guards'\nimport type {\n ApiKeyObject,\n SecurityRequirementObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { capitalize, computed, ref } from 'vue'\n\nimport { refreshOauth2Token } from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth'\nimport { getVisibleOrderedFlowKeys } from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth-flows'\nimport {\n runOAuth2Authorize,\n storeOAuth2Tokens,\n} from '@/v2/blocks/scalar-auth-selector-block/helpers/run-oauth2-authorize'\nimport { getOauth2AcquisitionTarget } from '@/v2/blocks/scalar-auth-selector-block/helpers/security-scheme'\nimport {\n DataTable,\n DataTableCell,\n DataTableRow,\n} from '@/v2/components/data-table'\n\nimport OAuth2, { type OAuth2Options } from './OAuth2.vue'\nimport OpenIDConnect from './OpenIDConnect.vue'\nimport RequestAuthDataTableInput from './RequestAuthDataTableInput.vue'\n\ntype SecurityItem = {\n scheme: SecuritySchemeObjectSecret | undefined\n name: string\n scopes: string[]\n /** Ordered, non-hidden oauth2/openIdConnect flow keys for this scheme (empty for other types). */\n visibleFlowKeys: (keyof OAuthFlowsObjectSecret)[]\n}\n\nconst {\n environment,\n isStatic,\n proxyUrl,\n selectedSecuritySchemas,\n securitySchemes,\n server,\n eventBus,\n options,\n documentType = 'openapi',\n} = defineProps<{\n /** Current environment configuration */\n environment: XScalarEnvironment\n /** Controls the display of certain borders which are used when we are non-collapsible */\n isStatic: boolean\n /** Proxy URL */\n proxyUrl: string\n /** Selected security schemes*/\n selectedSecuritySchemas: SecurityRequirementObject\n /** Merged security schemes from the document and the config together with the auth store secrets */\n securitySchemes: MergedSecuritySchemes\n /** Current server configuration */\n server: ServerObject | null\n /** Event bus for authentication updates */\n eventBus: WorkspaceEventBus\n /** Any config options required for the OAuth2 flow */\n options?: OAuth2Options\n /** Type of the document the schemes belong to, used to label the missing-type warning */\n documentType?: 'openapi' | 'asyncapi'\n}>()\n\n/**\n * Human-readable name of the document type.\n * Used in the missing-type warning so it points at the correct document\n * (e.g. \"AsyncAPI\") instead of always naming OpenAPI.\n */\nconst documentTypeLabel = computed<string>(() =>\n getDocumentTypeLabel(documentType),\n)\n\nconst emits = defineEmits<{\n (\n e: 'update:selectedScopes',\n payload: Omit<ApiReferenceEvents['auth:update:selected-scopes'], 'meta'>,\n ): void\n (e: 'upsert:scope', payload: ApiReferenceEvents['auth:upsert:scopes']): void\n (e: 'delete:scope', payload: ApiReferenceEvents['auth:delete:scopes']): void\n}>()\n\n/**\n * Resolves security schemes from the OpenAPI document and combines them with their selected scopes.\n * Each item includes the scheme definition, name, and associated scopes.\n */\nconst security = computed<SecurityItem[]>(() =>\n Object.entries(selectedSecuritySchemas).map(([name, scopes = []]) => {\n const scheme = getResolvedRef(securitySchemes[name])\n return {\n scheme,\n name,\n scopes,\n // Compute the visible, ordered flow keys once per scheme so the tabs, the label, and the\n // active-flow tracking all agree on the same set (and we do not filter + sort on every access).\n visibleFlowKeys:\n scheme?.type === 'oauth2' || scheme?.type === 'openIdConnect'\n ? getVisibleOrderedFlowKeys(scheme.flows)\n : [],\n }\n }),\n)\n\n/** Tracks which OAuth2 flow is currently active when multiple flows are available. */\nconst activeFlow = ref<string>('')\n\n/**\n * Keeps the selected flow in sync with the currently visible flow keys. Validating against the\n * visible set (not every declared flow) means a selection that becomes hidden — e.g. the document\n * is updated to mark the active flow with `x-scalar-ignore` — resets, so the default (first visible)\n * flow activates instead of leaving no tab selected.\n */\nconst selectedFlow = computed<string>(() => {\n const visibleFlowKeys = security.value.flatMap((item) => item.visibleFlowKeys)\n\n return visibleFlowKeys.some((key) => key === activeFlow.value)\n ? activeFlow.value\n : ''\n})\n\nconst setActiveFlow = (flow: string): void => {\n activeFlow.value = flow\n}\n\n/** Determines if multiple auth schemes are configured, which affects the UI layout. */\nconst hasMultipleSchemes = computed<boolean>(() => security.value.length > 1)\n\n/**\n * Generates a human-readable label for the security scheme.\n * Intentionally omits the description here — it is rendered separately as\n * rich text via ScalarMarkdownSummary so markdown formatting is preserved.\n */\nconst generateLabel = (\n name: string,\n scheme: SecuritySchemeObjectSecret,\n): string => {\n const capitalizedName = capitalize(name)\n\n switch (scheme.type) {\n case 'apiKey':\n return `${capitalizedName}: ${scheme.in}`\n\n case 'openIdConnect':\n case 'oauth2': {\n const firstFlow = getVisibleOrderedFlowKeys(scheme.flows)[0]\n const currentFlow = selectedFlow.value || firstFlow\n if (!currentFlow) {\n return capitalizedName\n }\n return `${capitalizedName}: ${currentFlow}`\n }\n\n case 'http':\n return `${capitalizedName}: ${scheme.scheme}`\n\n default:\n return capitalizedName\n }\n}\n\n/**\n * Whether an API key scheme exposes an editable parameter name.\n *\n * OpenAPI `apiKey` and AsyncAPI `httpApiKey` (normalized to `apiKey`) name a query/header/cookie\n * parameter, so the Name input is shown. AsyncAPI `apiKey` places the key in the broker `user` or\n * `password` slot and has no parameter name, so the Name input is hidden and only the value is asked for.\n */\nconst apiKeyHasName = (scheme: { in?: string }): boolean =>\n scheme.in !== 'user' && scheme.in !== 'password'\n\n/**\n * The scheme's type when it is one we do not render inputs for (a type outside both the OpenAPI\n * and AsyncAPI security scheme unions). Read through a helper so the fallback template branch,\n * where the scheme type is narrowed to `never` after the supported cases, can still surface the type.\n */\nconst getUnsupportedSchemeType = (\n scheme: SecurityItem['scheme'],\n): string | undefined => scheme?.type\n\n/**\n * Determines if an OAuth2 flow tab should be active.\n * The first flow is active by default if no flow is explicitly selected.\n */\nconst isFlowActive = (flowKey: string, index: number): boolean =>\n selectedFlow.value === flowKey || (index === 0 && !selectedFlow.value)\n\n/** Computes the container class for static display mode. */\nconst getStaticBorderClass = (): string | false => isStatic && 'border-t'\n\nconst handleHttpSecretsUpdate = (\n payload: Omit<Partial<SecretsHttp>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: { type: 'http', ...payload },\n name,\n })\n\nconst handleApiKeySecretsUpdate = (\n payload: Omit<Partial<SecretsApiKey>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: { type: 'apiKey', ...payload },\n name,\n })\n\nconst handleApiKeySecuritySchemeUpdate = (\n payload: Omit<Partial<ApiKeyObject>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme', {\n payload: { type: 'apiKey', ...payload },\n name,\n })\n\n/** Handles scope selection updates for OAuth2 */\nconst handleScopesUpdate = (\n name: string,\n event: { scopes?: string[]; scope?: string; selected?: boolean },\n): void => {\n emits('update:selectedScopes', {\n id: Object.keys(selectedSecuritySchemas),\n name,\n ...event,\n })\n}\n\n/** Handles scope-definition upserts (add / rename / description change) */\nconst handleScopeUpsert = (\n name: string,\n event: Omit<ApiReferenceEvents['auth:upsert:scopes'], 'name'>,\n): void => {\n emits('upsert:scope', { ...event, name })\n}\n\n/** Handles scope-definition deletes */\nconst handleScopeDelete = (\n name: string,\n event: Omit<ApiReferenceEvents['auth:delete:scopes'], 'name'>,\n): void => {\n emits('delete:scope', { ...event, name })\n}\n\n/**\n * Computes dynamic classes for OAuth2 flow tabs based on active state.\n */\nconst getFlowTabClasses = (flowKey: string, index: number): string => {\n const baseClasses =\n 'floating-bg text-c-3 relative cursor-pointer border-b border-transparent py-1 text-base font-medium'\n const activeClasses = '!text-c-1 !rounded-none border-b !border-current'\n\n return isFlowActive(flowKey, index)\n ? `${baseClasses} ${activeClasses} ${isStatic ? 'opacity-100' : ''}`\n : baseClasses\n}\n\n/**\n * OAuth2 token-acquisition target (an oauth2 scheme with an interactive grant) sourced from\n * the merged schemes. When the active scheme is HTTP bearer, this powers the inline\n * \"Authorize via OAuth2\" shortcut: the flow's bearer token is written onto the bearer scheme,\n * so the panel never switches to oauth2.\n *\n * The shortcut is purely a convenience, so it is offered for any interactive oauth2 scheme —\n * including one that is also independently selectable in the dropdown (e.g. Scalar Galaxy's\n * `oAuth2`). Whether that oauth2 scheme is *hidden* from the dropdown is a separate decision made\n * in the selector; here we only surface the shortcut.\n */\nconst oauth2Target = computed(() => getOauth2AcquisitionTarget(securitySchemes))\n\n/** Resolved oauth2 scheme object, for embedding its config form behind the gear. */\nconst oauth2Scheme = computed(() =>\n oauth2Target.value\n ? getResolvedRef(securitySchemes[oauth2Target.value.name])\n : undefined,\n)\n\nconst acquisitionLoader = useLoadingState()\nconst { toast } = useToasts()\nconst configModal = useModal()\n/** Bearer scheme that opened the config modal, so its Authorize callback targets it. */\nconst configBearerName = ref<string | undefined>()\n\n/** Runs the OAuth2 flow and writes the resulting bearer token onto the bearer scheme. */\nconst handleAcquisitionAuthorize = async (\n bearerName: string,\n): Promise<void> => {\n const target = oauth2Target.value\n if (!target || acquisitionLoader.isLoading) {\n return\n }\n acquisitionLoader.start()\n const [error] = await runOAuth2Authorize({\n eventBus,\n bearerSchemeName: bearerName,\n oauth2Name: target.name,\n flows: target.flows,\n flowType: target.flowType,\n scopes: target.scopes,\n server,\n proxyUrl,\n environment,\n options,\n })\n await acquisitionLoader.clear()\n if (error) {\n toast(error?.message ?? 'Failed to authorize', 'error')\n }\n}\n\n/** Refreshes the OAuth2 token and rewrites it onto the bearer scheme. */\nconst handleAcquisitionRefresh = async (bearerName: string): Promise<void> => {\n const target = oauth2Target.value\n // Only the authorization-code flow carries a refresh token; implicit can't be refreshed.\n if (\n !target ||\n target.flowType !== 'authorizationCode' ||\n acquisitionLoader.isLoading\n ) {\n return\n }\n acquisitionLoader.start()\n const [error, tokens] = await refreshOauth2Token(\n target.flows,\n target.flowType,\n proxyUrl,\n server,\n getEnvironmentVariables(environment),\n options?.customFetch,\n )\n await acquisitionLoader.clear()\n if (tokens?.accessToken) {\n storeOAuth2Tokens(eventBus, {\n bearerSchemeName: bearerName,\n oauth2Name: target.name,\n flowType: target.flowType,\n tokens,\n })\n } else if (error) {\n toast(error?.message ?? 'Failed to refresh', 'error')\n }\n}\n\nconst openAcquisitionConfig = (bearerName: string): void => {\n configBearerName.value = bearerName\n configModal.show()\n}\n\n/** Closes the config modal and runs Authorize against the bearer scheme that opened it. */\nconst handleConfigAuthorize = (): void => {\n const bearerName = configBearerName.value\n configModal.hide()\n if (bearerName) {\n void handleAcquisitionAuthorize(bearerName)\n }\n}\n</script>\n<template>\n <template\n v-for=\"{ scheme, name, scopes, visibleFlowKeys } in security\"\n :key=\"name\">\n <!--\n Header row for AND'ed schemes: label (bold) and description (rich text) are\n combined.\n -->\n <DataTableRow v-if=\"hasMultipleSchemes && scheme\">\n <DataTableCell\n :aria-label=\"generateLabel(name, scheme)\"\n class=\"max-h-[auto]\">\n <div class=\"bg-b-1 min-w-0 flex-1 px-3 py-1.25\">\n <p class=\"text-c-1 leading-5.5 font-medium\">\n {{ generateLabel(name, scheme) }}\n </p>\n <ScalarMarkdownSummary\n v-if=\"scheme.description\"\n class=\"auth-description text-c-2 w-full\"\n :value=\"scheme.description\" />\n </div>\n </DataTableCell>\n </DataTableRow>\n\n <!-- Description: shown for single auth schemes with descriptions -->\n <DataTableRow v-if=\"scheme?.description && !hasMultipleSchemes\">\n <DataTableCell\n :aria-label=\"scheme.description\"\n class=\"max-h-[auto]\">\n <ScalarMarkdownSummary\n class=\"auth-description bg-b-1 text-c-2 min-w-0 flex-1 px-3 py-1.25\"\n :value=\"scheme.description\" />\n </DataTableCell>\n </DataTableRow>\n\n <!-- HTTP Authentication -->\n <template v-if=\"scheme?.type === 'http'\">\n <!-- Bearer Token -->\n <DataTableRow v-if=\"scheme.scheme === 'bearer'\">\n <RequestAuthDataTableInput\n :containerClass=\"getStaticBorderClass()\"\n :environment\n :modelValue=\"scheme['x-scalar-secret-token']\"\n placeholder=\"Token\"\n type=\"password\"\n @update:modelValue=\"\n (v) => handleHttpSecretsUpdate({ 'x-scalar-secret-token': v }, name)\n \">\n Bearer Token\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <!-- OAuth2 token-acquisition shortcut (shown when an interactive oauth2 flow exists) -->\n <DataTableRow v-if=\"scheme.scheme === 'bearer' && oauth2Target\">\n <div class=\"flex h-8 items-center gap-2 border-t px-3\">\n <span class=\"text-c-3 mr-auto text-xs\">Get a token</span>\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n :loader=\"acquisitionLoader\"\n size=\"sm\"\n type=\"button\"\n variant=\"outlined\"\n @click=\"handleAcquisitionAuthorize(name)\">\n Authorize via {{ oauth2Target.name }}\n </ScalarButton>\n <ScalarButton\n v-if=\"\n scheme['x-scalar-secret-token'] &&\n oauth2Target.flowType === 'authorizationCode'\n \"\n class=\"p-0 px-2 py-0.5\"\n :disabled=\"acquisitionLoader.isLoading\"\n size=\"sm\"\n type=\"button\"\n variant=\"outlined\"\n @click=\"handleAcquisitionRefresh(name)\">\n Refresh\n </ScalarButton>\n <ScalarIconButton\n :icon=\"ScalarIconGear\"\n :label=\"`Configure ${oauth2Target.name}`\"\n size=\"xs\"\n @click=\"openAcquisitionConfig(name)\" />\n </div>\n </DataTableRow>\n\n <!-- HTTP Basic Authentication -->\n <template v-else-if=\"scheme?.scheme === 'basic'\">\n <DataTableRow>\n <RequestAuthDataTableInput\n class=\"text-c-2\"\n :environment\n :modelValue=\"scheme['x-scalar-secret-username']\"\n placeholder=\"janedoe\"\n required\n @update:modelValue=\"\n (v) =>\n handleHttpSecretsUpdate({ 'x-scalar-secret-username': v }, name)\n \">\n Username\n </RequestAuthDataTableInput>\n </DataTableRow>\n <DataTableRow>\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"scheme['x-scalar-secret-password']\"\n placeholder=\"********\"\n type=\"password\"\n @update:modelValue=\"\n (v) =>\n handleHttpSecretsUpdate({ 'x-scalar-secret-password': v }, name)\n \">\n Password\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n </template>\n\n <!-- API Key Authentication -->\n <template v-else-if=\"scheme?.type === 'apiKey'\">\n <DataTableRow v-if=\"apiKeyHasName(scheme)\">\n <RequestAuthDataTableInput\n :containerClass=\"getStaticBorderClass()\"\n :environment\n :modelValue=\"scheme.name ?? ''\"\n placeholder=\"api-key\"\n @update:modelValue=\"\n (v) => handleApiKeySecuritySchemeUpdate({ name: v }, name)\n \">\n Name\n </RequestAuthDataTableInput>\n </DataTableRow>\n <DataTableRow>\n <RequestAuthDataTableInput\n :containerClass=\"\n apiKeyHasName(scheme) ? undefined : getStaticBorderClass()\n \"\n :environment\n :modelValue=\"scheme['x-scalar-secret-token']\"\n placeholder=\"QUxMIFlPVVIgQkFTRSBBUkUgQkVMT05HIFRPIFVT\"\n type=\"password\"\n @update:modelValue=\"\n (v) =>\n handleApiKeySecretsUpdate({ 'x-scalar-secret-token': v }, name)\n \">\n Value\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n\n <!-- OAuth 2.0 / OpenID Connect Authentication -->\n <template\n v-else-if=\"scheme?.type === 'oauth2' || scheme?.type === 'openIdConnect'\">\n <!-- OpenID Connect -->\n <OpenIDConnect\n v-if=\"scheme?.type === 'openIdConnect' && !visibleFlowKeys.length\"\n :customFetch=\"options?.customFetch\"\n :environment\n :eventBus\n :getStaticBorderClass\n :name\n :proxyUrl\n :scheme />\n\n <!-- Flow selector tabs: shown when multiple visible flows are available -->\n <DataTableRow v-if=\"visibleFlowKeys.length > 1\">\n <div class=\"flex min-h-8 border-t text-base\">\n <div class=\"flex h-8 max-w-full gap-2.5 overflow-x-auto px-3\">\n <button\n v-for=\"(key, ind) in visibleFlowKeys\"\n :key=\"key\"\n :class=\"getFlowTabClasses(key, ind)\"\n type=\"button\"\n @click=\"setActiveFlow(key)\">\n <span class=\"relative z-10\">{{ key }}</span>\n </button>\n </div>\n </div>\n </DataTableRow>\n\n <!-- OAuth2 flow configuration -->\n <template\n v-for=\"(key, ind) in visibleFlowKeys\"\n :key=\"key\">\n <OAuth2\n v-if=\"scheme.flows && isFlowActive(key, ind)\"\n :environment\n :eventBus\n :flows=\"scheme.flows\"\n :name\n :options\n :proxyUrl\n :scheme\n :selectedScopes=\"scopes\"\n :server\n :type=\"key\"\n @delete:scope=\"(event) => handleScopeDelete(name, event)\"\n @update:selectedScopes=\"(event) => handleScopesUpdate(name, event)\"\n @upsert:scope=\"(event) => handleScopeUpsert(name, event)\" />\n </template>\n </template>\n\n <!-- Browser WebSocket connections cannot apply these broker credentials. -->\n <div\n v-else-if=\"\n scheme?.type === 'userPassword' ||\n scheme?.type === 'plain' ||\n scheme?.type === 'scramSha256' ||\n scheme?.type === 'scramSha512' ||\n scheme?.type === 'X509' ||\n scheme?.type === 'symmetricEncryption' ||\n scheme?.type === 'asymmetricEncryption' ||\n scheme?.type === 'gssapi'\n \"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n Credentials for this AsyncAPI security scheme are not sent by the browser\n client.\n </div>\n\n <!-- Mutual TLS credentials are chosen during the browser-managed TLS handshake. -->\n <div\n v-else-if=\"scheme?.type === 'mutualTLS'\"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n Mutual TLS authenticates with a client certificate presented during the\n TLS handshake, so there is nothing to enter here.\n </div>\n\n <!-- Scheme has a type we do not render inputs for -->\n <div\n v-else-if=\"getUnsupportedSchemeType(scheme)\"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n The <code>{{ getUnsupportedSchemeType(scheme) }}</code> security scheme\n type is not supported yet.\n </div>\n\n <!-- Scheme is missing type -->\n <div\n v-else\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n The security scheme is missing a type, please double check your\n {{ documentTypeLabel }} document or Authentication Configuration\n </div>\n </template>\n\n <!-- OAuth2 configuration modal (opened from the bearer scheme's gear) -->\n <ScalarModal\n v-if=\"oauth2Target && oauth2Scheme\"\n :state=\"configModal\"\n size=\"sm\"\n :title=\"`Configure ${oauth2Target.name}`\">\n <DataTable\n :columns=\"['']\"\n presentational>\n <OAuth2\n hideActions\n :environment\n :eventBus\n :flows=\"oauth2Target.flows\"\n :name=\"oauth2Target.name\"\n :options\n :proxyUrl\n :scheme=\"oauth2Scheme\"\n :selectedScopes=\"oauth2Target.scopes\"\n :server\n :type=\"oauth2Target.flowType\"\n @delete:scope=\"(event) => handleScopeDelete(oauth2Target!.name, event)\"\n @update:selectedScopes=\"\n (event) => handleScopesUpdate(oauth2Target!.name, event)\n \"\n @upsert:scope=\"\n (event) => handleScopeUpsert(oauth2Target!.name, event)\n \" />\n </DataTable>\n <div class=\"flex h-8 items-center justify-end gap-2 border-t\">\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"configModal.hide()\">\n Cancel\n </ScalarButton>\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n :loader=\"acquisitionLoader\"\n size=\"sm\"\n @click=\"handleConfigAuthorize\">\n Authorize\n </ScalarButton>\n </div>\n </ScalarModal>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RequestAuthTab.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components/button'\nimport { ScalarIconButton } from '@scalar/components/icon-button'\nimport { useLoadingState } from '@scalar/components/loading'\nimport { ScalarMarkdownSummary } from '@scalar/components/markdown'\nimport { ScalarModal, useModal } from '@scalar/components/modal'\nimport { ScalarIconGear } from '@scalar/icons'\nimport { useToasts } from '@scalar/use-toasts'\nimport type {\n SecretsApiKey,\n SecretsHttp,\n} from '@scalar/workspace-store/entities/auth'\nimport type {\n ApiReferenceEvents,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport {\n getEnvironmentVariables,\n type MergedSecuritySchemes,\n type OAuthFlowsObjectSecret,\n type SecuritySchemeObjectSecret,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { getDocumentTypeLabel } from '@scalar/workspace-store/schemas/type-guards'\nimport type {\n ApiKeyObject,\n SecurityRequirementObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { capitalize, computed, ref } from 'vue'\n\nimport { refreshOauth2Token } from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth'\nimport { getVisibleOrderedFlowKeys } from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth-flows'\nimport {\n runOAuth2Authorize,\n storeOAuth2Tokens,\n} from '@/v2/blocks/scalar-auth-selector-block/helpers/run-oauth2-authorize'\nimport { getOauth2AcquisitionTarget } from '@/v2/blocks/scalar-auth-selector-block/helpers/security-scheme'\nimport {\n DataTable,\n DataTableCell,\n DataTableRow,\n} from '@/v2/components/data-table'\n\nimport OAuth2, { type OAuth2Options } from './OAuth2.vue'\nimport OAuth2Metadata from './OAuth2Metadata.vue'\nimport OpenIDConnect from './OpenIDConnect.vue'\nimport RequestAuthDataTableInput from './RequestAuthDataTableInput.vue'\n\ntype SecurityItem = {\n scheme: SecuritySchemeObjectSecret | undefined\n name: string\n scopes: string[]\n /** Ordered, non-hidden oauth2/openIdConnect flow keys for this scheme (empty for other types). */\n visibleFlowKeys: (keyof OAuthFlowsObjectSecret)[]\n}\n\nconst {\n environment,\n isStatic,\n proxyUrl,\n selectedSecuritySchemas,\n securitySchemes,\n server,\n eventBus,\n options,\n documentType = 'openapi',\n} = defineProps<{\n /** Current environment configuration */\n environment: XScalarEnvironment\n /** Controls the display of certain borders which are used when we are non-collapsible */\n isStatic: boolean\n /** Proxy URL */\n proxyUrl: string\n /** Selected security schemes*/\n selectedSecuritySchemas: SecurityRequirementObject\n /** Merged security schemes from the document and the config together with the auth store secrets */\n securitySchemes: MergedSecuritySchemes\n /** Current server configuration */\n server: ServerObject | null\n /** Event bus for authentication updates */\n eventBus: WorkspaceEventBus\n /** Any config options required for the OAuth2 flow */\n options?: OAuth2Options\n /** Type of the document the schemes belong to, used to label the missing-type warning */\n documentType?: 'openapi' | 'asyncapi'\n}>()\n\n/**\n * Human-readable name of the document type.\n * Used in the missing-type warning so it points at the correct document\n * (e.g. \"AsyncAPI\") instead of always naming OpenAPI.\n */\nconst documentTypeLabel = computed<string>(() =>\n getDocumentTypeLabel(documentType),\n)\n\nconst emits = defineEmits<{\n (\n e: 'update:selectedScopes',\n payload: Omit<ApiReferenceEvents['auth:update:selected-scopes'], 'meta'>,\n ): void\n (e: 'upsert:scope', payload: ApiReferenceEvents['auth:upsert:scopes']): void\n (e: 'delete:scope', payload: ApiReferenceEvents['auth:delete:scopes']): void\n}>()\n\n/**\n * Resolves security schemes from the OpenAPI document and combines them with their selected scopes.\n * Each item includes the scheme definition, name, and associated scopes.\n */\nconst security = computed<SecurityItem[]>(() =>\n Object.entries(selectedSecuritySchemas).map(([name, scopes = []]) => {\n const scheme = getResolvedRef(securitySchemes[name])\n return {\n scheme,\n name,\n scopes,\n // Compute the visible, ordered flow keys once per scheme so the tabs, the label, and the\n // active-flow tracking all agree on the same set (and we do not filter + sort on every access).\n visibleFlowKeys:\n scheme?.type === 'oauth2' || scheme?.type === 'openIdConnect'\n ? getVisibleOrderedFlowKeys(scheme.flows)\n : [],\n }\n }),\n)\n\n/** Tracks which OAuth2 flow is currently active when multiple flows are available. */\nconst activeFlow = ref<string>('')\n\n/**\n * Keeps the selected flow in sync with the currently visible flow keys. Validating against the\n * visible set (not every declared flow) means a selection that becomes hidden — e.g. the document\n * is updated to mark the active flow with `x-scalar-ignore` — resets, so the default (first visible)\n * flow activates instead of leaving no tab selected.\n */\nconst selectedFlow = computed<string>(() => {\n const visibleFlowKeys = security.value.flatMap((item) => item.visibleFlowKeys)\n\n return visibleFlowKeys.some((key) => key === activeFlow.value)\n ? activeFlow.value\n : ''\n})\n\nconst setActiveFlow = (flow: string): void => {\n activeFlow.value = flow\n}\n\n/** Determines if multiple auth schemes are configured, which affects the UI layout. */\nconst hasMultipleSchemes = computed<boolean>(() => security.value.length > 1)\n\n/**\n * Generates a human-readable label for the security scheme.\n * Intentionally omits the description here — it is rendered separately as\n * rich text via ScalarMarkdownSummary so markdown formatting is preserved.\n */\nconst generateLabel = (\n name: string,\n scheme: SecuritySchemeObjectSecret,\n): string => {\n const capitalizedName = capitalize(name)\n\n switch (scheme.type) {\n case 'apiKey':\n return `${capitalizedName}: ${scheme.in}`\n\n case 'openIdConnect':\n case 'oauth2': {\n const firstFlow = getVisibleOrderedFlowKeys(scheme.flows)[0]\n const currentFlow = selectedFlow.value || firstFlow\n if (!currentFlow) {\n return capitalizedName\n }\n return `${capitalizedName}: ${currentFlow}`\n }\n\n case 'http':\n return `${capitalizedName}: ${scheme.scheme}`\n\n default:\n return capitalizedName\n }\n}\n\n/**\n * Whether an API key scheme exposes an editable parameter name.\n *\n * OpenAPI `apiKey` and AsyncAPI `httpApiKey` (normalized to `apiKey`) name a query/header/cookie\n * parameter, so the Name input is shown. AsyncAPI `apiKey` places the key in the broker `user` or\n * `password` slot and has no parameter name, so the Name input is hidden and only the value is asked for.\n */\nconst apiKeyHasName = (scheme: { in?: string }): boolean =>\n scheme.in !== 'user' && scheme.in !== 'password'\n\n/**\n * The scheme's type when it is one we do not render inputs for (a type outside both the OpenAPI\n * and AsyncAPI security scheme unions). Read through a helper so the fallback template branch,\n * where the scheme type is narrowed to `never` after the supported cases, can still surface the type.\n */\nconst getUnsupportedSchemeType = (\n scheme: SecurityItem['scheme'],\n): string | undefined => scheme?.type\n\n/**\n * Determines if an OAuth2 flow tab should be active.\n * The first flow is active by default if no flow is explicitly selected.\n */\nconst isFlowActive = (flowKey: string, index: number): boolean =>\n selectedFlow.value === flowKey || (index === 0 && !selectedFlow.value)\n\n/** Computes the container class for static display mode. */\nconst getStaticBorderClass = (): string | false => isStatic && 'border-t'\n\nconst handleHttpSecretsUpdate = (\n payload: Omit<Partial<SecretsHttp>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: { type: 'http', ...payload },\n name,\n })\n\nconst handleApiKeySecretsUpdate = (\n payload: Omit<Partial<SecretsApiKey>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: { type: 'apiKey', ...payload },\n name,\n })\n\nconst handleApiKeySecuritySchemeUpdate = (\n payload: Omit<Partial<ApiKeyObject>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme', {\n payload: { type: 'apiKey', ...payload },\n name,\n })\n\n/** Handles scope selection updates for OAuth2 */\nconst handleScopesUpdate = (\n name: string,\n event: { scopes?: string[]; scope?: string; selected?: boolean },\n): void => {\n emits('update:selectedScopes', {\n id: Object.keys(selectedSecuritySchemas),\n name,\n ...event,\n })\n}\n\n/** Handles scope-definition upserts (add / rename / description change) */\nconst handleScopeUpsert = (\n name: string,\n event: Omit<ApiReferenceEvents['auth:upsert:scopes'], 'name'>,\n): void => {\n emits('upsert:scope', { ...event, name })\n}\n\n/** Handles scope-definition deletes */\nconst handleScopeDelete = (\n name: string,\n event: Omit<ApiReferenceEvents['auth:delete:scopes'], 'name'>,\n): void => {\n emits('delete:scope', { ...event, name })\n}\n\n/**\n * Computes dynamic classes for OAuth2 flow tabs based on active state.\n */\nconst getFlowTabClasses = (flowKey: string, index: number): string => {\n const baseClasses =\n 'floating-bg text-c-3 relative cursor-pointer border-b border-transparent py-1 text-base font-medium'\n const activeClasses = '!text-c-1 !rounded-none border-b !border-current'\n\n return isFlowActive(flowKey, index)\n ? `${baseClasses} ${activeClasses} ${isStatic ? 'opacity-100' : ''}`\n : baseClasses\n}\n\n/**\n * OAuth2 token-acquisition target (an oauth2 scheme with an interactive grant) sourced from\n * the merged schemes. When the active scheme is HTTP bearer, this powers the inline\n * \"Authorize via OAuth2\" shortcut: the flow's bearer token is written onto the bearer scheme,\n * so the panel never switches to oauth2.\n *\n * The shortcut is purely a convenience, so it is offered for any interactive oauth2 scheme —\n * including one that is also independently selectable in the dropdown (e.g. Scalar Galaxy's\n * `oAuth2`). Whether that oauth2 scheme is *hidden* from the dropdown is a separate decision made\n * in the selector; here we only surface the shortcut.\n */\nconst oauth2Target = computed(() => getOauth2AcquisitionTarget(securitySchemes))\n\n/** Resolved oauth2 scheme object, for embedding its config form behind the gear. */\nconst oauth2Scheme = computed(() =>\n oauth2Target.value\n ? getResolvedRef(securitySchemes[oauth2Target.value.name])\n : undefined,\n)\n\nconst acquisitionLoader = useLoadingState()\nconst { toast } = useToasts()\nconst configModal = useModal()\n/** Bearer scheme that opened the config modal, so its Authorize callback targets it. */\nconst configBearerName = ref<string | undefined>()\n\n/** Runs the OAuth2 flow and writes the resulting bearer token onto the bearer scheme. */\nconst handleAcquisitionAuthorize = async (\n bearerName: string,\n): Promise<void> => {\n const target = oauth2Target.value\n if (!target || acquisitionLoader.isLoading) {\n return\n }\n acquisitionLoader.start()\n const [error] = await runOAuth2Authorize({\n eventBus,\n bearerSchemeName: bearerName,\n oauth2Name: target.name,\n flows: target.flows,\n flowType: target.flowType,\n scopes: target.scopes,\n server,\n proxyUrl,\n environment,\n options,\n })\n await acquisitionLoader.clear()\n if (error) {\n toast(error?.message ?? 'Failed to authorize', 'error')\n }\n}\n\n/** Refreshes the OAuth2 token and rewrites it onto the bearer scheme. */\nconst handleAcquisitionRefresh = async (bearerName: string): Promise<void> => {\n const target = oauth2Target.value\n // Only the authorization-code flow carries a refresh token; implicit can't be refreshed.\n if (\n !target ||\n target.flowType !== 'authorizationCode' ||\n acquisitionLoader.isLoading\n ) {\n return\n }\n acquisitionLoader.start()\n const [error, tokens] = await refreshOauth2Token(\n target.flows,\n target.flowType,\n proxyUrl,\n server,\n getEnvironmentVariables(environment),\n options?.customFetch,\n )\n await acquisitionLoader.clear()\n if (tokens?.accessToken) {\n storeOAuth2Tokens(eventBus, {\n bearerSchemeName: bearerName,\n oauth2Name: target.name,\n flowType: target.flowType,\n tokens,\n })\n } else if (error) {\n toast(error?.message ?? 'Failed to refresh', 'error')\n }\n}\n\nconst openAcquisitionConfig = (bearerName: string): void => {\n configBearerName.value = bearerName\n configModal.show()\n}\n\n/** Closes the config modal and runs Authorize against the bearer scheme that opened it. */\nconst handleConfigAuthorize = (): void => {\n const bearerName = configBearerName.value\n configModal.hide()\n if (bearerName) {\n void handleAcquisitionAuthorize(bearerName)\n }\n}\n</script>\n<template>\n <template\n v-for=\"{ scheme, name, scopes, visibleFlowKeys } in security\"\n :key=\"name\">\n <!--\n Header row for AND'ed schemes: label (bold) and description (rich text) are\n combined.\n -->\n <DataTableRow v-if=\"hasMultipleSchemes && scheme\">\n <DataTableCell\n :aria-label=\"generateLabel(name, scheme)\"\n class=\"max-h-[auto]\">\n <div class=\"bg-b-1 min-w-0 flex-1 px-3 py-1.25\">\n <p class=\"text-c-1 leading-5.5 font-medium\">\n {{ generateLabel(name, scheme) }}\n </p>\n <ScalarMarkdownSummary\n v-if=\"scheme.description\"\n class=\"auth-description text-c-2 w-full\"\n :value=\"scheme.description\" />\n </div>\n </DataTableCell>\n </DataTableRow>\n\n <!-- Description: shown for single auth schemes with descriptions -->\n <DataTableRow v-if=\"scheme?.description && !hasMultipleSchemes\">\n <DataTableCell\n :aria-label=\"scheme.description\"\n class=\"max-h-[auto]\">\n <ScalarMarkdownSummary\n class=\"auth-description bg-b-1 text-c-2 min-w-0 flex-1 px-3 py-1.25\"\n :value=\"scheme.description\" />\n </DataTableCell>\n </DataTableRow>\n\n <!-- HTTP Authentication -->\n <template v-if=\"scheme?.type === 'http'\">\n <!-- Bearer Token -->\n <DataTableRow v-if=\"scheme.scheme === 'bearer'\">\n <RequestAuthDataTableInput\n :containerClass=\"getStaticBorderClass()\"\n :environment\n :modelValue=\"scheme['x-scalar-secret-token']\"\n placeholder=\"Token\"\n type=\"password\"\n @update:modelValue=\"\n (v) => handleHttpSecretsUpdate({ 'x-scalar-secret-token': v }, name)\n \">\n Bearer Token\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <!-- OAuth2 token-acquisition shortcut (shown when an interactive oauth2 flow exists) -->\n <DataTableRow v-if=\"scheme.scheme === 'bearer' && oauth2Target\">\n <div class=\"flex h-8 items-center gap-2 border-t px-3\">\n <span class=\"text-c-3 mr-auto text-xs\">Get a token</span>\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n :loader=\"acquisitionLoader\"\n size=\"sm\"\n type=\"button\"\n variant=\"outlined\"\n @click=\"handleAcquisitionAuthorize(name)\">\n Authorize via {{ oauth2Target.name }}\n </ScalarButton>\n <ScalarButton\n v-if=\"\n scheme['x-scalar-secret-token'] &&\n oauth2Target.flowType === 'authorizationCode'\n \"\n class=\"p-0 px-2 py-0.5\"\n :disabled=\"acquisitionLoader.isLoading\"\n size=\"sm\"\n type=\"button\"\n variant=\"outlined\"\n @click=\"handleAcquisitionRefresh(name)\">\n Refresh\n </ScalarButton>\n <ScalarIconButton\n :icon=\"ScalarIconGear\"\n :label=\"`Configure ${oauth2Target.name}`\"\n size=\"xs\"\n @click=\"openAcquisitionConfig(name)\" />\n </div>\n </DataTableRow>\n\n <!-- HTTP Basic Authentication -->\n <template v-else-if=\"scheme?.scheme === 'basic'\">\n <DataTableRow>\n <RequestAuthDataTableInput\n class=\"text-c-2\"\n :environment\n :modelValue=\"scheme['x-scalar-secret-username']\"\n placeholder=\"janedoe\"\n required\n @update:modelValue=\"\n (v) =>\n handleHttpSecretsUpdate({ 'x-scalar-secret-username': v }, name)\n \">\n Username\n </RequestAuthDataTableInput>\n </DataTableRow>\n <DataTableRow>\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"scheme['x-scalar-secret-password']\"\n placeholder=\"********\"\n type=\"password\"\n @update:modelValue=\"\n (v) =>\n handleHttpSecretsUpdate({ 'x-scalar-secret-password': v }, name)\n \">\n Password\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n </template>\n\n <!-- API Key Authentication -->\n <template v-else-if=\"scheme?.type === 'apiKey'\">\n <DataTableRow v-if=\"apiKeyHasName(scheme)\">\n <RequestAuthDataTableInput\n :containerClass=\"getStaticBorderClass()\"\n :environment\n :modelValue=\"scheme.name ?? ''\"\n placeholder=\"api-key\"\n @update:modelValue=\"\n (v) => handleApiKeySecuritySchemeUpdate({ name: v }, name)\n \">\n Name\n </RequestAuthDataTableInput>\n </DataTableRow>\n <DataTableRow>\n <RequestAuthDataTableInput\n :containerClass=\"\n apiKeyHasName(scheme) ? undefined : getStaticBorderClass()\n \"\n :environment\n :modelValue=\"scheme['x-scalar-secret-token']\"\n placeholder=\"QUxMIFlPVVIgQkFTRSBBUkUgQkVMT05HIFRPIFVT\"\n type=\"password\"\n @update:modelValue=\"\n (v) =>\n handleApiKeySecretsUpdate({ 'x-scalar-secret-token': v }, name)\n \">\n Value\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n\n <!-- OAuth 2.0 / OpenID Connect Authentication -->\n <template\n v-else-if=\"scheme?.type === 'oauth2' || scheme?.type === 'openIdConnect'\">\n <OAuth2Metadata\n v-if=\"\n scheme.type === 'oauth2' && (!isStatic || scheme.oauth2MetadataUrl)\n \"\n :customFetch=\"options?.customFetch\"\n :environment\n :eventBus\n :name\n :proxyUrl\n :scheme />\n\n <!-- OpenID Connect -->\n <OpenIDConnect\n v-if=\"scheme?.type === 'openIdConnect' && !visibleFlowKeys.length\"\n :customFetch=\"options?.customFetch\"\n :environment\n :eventBus\n :getStaticBorderClass\n :name\n :proxyUrl\n :scheme />\n\n <!-- Flow selector tabs: shown when multiple visible flows are available -->\n <DataTableRow v-if=\"visibleFlowKeys.length > 1\">\n <div class=\"flex min-h-8 border-t text-base\">\n <div class=\"flex h-8 max-w-full gap-2.5 overflow-x-auto px-3\">\n <button\n v-for=\"(key, ind) in visibleFlowKeys\"\n :key=\"key\"\n :class=\"getFlowTabClasses(key, ind)\"\n type=\"button\"\n @click=\"setActiveFlow(key)\">\n <span class=\"relative z-10\">{{ key }}</span>\n </button>\n </div>\n </div>\n </DataTableRow>\n\n <!-- OAuth2 flow configuration -->\n <template\n v-for=\"(key, ind) in visibleFlowKeys\"\n :key=\"key\">\n <OAuth2\n v-if=\"scheme.flows && isFlowActive(key, ind)\"\n :environment\n :eventBus\n :flows=\"scheme.flows\"\n :name\n :options\n :proxyUrl\n :scheme\n :selectedScopes=\"scopes\"\n :server\n :type=\"key\"\n @delete:scope=\"(event) => handleScopeDelete(name, event)\"\n @update:selectedScopes=\"(event) => handleScopesUpdate(name, event)\"\n @upsert:scope=\"(event) => handleScopeUpsert(name, event)\" />\n </template>\n </template>\n\n <!-- Browser WebSocket connections cannot apply these broker credentials. -->\n <div\n v-else-if=\"\n scheme?.type === 'userPassword' ||\n scheme?.type === 'plain' ||\n scheme?.type === 'scramSha256' ||\n scheme?.type === 'scramSha512' ||\n scheme?.type === 'X509' ||\n scheme?.type === 'symmetricEncryption' ||\n scheme?.type === 'asymmetricEncryption' ||\n scheme?.type === 'gssapi'\n \"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n Credentials for this AsyncAPI security scheme are not sent by the browser\n client.\n </div>\n\n <!-- Mutual TLS credentials are chosen during the browser-managed TLS handshake. -->\n <div\n v-else-if=\"scheme?.type === 'mutualTLS'\"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n Mutual TLS authenticates with a client certificate presented during the\n TLS handshake, so there is nothing to enter here.\n </div>\n\n <!-- Scheme has a type we do not render inputs for -->\n <div\n v-else-if=\"getUnsupportedSchemeType(scheme)\"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n The <code>{{ getUnsupportedSchemeType(scheme) }}</code> security scheme\n type is not supported yet.\n </div>\n\n <!-- Scheme is missing type -->\n <div\n v-else\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n The security scheme is missing a type, please double check your\n {{ documentTypeLabel }} document or Authentication Configuration\n </div>\n </template>\n\n <!-- OAuth2 configuration modal (opened from the bearer scheme's gear) -->\n <ScalarModal\n v-if=\"oauth2Target && oauth2Scheme\"\n :state=\"configModal\"\n size=\"sm\"\n :title=\"`Configure ${oauth2Target.name}`\">\n <DataTable\n :columns=\"['']\"\n presentational>\n <OAuth2\n hideActions\n :environment\n :eventBus\n :flows=\"oauth2Target.flows\"\n :name=\"oauth2Target.name\"\n :options\n :proxyUrl\n :scheme=\"oauth2Scheme\"\n :selectedScopes=\"oauth2Target.scopes\"\n :server\n :type=\"oauth2Target.flowType\"\n @delete:scope=\"(event) => handleScopeDelete(oauth2Target!.name, event)\"\n @update:selectedScopes=\"\n (event) => handleScopesUpdate(oauth2Target!.name, event)\n \"\n @upsert:scope=\"\n (event) => handleScopeUpsert(oauth2Target!.name, event)\n \" />\n </DataTable>\n <div class=\"flex h-8 items-center justify-end gap-2 border-t\">\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"configModal.hide()\">\n Cancel\n </ScalarButton>\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n :loader=\"acquisitionLoader\"\n size=\"sm\"\n @click=\"handleConfigAuthorize\">\n Authorize\n </ScalarButton>\n </div>\n </ScalarModal>\n</template>\n"],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ErrorResponse } from '@scalar/helpers/errors/normalize-error';
|
|
2
|
+
import type { CustomFetch } from '../../../../v2/blocks/operation-block/helpers/send-request.js';
|
|
3
|
+
import { type OpenIDConnectDiscovery as AuthorizationServerMetadata } from './fetch-openid-connect-discovery.js';
|
|
4
|
+
/** Fetches the exact RFC8414 metadata URL, without applying OIDC issuer URL conventions. */
|
|
5
|
+
export declare const fetchOAuth2Metadata: (url: string, proxyUrl: string, customFetch?: CustomFetch) => Promise<ErrorResponse<AuthorizationServerMetadata>>;
|
|
6
|
+
//# sourceMappingURL=fetch-oauth2-metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-oauth2-metadata.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAK3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAA;AAGnF,OAAO,EACL,KAAK,sBAAsB,IAAI,2BAA2B,EAE3D,MAAM,kCAAkC,CAAA;AAKzC,4FAA4F;AAC5F,eAAO,MAAM,mBAAmB,GAC9B,KAAK,MAAM,EACX,UAAU,MAAM,EAChB,cAAa,WAAmB,KAC/B,OAAO,CAAC,aAAa,CAAC,2BAA2B,CAAC,CAuBpD,CAAA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { OpenIDConnectDiscoverySchema } from "./fetch-openid-connect-discovery.js";
|
|
2
|
+
import { redirectToProxy } from "@scalar/helpers/url/redirect-to-proxy";
|
|
3
|
+
import { isLocalUrl } from "@scalar/helpers/url/is-local-url";
|
|
4
|
+
import { coerceValue } from "@scalar/workspace-store/schemas/typebox-coerce";
|
|
5
|
+
//#region src/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.ts
|
|
6
|
+
var isAllowedMetadataUrl = (url) => url.protocol === "https:" || url.protocol === "http:" && isLocalUrl(url.href);
|
|
7
|
+
/** Fetches the exact RFC8414 metadata URL, without applying OIDC issuer URL conventions. */
|
|
8
|
+
var fetchOAuth2Metadata = async (url, proxyUrl, customFetch = fetch) => {
|
|
9
|
+
try {
|
|
10
|
+
const metadataUrl = new URL(url.trim());
|
|
11
|
+
if (!isAllowedMetadataUrl(metadataUrl)) return [/* @__PURE__ */ new Error("OAuth2 metadata URL must use HTTPS or HTTP for local development URLs"), null];
|
|
12
|
+
const response = await customFetch(redirectToProxy(proxyUrl, metadataUrl.href));
|
|
13
|
+
if (!response.ok) return [/* @__PURE__ */ new Error(`Failed to fetch OAuth2 metadata: ${response.status} ${response.statusText}`), null];
|
|
14
|
+
const data = coerceValue(OpenIDConnectDiscoverySchema, await response.json());
|
|
15
|
+
if (!data.authorization_endpoint && !data.token_endpoint) return [/* @__PURE__ */ new Error("Invalid OAuth2 metadata: missing or invalid endpoints"), null];
|
|
16
|
+
for (const endpoint of [data.authorization_endpoint, data.token_endpoint]) if (endpoint && !isAllowedMetadataUrl(new URL(endpoint))) return [/* @__PURE__ */ new Error("OAuth2 metadata endpoints must use HTTPS or HTTP for local development URLs"), null];
|
|
17
|
+
return [null, data];
|
|
18
|
+
} catch (error) {
|
|
19
|
+
return [error instanceof Error ? error : /* @__PURE__ */ new Error("Failed to fetch OAuth2 metadata"), null];
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
//#endregion
|
|
23
|
+
export { fetchOAuth2Metadata };
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=fetch-oauth2-metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-oauth2-metadata.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.ts"],"sourcesContent":["import type { ErrorResponse } from '@scalar/helpers/errors/normalize-error'\nimport { isLocalUrl } from '@scalar/helpers/url/is-local-url'\nimport { redirectToProxy } from '@scalar/helpers/url/redirect-to-proxy'\nimport { coerceValue } from '@scalar/workspace-store/schemas/typebox-coerce'\n\nimport type { CustomFetch } from '@/v2/blocks/operation-block/helpers/send-request'\n\n// RFC 8414 and OIDC share these consumed fields; this alias does not imply OIDC issuer semantics.\nimport {\n type OpenIDConnectDiscovery as AuthorizationServerMetadata,\n OpenIDConnectDiscoverySchema as AuthorizationServerMetadataSchema,\n} from './fetch-openid-connect-discovery'\n\nconst isAllowedMetadataUrl = (url: URL): boolean =>\n url.protocol === 'https:' || (url.protocol === 'http:' && isLocalUrl(url.href))\n\n/** Fetches the exact RFC8414 metadata URL, without applying OIDC issuer URL conventions. */\nexport const fetchOAuth2Metadata = async (\n url: string,\n proxyUrl: string,\n customFetch: CustomFetch = fetch,\n): Promise<ErrorResponse<AuthorizationServerMetadata>> => {\n try {\n const metadataUrl = new URL(url.trim())\n if (!isAllowedMetadataUrl(metadataUrl)) {\n return [new Error('OAuth2 metadata URL must use HTTPS or HTTP for local development URLs'), null]\n }\n const response = await customFetch(redirectToProxy(proxyUrl, metadataUrl.href))\n if (!response.ok) {\n return [new Error(`Failed to fetch OAuth2 metadata: ${response.status} ${response.statusText}`), null]\n }\n const data = coerceValue(AuthorizationServerMetadataSchema, await response.json())\n if (!data.authorization_endpoint && !data.token_endpoint) {\n return [new Error('Invalid OAuth2 metadata: missing or invalid endpoints'), null]\n }\n for (const endpoint of [data.authorization_endpoint, data.token_endpoint]) {\n if (endpoint && !isAllowedMetadataUrl(new URL(endpoint))) {\n return [new Error('OAuth2 metadata endpoints must use HTTPS or HTTP for local development URLs'), null]\n }\n }\n return [null, data]\n } catch (error) {\n return [error instanceof Error ? error : new Error('Failed to fetch OAuth2 metadata'), null]\n }\n}\n"],"mappings":";;;;;AAaA,IAAM,wBAAwB,QAC5B,IAAI,aAAa,YAAa,IAAI,aAAa,WAAW,WAAW,IAAI,IAAI;;AAG/E,IAAa,sBAAsB,OACjC,KACA,UACA,cAA2B,UAC6B;CACxD,IAAI;EACF,MAAM,cAAc,IAAI,IAAI,IAAI,KAAK,CAAC;EACtC,IAAI,CAAC,qBAAqB,WAAW,GACnC,OAAO,iBAAC,IAAI,MAAM,uEAAuE,GAAG,IAAI;EAElG,MAAM,WAAW,MAAM,YAAY,gBAAgB,UAAU,YAAY,IAAI,CAAC;EAC9E,IAAI,CAAC,SAAS,IACZ,OAAO,iBAAC,IAAI,MAAM,oCAAoC,SAAS,OAAO,GAAG,SAAS,YAAY,GAAG,IAAI;EAEvG,MAAM,OAAO,YAAY,8BAAmC,MAAM,SAAS,KAAK,CAAC;EACjF,IAAI,CAAC,KAAK,0BAA0B,CAAC,KAAK,gBACxC,OAAO,iBAAC,IAAI,MAAM,uDAAuD,GAAG,IAAI;EAElF,KAAK,MAAM,YAAY,CAAC,KAAK,wBAAwB,KAAK,cAAc,GACtE,IAAI,YAAY,CAAC,qBAAqB,IAAI,IAAI,QAAQ,CAAC,GACrD,OAAO,iBAAC,IAAI,MAAM,6EAA6E,GAAG,IAAI;EAG1G,OAAO,CAAC,MAAM,IAAI;CACpB,SAAS,OAAO;EACd,OAAO,CAAC,iBAAiB,QAAQ,wBAAQ,IAAI,MAAM,iCAAiC,GAAG,IAAI;CAC7F;AACF"}
|
package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type { CustomFetch } from '../../../../v2/blocks/operation-block/helpers/
|
|
|
7
7
|
*
|
|
8
8
|
* @see https://openid.net/specs/openid-connect-discovery-1_0.html
|
|
9
9
|
*/
|
|
10
|
-
declare const OpenIDConnectDiscoverySchema: import("@scalar/typebox").TObject<{
|
|
10
|
+
export declare const OpenIDConnectDiscoverySchema: import("@scalar/typebox").TObject<{
|
|
11
11
|
/** URL of the OAuth 2.0 Authorization Endpoint */
|
|
12
12
|
authorization_endpoint: import("@scalar/typebox").TOptional<import("@scalar/typebox").TString>;
|
|
13
13
|
/** URL of the OAuth 2.0 Token Endpoint */
|
|
@@ -35,5 +35,4 @@ export declare const OPENID_SCOPE = "openid";
|
|
|
35
35
|
* @returns The discovery document or an error
|
|
36
36
|
*/
|
|
37
37
|
export declare const fetchOpenIDConnectDiscovery: (url: string, proxyUrl: string, customFetch?: CustomFetch) => Promise<ErrorResponse<OpenIDConnectDiscovery>>;
|
|
38
|
-
export {};
|
|
39
38
|
//# sourceMappingURL=fetch-openid-connect-discovery.d.ts.map
|
package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-openid-connect-discovery.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAE3E,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,iBAAiB,CAAA;AAGnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAA;AAEnF;;;;;GAKG;AACH,
|
|
1
|
+
{"version":3,"file":"fetch-openid-connect-discovery.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAE3E,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,iBAAiB,CAAA;AAGnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAA;AAEnF;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B;IACvC,kDAAkD;;IAElD,0CAA0C;;IAE1C,+DAA+D;;IAE/D,oEAAoE;;IAEpE,uDAAuD;;EAEvD,CAAA;AAEF,MAAM,MAAM,sBAAsB,GAAG,MAAM,CAAC,OAAO,4BAA4B,CAAC,CAAA;AAEhF;;;GAGG;AACH,eAAO,MAAM,YAAY,WAAW,CAAA;AAEpC;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,GACtC,KAAK,MAAM,EACX,UAAU,MAAM,EAChB,cAAa,WAAmB,KAC/B,OAAO,CAAC,aAAa,CAAC,sBAAsB,CAAC,CA2C/C,CAAA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { redirectToProxy } from "@scalar/helpers/url/redirect-to-proxy";
|
|
2
|
-
import { Type } from "@scalar/typebox";
|
|
3
2
|
import { coerceValue } from "@scalar/workspace-store/schemas/typebox-coerce";
|
|
3
|
+
import { Type } from "@scalar/typebox";
|
|
4
4
|
//#region src/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.ts
|
|
5
5
|
/**
|
|
6
6
|
* OpenID Connect Discovery Document (subset)
|
|
@@ -46,6 +46,6 @@ var fetchOpenIDConnectDiscovery = async (url, proxyUrl, customFetch = fetch) =>
|
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
48
|
//#endregion
|
|
49
|
-
export { fetchOpenIDConnectDiscovery };
|
|
49
|
+
export { OpenIDConnectDiscoverySchema, fetchOpenIDConnectDiscovery };
|
|
50
50
|
|
|
51
51
|
//# sourceMappingURL=fetch-openid-connect-discovery.js.map
|
package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-openid-connect-discovery.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.ts"],"sourcesContent":["import type { ErrorResponse } from '@scalar/helpers/errors/normalize-error'\nimport { redirectToProxy } from '@scalar/helpers/url/redirect-to-proxy'\nimport { type Static, Type } from '@scalar/typebox'\nimport { coerceValue } from '@scalar/workspace-store/schemas/typebox-coerce'\n\nimport type { CustomFetch } from '@/v2/blocks/operation-block/helpers/send-request'\n\n/**\n * OpenID Connect Discovery Document (subset)\n * Represents the metadata fields consumed by the auth selector flow conversion.\n *\n * @see https://openid.net/specs/openid-connect-discovery-1_0.html\n */\
|
|
1
|
+
{"version":3,"file":"fetch-openid-connect-discovery.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.ts"],"sourcesContent":["import type { ErrorResponse } from '@scalar/helpers/errors/normalize-error'\nimport { redirectToProxy } from '@scalar/helpers/url/redirect-to-proxy'\nimport { type Static, Type } from '@scalar/typebox'\nimport { coerceValue } from '@scalar/workspace-store/schemas/typebox-coerce'\n\nimport type { CustomFetch } from '@/v2/blocks/operation-block/helpers/send-request'\n\n/**\n * OpenID Connect Discovery Document (subset)\n * Represents the metadata fields consumed by the auth selector flow conversion.\n *\n * @see https://openid.net/specs/openid-connect-discovery-1_0.html\n */\nexport const OpenIDConnectDiscoverySchema = Type.Object({\n /** URL of the OAuth 2.0 Authorization Endpoint */\n authorization_endpoint: Type.Optional(Type.String()),\n /** URL of the OAuth 2.0 Token Endpoint */\n token_endpoint: Type.Optional(Type.String()),\n /** List of OAuth 2.0 scope values that this server supports */\n scopes_supported: Type.Optional(Type.Array(Type.String())),\n /** List of OAuth 2.0 grant type values that this server supports */\n grant_types_supported: Type.Optional(Type.Array(Type.String())),\n /** Supported PKCE code challenge methods (RFC 7636) */\n code_challenge_methods_supported: Type.Optional(Type.Array(Type.String())),\n})\n\nexport type OpenIDConnectDiscovery = Static<typeof OpenIDConnectDiscoverySchema>\n\n/**\n * The required scope for OpenID Connect requests.\n * If this scope is present, the request is an OIDC request; otherwise, it is a standard OAuth 2.0 request.\n */\nexport const OPENID_SCOPE = 'openid'\n\n/**\n * Fetches the OpenID Connect discovery document from the specified URL.\n * Supports both full discovery URLs and issuer URLs.\n *\n * @param url - The OpenID Connect discovery URL or issuer URL\n * @param proxyUrl - Optional CORS proxy to route the request through\n * @param customFetch - Fetch used for the discovery request; the desktop app passes an IPC-backed fetch so it leaves the renderer's network stack.\n * @returns The discovery document or an error\n */\nexport const fetchOpenIDConnectDiscovery = async (\n url: string,\n proxyUrl: string,\n customFetch: CustomFetch = fetch,\n): Promise<ErrorResponse<OpenIDConnectDiscovery>> => {\n try {\n // If the URL does not end with the well-known path, append it\n let discoveryUrl = url.trim()\n\n if (!discoveryUrl) {\n return [new Error('URL cannot be empty'), null]\n }\n\n // Remove trailing slash if present\n if (discoveryUrl.endsWith('/')) {\n discoveryUrl = discoveryUrl.slice(0, -1)\n }\n\n // If the URL does not already include the well-known path, append it\n if (!discoveryUrl.includes('/.well-known/openid-configuration')) {\n discoveryUrl = `${discoveryUrl}/.well-known/openid-configuration`\n }\n\n const proxiedUrl = redirectToProxy(proxyUrl, discoveryUrl)\n const response = await customFetch(proxiedUrl)\n\n if (!response.ok) {\n return [\n new Error(`Failed to fetch OpenID Connect discovery document: ${response.status} ${response.statusText}`),\n null,\n ]\n }\n\n const data = coerceValue(OpenIDConnectDiscoverySchema, await response.json())\n\n // Validate that we have the essential fields\n if (!data.authorization_endpoint && !data.token_endpoint) {\n return [new Error('Invalid OpenID Connect discovery document: missing required endpoints'), null]\n }\n\n return [null, data]\n } catch (error) {\n if (error instanceof Error) {\n return [error, null]\n }\n return [new Error('Failed to fetch OpenID Connect discovery document'), null]\n }\n}\n"],"mappings":";;;;;;;;;;AAaA,IAAa,+BAA+B,KAAK,OAAO;;CAEtD,wBAAwB,KAAK,SAAS,KAAK,OAAO,CAAC;;CAEnD,gBAAgB,KAAK,SAAS,KAAK,OAAO,CAAC;;CAE3C,kBAAkB,KAAK,SAAS,KAAK,MAAM,KAAK,OAAO,CAAC,CAAC;;CAEzD,uBAAuB,KAAK,SAAS,KAAK,MAAM,KAAK,OAAO,CAAC,CAAC;;CAE9D,kCAAkC,KAAK,SAAS,KAAK,MAAM,KAAK,OAAO,CAAC,CAAC;AAC3E,CAAC;;;;;;;;;;AAmBD,IAAa,8BAA8B,OACzC,KACA,UACA,cAA2B,UACwB;CACnD,IAAI;EAEF,IAAI,eAAe,IAAI,KAAK;EAE5B,IAAI,CAAC,cACH,OAAO,iBAAC,IAAI,MAAM,qBAAqB,GAAG,IAAI;EAIhD,IAAI,aAAa,SAAS,GAAG,GAC3B,eAAe,aAAa,MAAM,GAAG,EAAE;EAIzC,IAAI,CAAC,aAAa,SAAS,mCAAmC,GAC5D,eAAe,GAAG,aAAa;EAIjC,MAAM,WAAW,MAAM,YADJ,gBAAgB,UAAU,YACV,CAAU;EAE7C,IAAI,CAAC,SAAS,IACZ,OAAO,iBACL,IAAI,MAAM,sDAAsD,SAAS,OAAO,GAAG,SAAS,YAAY,GACxG,IACF;EAGF,MAAM,OAAO,YAAY,8BAA8B,MAAM,SAAS,KAAK,CAAC;EAG5E,IAAI,CAAC,KAAK,0BAA0B,CAAC,KAAK,gBACxC,OAAO,iBAAC,IAAI,MAAM,uEAAuE,GAAG,IAAI;EAGlG,OAAO,CAAC,MAAM,IAAI;CACpB,SAAS,OAAO;EACd,IAAI,iBAAiB,OACnB,OAAO,CAAC,OAAO,IAAI;EAErB,OAAO,iBAAC,IAAI,MAAM,mDAAmD,GAAG,IAAI;CAC9E;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/oauth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAK3E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAA;AAErF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAA;AAGhG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAA;AAanF,KAAK,gBAAgB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;AAE1F,MAAM,MAAM,YAAY,GAAG;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAED;;;;;;;;;;GAUG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,MAAM,EAAE;IAC3C,6EAA6E;IAC7E,gBAAgB,EAAE,MAAM,CAAA;CACzB,KAAK,OAAO,CACX,aAAa,CAAC;IACZ,4FAA4F;IAC5F,WAAW,EAAE,MAAM,CAAA;IACnB,wFAAwF;IACxF,WAAW,EAAE,MAAM,CAAA;CACpB,CAAC,CACH,CAAA;AAED,kEAAkE;AAClE,KAAK,gBAAgB,GAAG,OAAO,CAAC,MAAM,sBAAsB,EAAE,UAAU,CAAC,CAAA;AAEzE;;;GAGG;AACH,eAAO,MAAM,YAAY,GACvB,cAAc,YAAY,GAAG,IAAI,EACjC,uBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,KAChD,MAIA,CAAA;AAEH;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAC9B,cAAc,YAAY,GAAG,IAAI,EACjC,uBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,KAChD,gBAWF,CAAA;AAuCD;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAC1B,OAAO,sBAAsB,EAC7B,MAAM,MAAM,sBAAsB,EAClC,gBAAgB,MAAM,EAAE;AACxB,wEAAwE;AACxE,cAAc,YAAY,GAAG,IAAI;AACjC,kCAAkC;AAClC,UAAU,MAAM;AAChB,6FAA6F;AAC7F,uBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM;AACjD,mHAAmH;AACnH,cAAc,WAAW;AACzB;;;;GAIG;AACH,kBAAkB,qBAAqB,KACtC,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CA6NrC,CAAA;
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/oauth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAK3E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAA;AAErF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAA;AAGhG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAA;AAanF,KAAK,gBAAgB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;AAE1F,MAAM,MAAM,YAAY,GAAG;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAED;;;;;;;;;;GAUG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,MAAM,EAAE;IAC3C,6EAA6E;IAC7E,gBAAgB,EAAE,MAAM,CAAA;CACzB,KAAK,OAAO,CACX,aAAa,CAAC;IACZ,4FAA4F;IAC5F,WAAW,EAAE,MAAM,CAAA;IACnB,wFAAwF;IACxF,WAAW,EAAE,MAAM,CAAA;CACpB,CAAC,CACH,CAAA;AAED,kEAAkE;AAClE,KAAK,gBAAgB,GAAG,OAAO,CAAC,MAAM,sBAAsB,EAAE,UAAU,CAAC,CAAA;AAEzE;;;GAGG;AACH,eAAO,MAAM,YAAY,GACvB,cAAc,YAAY,GAAG,IAAI,EACjC,uBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,KAChD,MAIA,CAAA;AAEH;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAC9B,cAAc,YAAY,GAAG,IAAI,EACjC,uBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,KAChD,gBAWF,CAAA;AAuCD;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAC1B,OAAO,sBAAsB,EAC7B,MAAM,MAAM,sBAAsB,EAClC,gBAAgB,MAAM,EAAE;AACxB,wEAAwE;AACxE,cAAc,YAAY,GAAG,IAAI;AACjC,kCAAkC;AAClC,UAAU,MAAM;AAChB,6FAA6F;AAC7F,uBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM;AACjD,mHAAmH;AACnH,cAAc,WAAW;AACzB;;;;GAIG;AACH,kBAAkB,qBAAqB,KACtC,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CA6NrC,CAAA;AAkJD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAC7B,OAAO,sBAAsB,EAC7B,MAAM,gBAAgB;AACtB,kCAAkC;AAClC,UAAU,MAAM;AAChB,+DAA+D;AAC/D,cAAc,YAAY,GAAG,IAAI;AACjC,2EAA2E;AAC3E,uBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM;AACjD,gIAAgI;AAChI,cAAa,WAAmB,KAC/B,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CAwFrC,CAAA"}
|
|
@@ -92,7 +92,7 @@ var authorizeOauth2 = async (flows, type, selectedScopes, activeServer, proxyUrl
|
|
|
92
92
|
if (!value) return;
|
|
93
93
|
url.searchParams.set(key, value);
|
|
94
94
|
});
|
|
95
|
-
url.searchParams.set("client_id", flow["x-scalar-secret-client-id"]);
|
|
95
|
+
url.searchParams.set("client_id", flow["x-scalar-secret-client-id"].trim());
|
|
96
96
|
url.searchParams.set("state", state);
|
|
97
97
|
if (scopes) url.searchParams.set("scope", scopes);
|
|
98
98
|
if (captureCallback) {
|
|
@@ -168,15 +168,17 @@ var authorizeServers = async (flows, type, scopes, { code, pkce, proxyUrl, custo
|
|
|
168
168
|
if (!flow) return [/* @__PURE__ */ new Error("OAuth2 flow was not defined"), null];
|
|
169
169
|
const formData = new URLSearchParams();
|
|
170
170
|
if (scopes && (type === "clientCredentials" || type === "password")) formData.set("scope", scopes);
|
|
171
|
+
const clientId = flow["x-scalar-secret-client-id"].trim();
|
|
172
|
+
const clientSecret = flow["x-scalar-secret-client-secret"].trim();
|
|
171
173
|
/** Where to add the credentials */
|
|
172
174
|
const addCredentialsToBody = flow["x-scalar-credentials-location"] === "body";
|
|
173
175
|
/**
|
|
174
176
|
* PKCE and client authentication are independent: a confidential client may use both.
|
|
175
177
|
* We send the client_secret whenever one is set, regardless of PKCE (see RFC 9700 Section 2.1.1).
|
|
176
178
|
*/
|
|
177
|
-
const hasClientSecret = Boolean(
|
|
178
|
-
if (addCredentialsToBody || type === "authorizationCode" && !hasClientSecret) formData.set("client_id",
|
|
179
|
-
if (addCredentialsToBody && hasClientSecret) formData.set("client_secret",
|
|
179
|
+
const hasClientSecret = Boolean(clientSecret);
|
|
180
|
+
if (addCredentialsToBody || type === "authorizationCode" && !hasClientSecret) formData.set("client_id", clientId);
|
|
181
|
+
if (addCredentialsToBody && hasClientSecret) formData.set("client_secret", clientSecret);
|
|
180
182
|
if (redirectUri) formData.set("redirect_uri", redirectUri);
|
|
181
183
|
else if ("x-scalar-secret-redirect-uri" in flow && flow["x-scalar-secret-redirect-uri"]) formData.set("redirect_uri", flow["x-scalar-secret-redirect-uri"]);
|
|
182
184
|
if (code) {
|
|
@@ -194,7 +196,7 @@ var authorizeServers = async (flows, type, scopes, { code, pkce, proxyUrl, custo
|
|
|
194
196
|
});
|
|
195
197
|
try {
|
|
196
198
|
const headers = { "Content-Type": "application/x-www-form-urlencoded" };
|
|
197
|
-
if (!addCredentialsToBody && hasClientSecret) headers.Authorization = `Basic ${encode(`${
|
|
199
|
+
if (!addCredentialsToBody && hasClientSecret) headers.Authorization = `Basic ${encode(`${clientId}:${clientSecret}`)}`;
|
|
198
200
|
const tokenUrl = makeUrlAbsolute(flow["x-scalar-secret-token-url"] ?? flow.tokenUrl, getActiveServerBase(activeServer, environmentVariables));
|
|
199
201
|
const responseData = await (await customFetch(shouldUseProxy(proxyUrl, tokenUrl) ? `${proxyUrl}?${new URLSearchParams([["scalar_url", tokenUrl]]).toString()}` : tokenUrl, {
|
|
200
202
|
method: "POST",
|
|
@@ -226,17 +228,19 @@ var refreshOauth2Token = async (flows, type, proxyUrl, activeServer, environment
|
|
|
226
228
|
const formData = new URLSearchParams();
|
|
227
229
|
formData.set("grant_type", "refresh_token");
|
|
228
230
|
formData.set("refresh_token", refreshToken);
|
|
231
|
+
const clientId = flow["x-scalar-secret-client-id"].trim();
|
|
232
|
+
const clientSecret = flow["x-scalar-secret-client-secret"].trim();
|
|
229
233
|
const addCredentialsToBody = flow["x-scalar-credentials-location"] === "body";
|
|
230
234
|
/** A confidential client keeps using its secret on refresh, even when PKCE is enabled. */
|
|
231
|
-
const hasClientSecret = Boolean(
|
|
232
|
-
if (addCredentialsToBody || type === "authorizationCode" && !hasClientSecret) formData.set("client_id",
|
|
233
|
-
if (addCredentialsToBody && hasClientSecret) formData.set("client_secret",
|
|
235
|
+
const hasClientSecret = Boolean(clientSecret);
|
|
236
|
+
if (addCredentialsToBody || type === "authorizationCode" && !hasClientSecret) formData.set("client_id", clientId);
|
|
237
|
+
if (addCredentialsToBody && hasClientSecret) formData.set("client_secret", clientSecret);
|
|
234
238
|
if (flow["x-scalar-security-body"]) Object.entries(flow["x-scalar-security-body"]).forEach(([key, value]) => {
|
|
235
239
|
if (value !== void 0 && value !== null) formData.set(key, String(value));
|
|
236
240
|
});
|
|
237
241
|
try {
|
|
238
242
|
const headers = { "Content-Type": "application/x-www-form-urlencoded" };
|
|
239
|
-
if (!addCredentialsToBody && hasClientSecret) headers.Authorization = `Basic ${encode(`${
|
|
243
|
+
if (!addCredentialsToBody && hasClientSecret) headers.Authorization = `Basic ${encode(`${clientId}:${clientSecret}`)}`;
|
|
240
244
|
const absoluteRefreshUrl = makeUrlAbsolute(flow.refreshUrl || flow["x-scalar-secret-token-url"] || flow.tokenUrl, getActiveServerBase(activeServer, environmentVariables));
|
|
241
245
|
const responseData = await (await customFetch(shouldUseProxy(proxyUrl, absoluteRefreshUrl) ? `${proxyUrl}?${new URLSearchParams([["scalar_url", absoluteRefreshUrl]]).toString()}` : absoluteRefreshUrl, {
|
|
242
246
|
method: "POST",
|