@redocly/redoc-revel 0.139.0-next.4 → 0.139.0-next.6

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 CHANGED
@@ -1,5 +1,34 @@
1
1
  # @redocly/redoc-revel
2
2
 
3
+ ## 0.139.0-next.6
4
+
5
+ ### Minor Changes
6
+
7
+ - 652fdc936d2: Added the ejectable `layouts/CustomContexts.tsx` component that allows to wrap every page of a project in custom React context providers.
8
+
9
+ ### Patch Changes
10
+
11
+ - 1f99eb40dbb: Fixed an issue in the **Try it** console where request body validation reported required `readOnly` properties as missing.
12
+ - d1c8ff2547e: Fixed an issue in the **Try it** console that caused `QUERY` and custom HTTP methods to reach the server as `POST`.
13
+ The console displays an error for `TRACE`, `CONNECT`, and `TRACK` requests, which browsers block.
14
+ - Updated dependencies [652fdc936d2]
15
+ - @redocly/theme@0.71.0-next.3
16
+ - @redocly/api-docs@0.4.0-next.6
17
+
18
+ ## 0.139.0-next.5
19
+
20
+ ### Patch Changes
21
+
22
+ - 715b9d44dcf: Fixed an issue where the sign-in to the authenticated Docs MCP server failed with `Invalid MCP callback` or `invalid_grant`.
23
+ - 498cecc7a30: Fixed an issue where screen readers announced the close button without a name in **Try it** console.
24
+ - 498cecc7a30: Fixed an issue in **Try it** console where pressing <kbd>Space</kbd> on the focused close button did not close the console.
25
+ - 6409d73811e: Fixed the **Close all tabs** action in the **Try it** panel of API docs to ask for confirmation before it closes open requests and discards entered values.
26
+ - 25f78711989: Fixed an issue in the **Try it** console in OpenAPI docs where the first request left out parameters with an empty example value (`''`, `[]`, or `null`) and query parameters with `allowEmptyValue: true`.
27
+ - Updated dependencies [6409d73811e]
28
+ - Updated dependencies [25f78711989]
29
+ - @redocly/theme@0.71.0-next.2
30
+ - @redocly/api-docs@0.4.0-next.5
31
+
3
32
  ## 0.139.0-next.4
4
33
 
5
34
  ### Patch Changes
@@ -59,6 +88,17 @@
59
88
  - @redocly/theme@0.71.0-next.0
60
89
  - @redocly/api-docs@0.4.0-next.0
61
90
 
91
+ ## 0.138.1
92
+
93
+ ### Patch Changes
94
+
95
+ - 05163ee7071: Fixed an issue where page content jumped to the side while long pages were loading.
96
+ - 20996e6bfa6: Fixed an issue where the sign-in to the authenticated Docs MCP server failed with `Invalid MCP callback` or `invalid_grant`.
97
+ - 6bb2e1e62d0: Fixed security vulnerability `CVE-2026-93687` by removing the `braces` dependency.
98
+ - Updated dependencies [05163ee7071]
99
+ - @redocly/theme@0.70.1
100
+ - @redocly/api-docs@0.3.1
101
+
62
102
  ## 0.138.0
63
103
 
64
104
  ### Minor Changes
@@ -1 +1 @@
1
- import*as c from"path";import{DEFAULT_THEME_NAME as i,USER_THEME_ALIAS as f}from"../../constants/common.js";import{logger as k}from"../../server/tools/notifiers/logger.js";import{reporter as T}from"../../server/tools/notifiers/reporter.js";import{resolveTheme as A}from"./resolveTheme.js";import{EntitlementsProvider as F}from"../../server/entitlements/entitlements-provider.js";const v=["markdoc/attributes/code-walkthrough-filesets.ts","markdoc/attributes/code-walkthrough-filters.ts","markdoc/components/CodeWalkthrough/**","markdoc/tags/code-step.ts","markdoc/tags/code-toggle.ts","markdoc/tags/code-walkthrough.ts"],m=["./core/**","./markdoc/**/default.*","**/__mocks__/**","**/index.*","**/utils/**/*","**/__tests__/**/*","**/__snapshots__/**/*","**/*.stories.*","**/variables.*",...v],L=["./components/CatalogClassic/CatalogClassicCard.*","./components/ColorModeSwitcher/**","./components/ReplayGate/**","./components/ReplaySecuritySchemeActions/**","./components/ReplayTopBarActions/**","./components/Feedback/**","./components/Filter/**","./components/Footer/**","./components/LanguagePicker/**","./components/Menu/**","./components/Navbar/**","./components/PageNavigation/**","./components/Product/**","./components/Search/**","./components/NavigationTabs/**","./components/UserMenu/**","./layouts/RootLayout.*","./layouts/NotFound.*","./layouts/Forbidden.*","./layouts/DocumentationLayoutTop.*","./layouts/DocumentationLayoutBottom.*","./icons/**","./markdoc/**","./ext/**"];async function S(t){const[p,r]=t._,{theme:l,force:u,onSuccess:d,onError:g,onOverride:h,config:E}=t,_=F.instance(),s=c.resolve(t["project-dir"]);let o=l;o||(o=i);const n=await A(s,E.plugins||[],o,r);n||await T.panicOnContentError(`Theme ${o} not found. Skipping eject.`);const e=n?.config.ejectIgnore;e&&!Array.isArray(e)&&k.warn("'ejectIgnore' must be of type Array. Skipping.");const a=await _.getPackageEjectIgnore(),y={force:u,onSuccess:d,onError:g,onOverride:h,onlyFiles:o===i?L:void 0,ignoreFiles:Array.isArray(e)?[...e,...a,...m]:[...a,...m]};return{objectType:p,pathToThemeFolder:n?.pluginDirAbsolutePath,pathToPortalCustomThemeFolder:c.resolve(s,f),componentToEject:r,theme:o,options:y}}export{m as DEFAULT_IGNORED_FILES,L as EJECTABLE_FILES,S as default};
1
+ import*as c from"path";import{DEFAULT_THEME_NAME as i,USER_THEME_ALIAS as f}from"../../constants/common.js";import{logger as k}from"../../server/tools/notifiers/logger.js";import{reporter as T}from"../../server/tools/notifiers/reporter.js";import{resolveTheme as A}from"./resolveTheme.js";import{EntitlementsProvider as F}from"../../server/entitlements/entitlements-provider.js";const C=["markdoc/attributes/code-walkthrough-filesets.ts","markdoc/attributes/code-walkthrough-filters.ts","markdoc/components/CodeWalkthrough/**","markdoc/tags/code-step.ts","markdoc/tags/code-toggle.ts","markdoc/tags/code-walkthrough.ts"],m=["./core/**","./markdoc/**/default.*","**/__mocks__/**","**/index.*","**/utils/**/*","**/__tests__/**/*","**/__snapshots__/**/*","**/*.stories.*","**/variables.*",...C],v=["./components/CatalogClassic/CatalogClassicCard.*","./components/ColorModeSwitcher/**","./components/ReplayGate/**","./components/ReplaySecuritySchemeActions/**","./components/ReplayTopBarActions/**","./components/Feedback/**","./components/Filter/**","./components/Footer/**","./components/LanguagePicker/**","./components/Menu/**","./components/Navbar/**","./components/PageNavigation/**","./components/Product/**","./components/Search/**","./components/NavigationTabs/**","./components/UserMenu/**","./layouts/RootLayout.*","./layouts/CustomContexts.*","./layouts/NotFound.*","./layouts/Forbidden.*","./layouts/DocumentationLayoutTop.*","./layouts/DocumentationLayoutBottom.*","./icons/**","./markdoc/**","./ext/**"];async function L(t){const[p,r]=t._,{theme:l,force:u,onSuccess:d,onError:g,onOverride:h,config:E}=t,y=F.instance(),s=c.resolve(t["project-dir"]);let o=l;o||(o=i);const n=await A(s,E.plugins||[],o,r);n||await T.panicOnContentError(`Theme ${o} not found. Skipping eject.`);const e=n?.config.ejectIgnore;e&&!Array.isArray(e)&&k.warn("'ejectIgnore' must be of type Array. Skipping.");const a=await y.getPackageEjectIgnore(),_={force:u,onSuccess:d,onError:g,onOverride:h,onlyFiles:o===i?v:void 0,ignoreFiles:Array.isArray(e)?[...e,...a,...m]:[...a,...m]};return{objectType:p,pathToThemeFolder:n?.pluginDirAbsolutePath,pathToPortalCustomThemeFolder:c.resolve(s,f),componentToEject:r,theme:o,options:_}}export{m as DEFAULT_IGNORED_FILES,v as EJECTABLE_FILES,L as default};
@@ -1 +1 @@
1
- import*as n from"dotenv";import*as a from"path";import{simpleGit as v}from"simple-git";import{envConfig as i,reloadEnvConfig as o}from"../../config/env-config.js";import{sanitizeBranchName as p}from"../../utils/envs/sanitize-branch-name.js";async function m(e){try{return(await v(e??process.cwd()).revparse(["--abbrev-ref","HEAD"])).trim()}catch{return""}}async function d(e){n.config({path:a.resolve(e??"",".env")}),o();const t=i.PUBLIC_REDOCLY_BRANCH_NAME||await m(e);if(t){const s=p(t);n.config({path:a.resolve(e??"",`.env.branch.${s}`),override:!0}),o()}const c=i.REDOCLY_ENV;let r;switch(c){case"production":r=".env.production";break;case"preview":r=".env.preview";break;default:r=".env.development";break}n.config({path:a.resolve(e??"",r),override:!0}),o()}export{d as loadEnvVariables};
1
+ import*as o from"dotenv";import*as n from"path";import{simpleGit as p}from"simple-git";import{envConfig as s,reloadEnvConfig as c,setEnv as m}from"../../config/env-config.js";import{readEnvVariable as f}from"../../utils/envs/read-env-variable.js";import{sanitizeBranchName as E}from"../../utils/envs/sanitize-branch-name.js";async function l(e){try{return(await p(e??process.cwd()).revparse(["--abbrev-ref","HEAD"])).trim()}catch{return""}}const h=["REDOCLY_EXP_REPLAY_GRAPHQL_ENABLED"];async function N(e){const a=Object.fromEntries(h.map(t=>[t,f(t)]));o.config({path:n.resolve(e??"",".env")}),c();const i=s.PUBLIC_REDOCLY_BRANCH_NAME||await l(e);if(i){const t=E(i);o.config({path:n.resolve(e??"",`.env.branch.${t}`),override:!0}),c()}const v=s.REDOCLY_ENV;let r;switch(v){case"production":r=".env.production";break;case"preview":r=".env.preview";break;default:r=".env.development";break}o.config({path:n.resolve(e??"",r),override:!0}),m(a)}export{N as loadEnvVariables};
@@ -1 +1 @@
1
- import{getCookie as H}from"hono/cookie";import{createHash as F,timingSafeEqual as ne}from"node:crypto";import{ulid as oe}from"ulid";import{isRedoclySso as ie,isOidcProviderConfig as R,createMcpAuthorizationCode as se,verifyMcpAuthorizationCode as ae,createMcpRefreshToken as G,verifyMcpRefreshToken as ce,createMcpSessionResource as M,oidcRefreshTokenGrant as de,getOidcMetadata as pe,getUserParamsFromCookies as ue,idTokenIsForThisProject as le}from"../../auth.js";import{isMcpContentProtected as P}from"../../../plugins/mcp/auth/auth-handlers.js";import{resolveSiteBranding as _e}from"../../../plugins/mcp/handlers/credentials-page/site-branding.js";import{SUPPORTED_MCP_SCOPES as E}from"../../../plugins/mcp/constants.js";import{AUTH_URL as fe,JWT_SECRET_KEY as m,MCP_ACCESS_TOKEN_TTL_SEC as b,MCP_REFRESH_SESSION_LIFETIME_SEC as K}from"../../../constants/common.js";import{ServerRoutes as I}from"../../../../constants/api.js";import{AuthCookieNames as v}from"../../../../constants/common.js";import{withPathPrefix as w}from"@redocly/theme/core/utils";import{telemetry as y}from"../../../telemetry/index.js";import{envConfig as q}from"../../../config/env-config.js";import*as C from"../../jwt/jwt.js";import{InternalTokenTypes as O,McpAccessTokenMarker as U}from"../../jwt/token-types.js";import{AlgorithmTypes as A,JwtAlgorithmNotImplemented as he,JwtTokenExpired as me,JwtTokenInvalid as ge,JwtTokenNotBefore as Ce,JwtTokenSignatureMismatched as Te}from"../../jwt/types.js";import{getRequestOrigin as L}from"../../utils/get-request-origin.js";import{encryptClaimValue as B}from"../../../utils/crypto/encrypt-claim-value.js";import{decryptAesGcm as ke}from"../../../utils/crypto/decrypt-aes-gcm.js";import{encryptAesGcm as J}from"../../../utils/crypto/encrypt-aes-gcm.js";import{fetchClientMetadataDocument as Se,isClientMetadataDocumentUrl as j,isRedirectUriRegistered as Ie}from"./mcp-client-metadata.js";import{CONSENT_PAGE_HEADERS as V,MCP_CONSENT_TTL_SEC as we,consentInvalidPage as Me,consentPage as Ee}from"./mcp-consent-page.js";import{MCP_CONSENT_MEMORY_DAYS as ye,hasConsent as Ae,redeemAuthorizationCode as Re,redeemRefreshToken as Pe,saveConsent as ve}from"./mcp-oauth-store.js";const s=(r,e,t=200,n)=>r.json(e,t,{"Content-Type":"application/json",...n??{}}),z=new Set(["S256"]),$=["authorization_code","refresh_token"],Oe="https://claude.ai/oauth/claude-code-client-metadata";function Ue(r,e,t){if(!r||!z.has(e||""))return!1;const n=F("sha256").update(t).digest("base64url"),i=Buffer.from(n),a=Buffer.from(r);return i.length!==a.length?!1:ne(i,a)}async function Le(r){const e=Math.floor(Date.now()/1e3);return C.sign({type:O.MCP_CONTEXT,...r,iat:e,exp:e+600},m,A.HS256)}async function Ne(r){await C.verify(r,m,A.HS256);const{payload:e}=C.decode(r);if(e.type!==O.MCP_CONTEXT)throw new Error("Invalid context token type");return e}function fr(r){return async e=>{if(!P(r))return s(e,{error:"not_found"},404);if(e.req.method!=="GET")return s(e,{error:"Method not allowed"},405,{Allow:"GET"});const t=L(e);return s(e,{resource:`${t}${w("/mcp")}`,authorization_servers:[t],bearer_methods_supported:["header"],resource_documentation:`${t}${I.MCP_OAUTH_AUTHORIZATION_SERVER}`,scopes_supported:[...E],bearer_token_types_supported:["Bearer"]},200,{"Access-Control-Allow-Origin":"*"})}}function hr(r){return async e=>{if(!P(r))return s(e,{error:"not_found"},404);const t=L(e);return s(e,{issuer:t,authorization_endpoint:`${t}${w(I.MCP_AUTHORIZATION)}`,token_endpoint:`${t}${w(I.MCP_TOKEN_PORTAL)}`,scopes_supported:[...E],registration_endpoint:`${t}${w(I.MCP_DYNAMIC_CLIENT_REGISTRATION)}`,response_types_supported:["code"],grant_types_supported:[...$],subject_types_supported:["public"],id_token_signing_alg_values_supported:["RS256"],code_challenge_methods_supported:["S256"],token_endpoint_auth_methods_supported:["none"],client_id_metadata_document_supported:!0},200,{"Access-Control-Allow-Origin":"*"})}}function mr(r){return async e=>{if(!P(r))return s(e,{error:"not_found"},404);if(e.req.method!=="POST")return s(e,{error:"Method not allowed"},405);try{return s(e,{client_id:q.OAUTH_CLIENT_ID||"",client_name:"MCP Client",redirect_uris:[],grant_types:[...$],response_types:["code"],scope:E.join(" "),subject_type:"public",token_endpoint_auth_method:"none",created_at:new Date().toISOString(),updated_at:new Date().toISOString()},201,{"Access-Control-Allow-Origin":"*"})}catch(t){return s(e,{error:"invalid_request",error_description:t?.message||"Unable to register client"},500,{"Access-Control-Allow-Origin":"*"})}}}const De=new Set(["127.0.0.1","localhost","[::1]"]),He=new Set(["http:","https:","ws:","wss:","ftp:","file:"]),be=new Set(["javascript:","data:","blob:","about:","vbscript:","intent:","chrome:","view-source:","ms-msdt:","ms-appx-web:"]),qe=2048,je=/[\s\p{Cc}]/u;function W(r){return r.protocol==="http:"&&De.has(r.hostname)}function Y(r){if(!r||r.length>qe||r.includes("#")||je.test(r))return;const e=URL.parse(r);if(e){if(e.protocol==="https:"||W(e))return r.toLowerCase().startsWith(`${e.protocol}//`)?e:void 0;if(!(He.has(e.protocol)||be.has(e.protocol)))return e}}function Z(r){const e=r||{},t=Object.keys(e),n=t.find(a=>R(e[a])&&ie(e[a])),i=t.find(a=>R(e[a]));return n||i||t[0]}function gr(r){return async e=>{if(!P(r))return s(e,{error:"not_found"},404);const t=new URL(e.req.url),{searchParams:n}=t,i=n.get("redirect_uri"),a=n.get("client_id"),c=n.get("code_challenge"),o=n.get("code_challenge_method"),d=oe();if(!i||!Y(i))return s(e,{error:"invalid_request",error_description:"redirect_uri must be an https URL, a loopback http URL, or a private-use scheme"},400);if(!c)return s(e,{error:"invalid_request",error_description:"code_challenge is required"},400);if(!z.has(o||""))return s(e,{error:"invalid_request",error_description:`Unsupported code_challenge_method. Supported: ${[...z].join(", ")}`},400);let p;if(j(a))try{const u=await Se(a);p=u.client_name;const _=a===Oe;if(!Ie(i,u.redirect_uris,{ignorePort:_}))return s(e,{error:"invalid_request",error_description:"redirect_uri is not registered for this client"},400)}catch(u){const _=u instanceof Error?u.message:String(u);return s(e,{error:"invalid_client",error_description:`Unable to resolve client metadata document: ${_}`},400)}y.sendMcpAuthorizationStartedMessage([{...M(d),redirect_uri:i||null}]);const l=L(e),k={isMcpFlow:!0,originalRedirectUri:i,mcpClientId:a,mcpState:n.get("state"),mcpSessionId:d,mcpCodeChallenge:c,mcpCodeChallengeMethod:o,mcpClientName:p,timestamp:Date.now()};try{const u=await Le(k),_=new URL(w(I.IDP_LOGIN),l);_.searchParams.set("redirectTo",`${I.MCP_CALLBACK}/${u}`);const h=Z(r.getConfig().ssoDirect);return h?(_.searchParams.set("idpId",h),e.redirect(_.toString())):s(e,{error:"not_found"},404)}catch(u){const _=u instanceof Error?u.message:String(u),h=u instanceof Error?u.stack:String(u);y.sendMcpAuthorizationFailedMessage([{...M(d),error:_,error_details:h}]);const S=new URL(w(`${fe}/oauth2/auth`));return S.search=n.toString(),e.redirect(S.toString())}}}async function X(r){const e=Math.floor(Date.now()/1e3),t=r.ttlSec?e+r.ttlSec:Math.min(typeof r.claims.exp=="number"?r.claims.exp:1/0,e+b);return{accessToken:await C.sign({...r.claims,[U.CLAIM]:U.VALUE,...r.idpId?{idpId:r.idpId}:{},...r.idpAccessTokenEnc?{idp_access_token:r.idpAccessTokenEnc}:{},...r.ttlSec?{iat:e}:{},exp:t},m,A.HS256,r.kid),expiresIn:Math.max(t-e,0)}}async function ze(r,e,t){const n=T=>s(r,{error:"invalid_grant",error_description:T},400),i=r.get("logger"),a=t.get("refresh_token"),c=t.get("client_id")||void 0;if(!a)return s(r,{error:"invalid_request",error_description:"refresh_token is required"},400);let o;try{o=await ce(a)}catch(T){return i?.warn("MCP refresh token rejected: %s",T instanceof Error?T.message:String(T)),n("Invalid refresh token")}if(c&&c!==o.client_id)return n("Client mismatch");const d=o.idp_id?e.getConfig().ssoDirect?.[o.idp_id]:void 0;let p,l,k=o.idp_access_token_enc,u=o.idp_refresh_token_enc;if(o.idp_refresh_token_enc){let T;try{T=ke(o.idp_refresh_token_enc,m)}catch{return n("Invalid refresh token")}if(!o.idp_id||!R(d))return n("Unknown identity provider");let f;try{const g=await pe(o.idp_id,d);if(!g?.token_endpoint)return n("Identity provider has no token endpoint");f=await de(g.token_endpoint,T,d)}catch(g){return i?.warn("MCP refresh failed to reach the IdP token endpoint: %s",g instanceof Error?g.message:String(g)),s(r,{error:"server_error",error_description:"Failed to refresh session"},500)}if(f.error||!(f.id_token||f.access_token))return i?.warn("MCP refresh rejected by IdP: %s",f.error||"empty token response"),n("Refresh rejected by identity provider");if(f.refresh_token&&(u=J(f.refresh_token,m)),f.access_token&&(k=B(f.access_token,m)),f.id_token){try{const g=C.decode(f.id_token);p=g.payload,l=g.header.kid}catch{return n("Invalid token response from identity provider")}if(p.iss!==o.claims.iss||p.sub!==o.claims.sub)return i?.warn("MCP refresh rejected: the id_token names another issuer or subject"),n("Invalid refresh token")}}const _=Math.min(R(d)&&d.tokenExpirationTime||b,b),h=p??o.claims;if(!le(h,d))return i?.warn("MCP refresh rejected: the id_token was issued for another project"),n("Invalid refresh token");if(!await Pe(await e.getKv(),a,o.exp))return i?.warn("MCP refresh rejected: the refresh token was already used"),n("Refresh token already used");const S=await X({claims:h,kid:l,idpId:o.idp_id,idpAccessTokenEnc:k,ttlSec:p?void 0:_}),D=await G({clientId:o.client_id,idpId:o.idp_id,claims:h,idpAccessTokenEnc:k,idpRefreshTokenEnc:u,sessionExp:o.session_exp});return s(r,{access_token:S.accessToken,token_type:"Bearer",expires_in:S.expiresIn,refresh_token:D,scope:E.join(" ")},200,{"Cache-Control":"no-store",Pragma:"no-cache"})}function Cr(r){return async e=>{if(e.req.method!=="POST")return s(e,{error:"Method not allowed"},405);try{const t=await e.req.formData(),n=t.get("grant_type"),i=t.get("code"),a=t.get("redirect_uri")||void 0,c=t.get("code_verifier")||void 0;if(!$.includes(n))return s(e,{error:"invalid_request",error_description:"Invalid grant type"},400);if(n==="refresh_token")return await ze(e,r,t);if(!i)return s(e,{error:"invalid_request",error_description:"Missing authorization code"},400);try{const o=await ae(i);if(a&&a!==o.redirect_uri)return s(e,{error:"invalid_grant",error_description:"redirect_uri mismatch"},400);if(!c)return s(e,{error:"invalid_grant",error_description:"code_verifier required"},400);if(!Ue(o.code_challenge,o.code_challenge_method,c))return s(e,{error:"invalid_grant",error_description:"code_verifier mismatch"},400);if(q.OAUTH_CLIENT_ID&&o.client_id&&!j(o.client_id)&&o.client_id!==q.OAUTH_CLIENT_ID)return s(e,{error:"invalid_client",error_description:"Client mismatch"},400);const d=o.id_token;if(typeof d!="string"||d.length===0)return s(e,{error:"invalid_grant",error_description:"Missing id_token in authorization code"},400);const p=await Q(d,r.getConfig().ssoDirect);if(!p)return s(e,{error:"invalid_grant",error_description:"Invalid authorization code"},400);if(!await Re(await r.getKv(),i,o.exp))return s(e,{error:"invalid_grant",error_description:"Authorization code already used"},400);const l=o.idp_access_token_enc,{accessToken:k,expiresIn:u}=await X({claims:p.payload,kid:p.kid,idpId:o.idp_id,idpAccessTokenEnc:l}),h=Math.floor(Date.now()/1e3)+K,S=await G({clientId:o.client_id,idpId:o.idp_id,claims:p.payload,idpAccessTokenEnc:l,idpRefreshTokenEnc:o.idp_refresh_token_enc,sessionExp:h}),D={access_token:k,token_type:"Bearer",expires_in:u,refresh_token:S,scope:E.join(" ")};return s(e,D,200,{"Cache-Control":"no-store",Pragma:"no-cache"})}catch(o){return e.get("logger")?.warn("MCP token exchange failed: %s",o instanceof Error?o.message:String(o)),s(e,{error:"invalid_grant",error_description:"Invalid authorization code"},400)}}catch(t){const n=t instanceof Error?t.message:String(t);return s(e,{error:"server_error",error_description:"Failed to process token request",error_details:n},500)}}}async function Q(r,e){const t=await ue(e||{},{[v.AUTHORIZATION]:r});if(t.isAuthenticated!==!0)return;const{payload:n,header:i}=C.decode(r);if(n[U.CLAIM]!==U.VALUE)return{payload:n,kid:i.kid,idpId:typeof t.idpId=="string"?t.idpId:void 0}}function N(r){return F("sha256").update(r).digest("base64url")}async function $e(r){const e=Math.floor(Date.now()/1e3);return C.sign({type:O.MCP_CONSENT,session_hash:N(r.sessionToken),context_hash:N(r.contextToken),iat:e,exp:e+we},m,A.HS256)}async function Fe(r,e){try{await C.verify(r,m,A.HS256)}catch{return!1}const{payload:t}=C.decode(r);return t.type===O.MCP_CONSENT&&t.session_hash===N(e.sessionToken)&&t.context_hash===N(e.contextToken)}function x(r,e){return async t=>{const n=new URL(t.req.url);let i=n.searchParams.get("context");if(!i&&n.pathname.startsWith(w(`${I.MCP_CALLBACK}/`))){const c=n.pathname.split("/");i=c[c.length-1]}if(!i)return t.text("Missing context parameter",400);let a=null;try{const c=await Ne(i);a=c.mcpSessionId||null;const o=c.originalRedirectUri,d=Y(o);if(!c.isMcpFlow||!o||!d)throw new Error("Invalid MCP context");const p=H(t,v.AUTHORIZATION),l=p?await Q(p,r.getConfig().ssoDirect):void 0;return!p||!l?(y.sendMcpAuthorizationFailedMessage([{...M(a),error:"Authentication required",error_details:null}]),t.text("Authentication required",401)):await e(t,{contextToken:i,mcpContext:c,redirectUri:o,redirectUrl:d,sessionToken:p,session:l})}catch(c){const o=Be(c);return y.sendMcpAuthorizationFailedMessage([{...M(a),...o}]),t.text(`Invalid MCP callback: ${o.error}`,400)}}}async function ee(r,e,{mcpContext:t,redirectUri:n,redirectUrl:i,sessionToken:a,session:c}){const o=H(r,v.IDP_ACCESS_TOKEN),d=H(r,v.IDP_REFRESH_TOKEN),p=await se({idToken:a,idpId:c.idpId??Z(e.getConfig().ssoDirect),idpAccessTokenEnc:o?B(o,m):void 0,idpRefreshTokenEnc:d?J(d,m):void 0,clientId:t.mcpClientId||"",redirectUri:n,codeChallenge:t.mcpCodeChallenge||void 0,codeChallengeMethod:t.mcpCodeChallengeMethod||void 0,ttlSec:600}),l=new URL(i);return l.searchParams.set("code",p),t.mcpState&&l.searchParams.set("state",t.mcpState),y.sendMcpAuthorizationCompletedMessage([{...M(t.mcpSessionId||null),redirect_uri:n}]),r.redirect(l.toString())}function Ge(r,{mcpContext:e,redirectUrl:t}){const n=new URL(t);return n.searchParams.set("error","access_denied"),e.mcpState&&n.searchParams.set("state",e.mcpState),y.sendMcpAuthorizationFailedMessage([{...M(e.mcpSessionId||null),error:"access_denied",error_details:null}]),r.redirect(n.toString())}function Ke({payload:r}){return[r.email,r.name,r.sub].find(e=>typeof e=="string"&&e.length>0)}function re({mcpContext:r,redirectUri:e,session:t}){const{sub:n}=t.payload;if(!(typeof n!="string"||n.length===0))return{idpId:t.idpId,subject:n,clientId:r.mcpClientId||"",redirectUri:e}}function te(r,e){const{seo:t,colorMode:n}=e.getConfig(),{logo:i}=e.getGlobalData();return{..._e({seo:t,logo:i,colorMode:n}),host:new URL(L(r)).host}}function Tr(r){return x(r,async(e,t)=>{const n=re(t);if(W(t.redirectUrl)||n&&await Ae(await r.getKv(),n))return ee(e,r,t);const{mcpClientId:i,mcpClientName:a}=t.mcpContext,c=Ee({site:te(e,r),user:Ke(t.session),clientName:a||void 0,clientIdHost:j(i)?new URL(i).host:void 0,redirectUrl:t.redirectUrl,scopes:E,accessLifetimeHours:K/3600,rememberDays:n?ye:void 0,consentToken:await $e(t)});return new Response(c,{status:200,headers:V})})}function kr(r){return x(r,async(e,t)=>{const n=await e.req.formData(),i=n.get("consent");if(typeof i!="string"||!await Fe(i,t))return new Response(Me(te(e,r)),{status:403,headers:V});if(n.get("decision")==="allow"){const a=re(t);return a&&await ve(await r.getKv(),a),ee(e,r,t)}return Ge(e,t)})}function Be(r){return r instanceof Error&&[he,me,ge,Ce,Te].some(e=>r instanceof e)?{error:r.name,error_details:null}:r instanceof Error?{error:r.message,error_details:r.stack??null}:{error:String(r),error_details:null}}export{$ as SUPPORTED_MCP_GRANT_TYPES,Le as createMcpContextToken,gr as mcpAuthorizationHandler,Tr as mcpCallbackHandler,kr as mcpConsentHandler,mr as mcpDynamicClientRegistrationHandler,hr as mcpOAuthAuthorizationServerHandler,fr as mcpOAuthProtectedResourceHandler,Cr as mcpTokenPortalHandler,Z as resolveMcpIdpId,Ne as verifyAndParseMcpContextToken,Ue as verifyPkce};
1
+ import{getCookie as H}from"hono/cookie";import{createHash as G,timingSafeEqual as oe}from"node:crypto";import{ulid as ie}from"ulid";import{isRedoclySso as se,isOidcProviderConfig as P,createMcpAuthorizationCode as ae,verifyMcpAuthorizationCode as ce,createMcpRefreshToken as K,verifyMcpRefreshToken as de,createMcpSessionResource as M,oidcRefreshTokenGrant as pe,getOidcMetadata as ue,getUserParamsFromCookies as le,idTokenIsForThisProject as _e}from"../../auth.js";import{isMcpContentProtected as R}from"../../../plugins/mcp/auth/auth-handlers.js";import{resolveSiteBranding as fe}from"../../../plugins/mcp/handlers/credentials-page/site-branding.js";import{SUPPORTED_MCP_SCOPES as E}from"../../../plugins/mcp/constants.js";import{AUTH_URL as he,JWT_SECRET_KEY as m,MCP_ACCESS_TOKEN_TTL_SEC as b,MCP_REFRESH_SESSION_LIFETIME_SEC as B}from"../../../constants/common.js";import{ServerRoutes as I}from"../../../../constants/api.js";import{AuthCookieNames as v}from"../../../../constants/common.js";import{withPathPrefix as w}from"@redocly/theme/core/utils";import{telemetry as y}from"../../../telemetry/index.js";import{envConfig as q}from"../../../config/env-config.js";import{hasProjectDatabase as j}from"../../../providers/database/has-project-database.js";import*as C from"../../jwt/jwt.js";import{InternalTokenTypes as O,McpAccessTokenMarker as U}from"../../jwt/token-types.js";import{AlgorithmTypes as A,JwtAlgorithmNotImplemented as me,JwtTokenExpired as ge,JwtTokenInvalid as Ce,JwtTokenNotBefore as Te,JwtTokenSignatureMismatched as ke}from"../../jwt/types.js";import{getRequestOrigin as L}from"../../utils/get-request-origin.js";import{encryptClaimValue as J}from"../../../utils/crypto/encrypt-claim-value.js";import{decryptAesGcm as Se}from"../../../utils/crypto/decrypt-aes-gcm.js";import{encryptAesGcm as V}from"../../../utils/crypto/encrypt-aes-gcm.js";import{fetchClientMetadataDocument as Ie,isClientMetadataDocumentUrl as z,isRedirectUriRegistered as we}from"./mcp-client-metadata.js";import{CONSENT_PAGE_HEADERS as W,MCP_CONSENT_TTL_SEC as Me,consentInvalidPage as Ee,consentPage as ye}from"./mcp-consent-page.js";import{MCP_CONSENT_MEMORY_DAYS as Ae,hasConsent as Pe,redeemAuthorizationCode as Re,redeemRefreshToken as ve,saveConsent as Oe}from"./mcp-oauth-store.js";const s=(r,e,t=200,n)=>r.json(e,t,{"Content-Type":"application/json",...n??{}}),$=new Set(["S256"]),F=["authorization_code","refresh_token"],Ue="https://claude.ai/oauth/claude-code-client-metadata";function Le(r,e,t){if(!r||!$.has(e||""))return!1;const n=G("sha256").update(t).digest("base64url"),i=Buffer.from(n),a=Buffer.from(r);return i.length!==a.length?!1:oe(i,a)}async function Ne(r){const e=Math.floor(Date.now()/1e3);return C.sign({type:O.MCP_CONTEXT,...r,iat:e,exp:e+600},m,A.HS256)}async function De(r){await C.verify(r,m,A.HS256);const{payload:e}=C.decode(r);if(e.type!==O.MCP_CONTEXT)throw new Error("Invalid context token type");return e}function mr(r){return async e=>{if(!R(r))return s(e,{error:"not_found"},404);if(e.req.method!=="GET")return s(e,{error:"Method not allowed"},405,{Allow:"GET"});const t=L(e);return s(e,{resource:`${t}${w("/mcp")}`,authorization_servers:[t],bearer_methods_supported:["header"],resource_documentation:`${t}${I.MCP_OAUTH_AUTHORIZATION_SERVER}`,scopes_supported:[...E],bearer_token_types_supported:["Bearer"]},200,{"Access-Control-Allow-Origin":"*"})}}function gr(r){return async e=>{if(!R(r))return s(e,{error:"not_found"},404);const t=L(e);return s(e,{issuer:t,authorization_endpoint:`${t}${w(I.MCP_AUTHORIZATION)}`,token_endpoint:`${t}${w(I.MCP_TOKEN_PORTAL)}`,scopes_supported:[...E],registration_endpoint:`${t}${w(I.MCP_DYNAMIC_CLIENT_REGISTRATION)}`,response_types_supported:["code"],grant_types_supported:[...F],subject_types_supported:["public"],id_token_signing_alg_values_supported:["RS256"],code_challenge_methods_supported:["S256"],token_endpoint_auth_methods_supported:["none"],client_id_metadata_document_supported:!0},200,{"Access-Control-Allow-Origin":"*"})}}function Cr(r){return async e=>{if(!R(r))return s(e,{error:"not_found"},404);if(e.req.method!=="POST")return s(e,{error:"Method not allowed"},405);try{return s(e,{client_id:q.OAUTH_CLIENT_ID||"",client_name:"MCP Client",redirect_uris:[],grant_types:[...F],response_types:["code"],scope:E.join(" "),subject_type:"public",token_endpoint_auth_method:"none",created_at:new Date().toISOString(),updated_at:new Date().toISOString()},201,{"Access-Control-Allow-Origin":"*"})}catch(t){return s(e,{error:"invalid_request",error_description:t?.message||"Unable to register client"},500,{"Access-Control-Allow-Origin":"*"})}}}const He=new Set(["127.0.0.1","localhost","[::1]"]),be=new Set(["http:","https:","ws:","wss:","ftp:","file:"]),qe=new Set(["javascript:","data:","blob:","about:","vbscript:","intent:","chrome:","view-source:","ms-msdt:","ms-appx-web:"]),je=2048,ze=/[\s\p{Cc}]/u;function Y(r){return r.protocol==="http:"&&He.has(r.hostname)}function Z(r){if(!r||r.length>je||r.includes("#")||ze.test(r))return;const e=URL.parse(r);if(e){if(e.protocol==="https:"||Y(e))return r.toLowerCase().startsWith(`${e.protocol}//`)?e:void 0;if(!(be.has(e.protocol)||qe.has(e.protocol)))return e}}function X(r){const e=r||{},t=Object.keys(e),n=t.find(a=>P(e[a])&&se(e[a])),i=t.find(a=>P(e[a]));return n||i||t[0]}function Tr(r){return async e=>{if(!R(r))return s(e,{error:"not_found"},404);const t=new URL(e.req.url),{searchParams:n}=t,i=n.get("redirect_uri"),a=n.get("client_id"),c=n.get("code_challenge"),o=n.get("code_challenge_method"),d=ie();if(!i||!Z(i))return s(e,{error:"invalid_request",error_description:"redirect_uri must be an https URL, a loopback http URL, or a private-use scheme"},400);if(!c)return s(e,{error:"invalid_request",error_description:"code_challenge is required"},400);if(!$.has(o||""))return s(e,{error:"invalid_request",error_description:`Unsupported code_challenge_method. Supported: ${[...$].join(", ")}`},400);let p;if(z(a))try{const u=await Ie(a);p=u.client_name;const _=a===Ue;if(!we(i,u.redirect_uris,{ignorePort:_}))return s(e,{error:"invalid_request",error_description:"redirect_uri is not registered for this client"},400)}catch(u){const _=u instanceof Error?u.message:String(u);return s(e,{error:"invalid_client",error_description:`Unable to resolve client metadata document: ${_}`},400)}y.sendMcpAuthorizationStartedMessage([{...M(d),redirect_uri:i||null}]);const l=L(e),k={isMcpFlow:!0,originalRedirectUri:i,mcpClientId:a,mcpState:n.get("state"),mcpSessionId:d,mcpCodeChallenge:c,mcpCodeChallengeMethod:o,mcpClientName:p,timestamp:Date.now()};try{const u=await Ne(k),_=new URL(w(I.IDP_LOGIN),l);_.searchParams.set("redirectTo",`${I.MCP_CALLBACK}/${u}`);const h=X(r.getConfig().ssoDirect);return h?(_.searchParams.set("idpId",h),e.redirect(_.toString())):s(e,{error:"not_found"},404)}catch(u){const _=u instanceof Error?u.message:String(u),h=u instanceof Error?u.stack:String(u);y.sendMcpAuthorizationFailedMessage([{...M(d),error:_,error_details:h}]);const S=new URL(w(`${he}/oauth2/auth`));return S.search=n.toString(),e.redirect(S.toString())}}}async function Q(r){const e=Math.floor(Date.now()/1e3),t=r.ttlSec?e+r.ttlSec:Math.min(typeof r.claims.exp=="number"?r.claims.exp:1/0,e+b);return{accessToken:await C.sign({...r.claims,[U.CLAIM]:U.VALUE,...r.idpId?{idpId:r.idpId}:{},...r.idpAccessTokenEnc?{idp_access_token:r.idpAccessTokenEnc}:{},...r.ttlSec?{iat:e}:{},exp:t},m,A.HS256,r.kid),expiresIn:Math.max(t-e,0)}}async function $e(r,e,t){const n=T=>s(r,{error:"invalid_grant",error_description:T},400),i=r.get("logger"),a=t.get("refresh_token"),c=t.get("client_id")||void 0;if(!a)return s(r,{error:"invalid_request",error_description:"refresh_token is required"},400);let o;try{o=await de(a)}catch(T){return i?.warn("MCP refresh token rejected: %s",T instanceof Error?T.message:String(T)),n("Invalid refresh token")}if(c&&c!==o.client_id)return n("Client mismatch");const d=o.idp_id?e.getConfig().ssoDirect?.[o.idp_id]:void 0;let p,l,k=o.idp_access_token_enc,u=o.idp_refresh_token_enc;if(o.idp_refresh_token_enc){let T;try{T=Se(o.idp_refresh_token_enc,m)}catch{return n("Invalid refresh token")}if(!o.idp_id||!P(d))return n("Unknown identity provider");let f;try{const g=await ue(o.idp_id,d);if(!g?.token_endpoint)return n("Identity provider has no token endpoint");f=await pe(g.token_endpoint,T,d)}catch(g){return i?.warn("MCP refresh failed to reach the IdP token endpoint: %s",g instanceof Error?g.message:String(g)),s(r,{error:"server_error",error_description:"Failed to refresh session"},500)}if(f.error||!(f.id_token||f.access_token))return i?.warn("MCP refresh rejected by IdP: %s",f.error||"empty token response"),n("Refresh rejected by identity provider");if(f.refresh_token&&(u=V(f.refresh_token,m)),f.access_token&&(k=J(f.access_token,m)),f.id_token){try{const g=C.decode(f.id_token);p=g.payload,l=g.header.kid}catch{return n("Invalid token response from identity provider")}if(p.iss!==o.claims.iss||p.sub!==o.claims.sub)return i?.warn("MCP refresh rejected: the id_token names another issuer or subject"),n("Invalid refresh token")}}const _=Math.min(P(d)&&d.tokenExpirationTime||b,b),h=p??o.claims;if(!_e(h,d))return i?.warn("MCP refresh rejected: the id_token was issued for another project"),n("Invalid refresh token");if(j()&&!await ve(await e.getKv(),a,o.exp))return i?.warn("MCP refresh rejected: the refresh token was already used"),n("Refresh token already used");const S=await Q({claims:h,kid:l,idpId:o.idp_id,idpAccessTokenEnc:k,ttlSec:p?void 0:_}),D=await K({clientId:o.client_id,idpId:o.idp_id,claims:h,idpAccessTokenEnc:k,idpRefreshTokenEnc:u,sessionExp:o.session_exp});return s(r,{access_token:S.accessToken,token_type:"Bearer",expires_in:S.expiresIn,refresh_token:D,scope:E.join(" ")},200,{"Cache-Control":"no-store",Pragma:"no-cache"})}function kr(r){return async e=>{if(e.req.method!=="POST")return s(e,{error:"Method not allowed"},405);try{const t=await e.req.formData(),n=t.get("grant_type"),i=t.get("code"),a=t.get("redirect_uri")||void 0,c=t.get("code_verifier")||void 0;if(!F.includes(n))return s(e,{error:"invalid_request",error_description:"Invalid grant type"},400);if(n==="refresh_token")return await $e(e,r,t);if(!i)return s(e,{error:"invalid_request",error_description:"Missing authorization code"},400);try{const o=await ce(i);if(a&&a!==o.redirect_uri)return s(e,{error:"invalid_grant",error_description:"redirect_uri mismatch"},400);if(!c)return s(e,{error:"invalid_grant",error_description:"code_verifier required"},400);if(!Le(o.code_challenge,o.code_challenge_method,c))return s(e,{error:"invalid_grant",error_description:"code_verifier mismatch"},400);if(q.OAUTH_CLIENT_ID&&o.client_id&&!z(o.client_id)&&o.client_id!==q.OAUTH_CLIENT_ID)return s(e,{error:"invalid_client",error_description:"Client mismatch"},400);const d=o.id_token;if(typeof d!="string"||d.length===0)return s(e,{error:"invalid_grant",error_description:"Missing id_token in authorization code"},400);const p=await x(d,r.getConfig().ssoDirect);if(!p)return s(e,{error:"invalid_grant",error_description:"Invalid authorization code"},400);if(j()&&!await Re(await r.getKv(),i,o.exp))return s(e,{error:"invalid_grant",error_description:"Authorization code already used"},400);const l=o.idp_access_token_enc,{accessToken:k,expiresIn:u}=await Q({claims:p.payload,kid:p.kid,idpId:o.idp_id,idpAccessTokenEnc:l}),h=Math.floor(Date.now()/1e3)+B,S=await K({clientId:o.client_id,idpId:o.idp_id,claims:p.payload,idpAccessTokenEnc:l,idpRefreshTokenEnc:o.idp_refresh_token_enc,sessionExp:h}),D={access_token:k,token_type:"Bearer",expires_in:u,refresh_token:S,scope:E.join(" ")};return s(e,D,200,{"Cache-Control":"no-store",Pragma:"no-cache"})}catch(o){return e.get("logger")?.warn("MCP token exchange failed: %s",o instanceof Error?o.message:String(o)),s(e,{error:"invalid_grant",error_description:"Invalid authorization code"},400)}}catch(t){const n=t instanceof Error?t.message:String(t);return s(e,{error:"server_error",error_description:"Failed to process token request",error_details:n},500)}}}async function x(r,e){const t=await le(e||{},{[v.AUTHORIZATION]:r});if(t.isAuthenticated!==!0)return;const{payload:n,header:i}=C.decode(r);if(n[U.CLAIM]!==U.VALUE)return{payload:n,kid:i.kid,idpId:typeof t.idpId=="string"?t.idpId:void 0}}function N(r){return G("sha256").update(r).digest("base64url")}async function Fe(r){const e=Math.floor(Date.now()/1e3);return C.sign({type:O.MCP_CONSENT,session_hash:N(r.sessionToken),context_hash:N(r.contextToken),iat:e,exp:e+Me},m,A.HS256)}async function Ge(r,e){try{await C.verify(r,m,A.HS256)}catch{return!1}const{payload:t}=C.decode(r);return t.type===O.MCP_CONSENT&&t.session_hash===N(e.sessionToken)&&t.context_hash===N(e.contextToken)}function ee(r,e){return async t=>{const n=new URL(t.req.url);let i=n.searchParams.get("context");if(!i&&n.pathname.startsWith(w(`${I.MCP_CALLBACK}/`))){const c=n.pathname.split("/");i=c[c.length-1]}if(!i)return t.text("Missing context parameter",400);let a=null;try{const c=await De(i);a=c.mcpSessionId||null;const o=c.originalRedirectUri,d=Z(o);if(!c.isMcpFlow||!o||!d)throw new Error("Invalid MCP context");const p=H(t,v.AUTHORIZATION),l=p?await x(p,r.getConfig().ssoDirect):void 0;return!p||!l?(y.sendMcpAuthorizationFailedMessage([{...M(a),error:"Authentication required",error_details:null}]),t.text("Authentication required",401)):await e(t,{contextToken:i,mcpContext:c,redirectUri:o,redirectUrl:d,sessionToken:p,session:l})}catch(c){const o=Je(c);return y.sendMcpAuthorizationFailedMessage([{...M(a),...o}]),t.text(`Invalid MCP callback: ${o.error}`,400)}}}async function re(r,e,{mcpContext:t,redirectUri:n,redirectUrl:i,sessionToken:a,session:c}){const o=H(r,v.IDP_ACCESS_TOKEN),d=H(r,v.IDP_REFRESH_TOKEN),p=await ae({idToken:a,idpId:c.idpId??X(e.getConfig().ssoDirect),idpAccessTokenEnc:o?J(o,m):void 0,idpRefreshTokenEnc:d?V(d,m):void 0,clientId:t.mcpClientId||"",redirectUri:n,codeChallenge:t.mcpCodeChallenge||void 0,codeChallengeMethod:t.mcpCodeChallengeMethod||void 0,ttlSec:600}),l=new URL(i);return l.searchParams.set("code",p),t.mcpState&&l.searchParams.set("state",t.mcpState),y.sendMcpAuthorizationCompletedMessage([{...M(t.mcpSessionId||null),redirect_uri:n}]),r.redirect(l.toString())}function Ke(r,{mcpContext:e,redirectUrl:t}){const n=new URL(t);return n.searchParams.set("error","access_denied"),e.mcpState&&n.searchParams.set("state",e.mcpState),y.sendMcpAuthorizationFailedMessage([{...M(e.mcpSessionId||null),error:"access_denied",error_details:null}]),r.redirect(n.toString())}function Be({payload:r}){return[r.email,r.name,r.sub].find(e=>typeof e=="string"&&e.length>0)}function te({mcpContext:r,redirectUri:e,session:t}){const{sub:n}=t.payload;if(!(!j()||typeof n!="string"||n.length===0))return{idpId:t.idpId,subject:n,clientId:r.mcpClientId||"",redirectUri:e}}function ne(r,e){const{seo:t,colorMode:n}=e.getConfig(),{logo:i}=e.getGlobalData();return{...fe({seo:t,logo:i,colorMode:n}),host:new URL(L(r)).host}}function Sr(r){return ee(r,async(e,t)=>{const n=te(t);if(Y(t.redirectUrl)||n&&await Pe(await r.getKv(),n))return re(e,r,t);const{mcpClientId:i,mcpClientName:a}=t.mcpContext,c=ye({site:ne(e,r),user:Be(t.session),clientName:a||void 0,clientIdHost:z(i)?new URL(i).host:void 0,redirectUrl:t.redirectUrl,scopes:E,accessLifetimeHours:B/3600,rememberDays:n?Ae:void 0,consentToken:await Fe(t)});return new Response(c,{status:200,headers:W})})}function Ir(r){return ee(r,async(e,t)=>{const n=await e.req.formData(),i=n.get("consent");if(typeof i!="string"||!await Ge(i,t))return new Response(Ee(ne(e,r)),{status:403,headers:W});if(n.get("decision")==="allow"){const a=te(t);return a&&await Oe(await r.getKv(),a),re(e,r,t)}return Ke(e,t)})}function Je(r){return r instanceof Error&&[me,ge,Ce,Te,ke].some(e=>r instanceof e)?{error:r.name,error_details:null}:r instanceof Error?{error:r.message,error_details:r.stack??null}:{error:String(r),error_details:null}}export{F as SUPPORTED_MCP_GRANT_TYPES,Ne as createMcpContextToken,Tr as mcpAuthorizationHandler,Sr as mcpCallbackHandler,Ir as mcpConsentHandler,Cr as mcpDynamicClientRegistrationHandler,gr as mcpOAuthAuthorizationServerHandler,mr as mcpOAuthProtectedResourceHandler,kr as mcpTokenPortalHandler,X as resolveMcpIdpId,De as verifyAndParseMcpContextToken,Le as verifyPkce};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/redoc-revel",
3
- "version": "0.139.0-next.4",
3
+ "version": "0.139.0-next.6",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "bin": {
@@ -33,13 +33,13 @@
33
33
  "@opentelemetry/sdk-trace-web": "2.8.0",
34
34
  "@opentelemetry/semantic-conventions": "1.40.0",
35
35
  "@redocly/ajv": "8.18.0",
36
- "@redocly/api-docs": "0.4.0-next.4",
37
- "@redocly/config": "0.65.0",
36
+ "@redocly/api-docs": "0.4.0-next.6",
37
+ "@redocly/config": "0.66.0",
38
38
  "@redocly/openapi-core": "2.63.0",
39
39
  "@redocly/portal-legacy-ui": "0.19.0",
40
40
  "@redocly/portal-plugin-mock-server": "0.24.0-next.0",
41
41
  "@redocly/realm-asyncapi-sdk": "0.16.0",
42
- "@redocly/theme": "0.71.0-next.1",
42
+ "@redocly/theme": "0.71.0-next.3",
43
43
  "@shikijs/transformers": "3.21.0",
44
44
  "@tanstack/react-query": "5.62.3",
45
45
  "@tanstack/react-table": "8.21.3",