import"../node-crypto-polyfill.js";import{DOMParser as T}from"@xmldom/xmldom";import{SignedXml as $}from"xml-crypto";import B from"xpath";import{deflateSync as F,inflateSync as J}from"fflate";import{createHash as q}from"crypto";import{AuthProviderType as u,DEFAULT_TEAM_CLAIM_NAME as z}from"@redocly/config";import{getPathPrefix as H}from"@redocly/theme/core/utils";import{DEFAULT_AUTHENTICATED_TEAM as W,REQUIRED_OIDC_SCOPES as U,ServerRoutes as D}from"../../constants/index.js";import{AUTH_URL as K,JWT_SECRET_KEY as Q}from"../constants/common.js";import{appendQueryParams as X}from"../../shared/urls.js";import{AlgorithmTypes as Y,JwtTokenExpired as G}from"./jwt/types.js";import*as g from"./jwt/jwt.js";import{parseTeamClaimToArray as Z,randomString as ee,randomUUID as O}from"../utils/index.js";import{arrayBufferToBase64 as te,decodeBase64 as b,encodeBase64URL as ne,urlSafeBase64 as P}from"./jwt/encode.js";import{formatSamlCertificate as ae}from"./utils/format-saml-certificate.js";import oe from"../utils/reporter/logger.js";function R(e){return e?.type===u.OIDC}function re(e){return e?.type===u.SAML2}async function Ne(e,t){if(R(t))return se(e,t);if(re(t))return ie(e,t)}async function se(e,t){const a=await N(e,t),n=new Set((t.scopes||[]).concat(U)),o=t.authorizationRequestCustomParams||{};return{type:u.OIDC,idpId:e,name:"OAuth provider",authorizationEndpoint:a.authorization_endpoint,clientId:t.clientId,responseType:"code",scope:Array.from(n).join(" "),extraParams:o,pkce:t.pkce}}function ie(e,t){return{type:u.SAML2,idpId:e,name:"SAML2 provider",ssoUrl:t.ssoUrl,issuerId:t.issuerId,entityId:t.entityId||t.issuerId}}async function ve(e,t,a,n,o={}){const r=new Set((n.scopes||[]).concat(U));return await fetch(e,{method:"POST",body:new URLSearchParams({client_id:n.clientId,scope:Array.from(r).join(" "),code:t,redirect_uri:j(a),grant_type:"authorization_code",...n.clientSecret?{client_secret:n.clientSecret}:{},...o}).toString(),headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"}}).then(s=>s.json())}function ce(e,{authorizationEndpoint:t,clientId:a,responseType:n,scope:o,extraParams:r,idpId:s,pkce:l},d,S){if(!t||!a||!n||!o)return{loginUrl:void 0};const c=new URL(t),f=`${e}${D.OIDC_CALLBACK}`,h={state:O(),idpId:s,redirectUri:f,redirectTo:d,branch:ue(e),inviteCode:S,source:"portal"},y={};if(l){const m=P(ee(50)),w=P(q("sha256").update(m).digest("base64")),A="S256";c.searchParams.append("code_challenge",w),c.searchParams.append("code_challenge_method",A),y.code_verifier={value:m,options:{secure:!0,httpOnly:!0,expires:new Date(Date.now()+1e3*60*10),path:H()||"/"}}}c.searchParams.append("client_id",a),c.searchParams.append("scope",o),c.searchParams.append("response_type",n),c.searchParams.append("redirect_uri",j(f)),c.searchParams.append("state",ne(JSON.stringify(h)));for(const m in r)r[m]!==void 0&&c.searchParams.append(m,r[m]);return{loginUrl:c.toString(),cookies:y}}function Ee(e,t,a,n){const o=new URL(e);return o.searchParams.append("post_logout_redirect_uri",t),n&&o.searchParams.append("state",n),o.searchParams.append("id_token_hint",a),o.toString()}function j(e){return e.match(/^https:\/\/preview-[^\.]+--/)?"https://previewauth--"+e.split("--")[1]:e.match(/^(https:\/\/[^\.]+)--[^\.]+\.preview\./)?e.replace(/^(https:\/\/[^\.]+?)--[^\.]+\.preview\./,"$1.previewauth."):e}function ue(e){return e.match(/^(https:\/\/[^\.]+)--([^\.]+)\.preview\./)?.[2]||void 0}function me(e){return e.type===u.OIDC}function de(e){return e.type===u.SAML2}function Ve(e,t,a,n){return me(e)?ce(t,e,a,n):de(e)?le(t,e,a,n):{}}function le(e,t,a,n){const r=`<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
    xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
    Version="2.0"
    ID="_${O()}"
    IssueInstant="${new Date().toISOString()}"
    AssertionConsumerServiceURL="${e}${D.SAML_CALLBACK}"
    AttributeConsumingServiceIndex="0">
    <saml:Issuer>${t.entityId}</saml:Issuer>
    <samlp:NameIDPolicy
      AllowCreate="true"
      Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/>
  </samlp:AuthnRequest>`,s=pe(r);return{loginUrl:X(t.ssoUrl,{SAMLRequest:s,RelayState:JSON.stringify({idpId:t.idpId,redirectTo:a,inviteCode:n,source:"portal"})})}}function pe(e){return te(F(new TextEncoder().encode(e)).buffer)}function $e(e){const t=b(e);if(t.startsWith("<samlp:Response")||t.indexOf("<saml2p:Response")>-1)return t;const a=J(new Uint8Array(atob(e).split("").map(n=>n.charCodeAt(0))));return new TextDecoder().decode(a)}function Be(e){try{return JSON.parse(b(e||""))}catch{throw new Error("Invalid OAuth2 state")}}function Fe(e){const t=new T().parseFromString(e,"application/xml"),n=i(t,"//*[local-name(.)='StatusCode']/@Value")[0]?.nodeValue?.endsWith("Success")||!1,r=i(t,"//*[local-name(.)='Response']/@Destination")[0]?.nodeValue||"",s=i(t,"//*[local-name(.)='Assertion']//*[local-name(.)='Issuer']/text()")[0],l=s&&s.nodeValue||void 0,d=i(t,"//*[local-name(.)='Audience']/text()")[0],S=d&&d.nodeValue||void 0,f=i(t,"//*[local-name(.)='Assertion']//*[local-name(.)='X509Certificate']/text()")[0]?.nodeValue||"",h=i(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/text()")[0],y=h&&h.nodeValue||"",m=i(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/@Format")[0],w=m&&m.nodeValue||"",A=i(t,"//*[local-name(.)='Conditions']/@NotOnOrAfter")[0],V=fe(A),I={},_=i(t,"//*[local-name(.)='AttributeStatement']//*[local-name(.)='Attribute']");if(_.length)for(const M of _){const k=i(M,"./@Name")[0];if(k.nodeValue){const C=i(M,"./*[local-name(.)='AttributeValue']/text()")[0];C?.nodeValue&&(I[k.nodeValue]=C.nodeValue)}}return{uid:y,success:n,expiresAt:V,issuerId:l,entityId:S,attrs:I,cert:f,nameFormat:w,destination:r}}function fe(e){const t=typeof e?.nodeValue=="string"&&x(Date.parse(e.nodeValue)),a=x(Date.now()),n=x(Date.now()+12*60*60*1e3);return t?t>a&&t<n?n:t:a}function x(e){return Math.floor(e/1e3)}const L={},p={jwks:{}};async function N(e,t){return L[e]||(L[e]=t.configurationUrl?await v(t.configurationUrl):t.configuration),L[e]}async function he(e){for(const t of Object.keys(e)){const a=e[t];if(!R(a))continue;const n=await N(t,a);if(n.jwks_uri){const o=await v(n.jwks_uri);for(const r of o.keys)p.jwks[r.kid]={...r,idpId:t}}}}async function v(e){return fetch(e,{headers:{Accept:"application/json"}}).then(t=>t.json())}async function Je(e){return fetch(`${K}/oidc/userinfo`,{headers:{Accept:"application/json",Authorization:`Bearer ${e}`}}).then(t=>t.status===200?t.json():void 0).catch(()=>{})}function qe(e){if(!e.configurationUrl)return!1;const t=new URL(e.configurationUrl);return["localhost","127.0.0.1","blueharvest.cloud","bhstage.cloud","cloud.redocly.com","beta.redocly.com","cloud.eu.redocly.com","beta.eu.redocly.com","cba.au.redocly.com"].some(n=>ye(t.hostname,n))}function ye(e,t){return e===t||e.endsWith(`.${t}`)}async function ze(e,t){const a=new T().parseFromString(e),n=i(a,"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0];if(!n)throw new Error("Cannot find Signature in the SAML response");const o=ae(t),r=new $({publicCert:o});r.loadSignature(n);try{return r.checkSignature(e)}catch{return!1}}function He(e,t,a,n){t==="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"&&(e=a["http://schemas.microsoft.com/identity/claims/objectidentifier"]);let o;(t==="urn:oasis:names:tc:SAML:2.0:nameid-format:email"||t==="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress")&&(o=e),t==="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"&&e?.match(/.+@.+/)&&(o=e);const r=a["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"],s=r?.match(/.+@.+/);return o=o||a["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]||(s?r:void 0),o=o?.toLowerCase(),{sub:e,given_name:a["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"],family_name:a["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"],name:a["http://schemas.microsoft.com/identity/claims/displayname"]||r,email:o,email_verified:!0,teams:n?Z(a[n]):[]}}function E(e,t={}){return e.map(a=>t[a]||a)}async function We(e,t){if(!t)return{};const a=t.authorization;if(!a)return{};try{const n=g.decode(a);if(n.header.alg===Y.RS256){p.jwks[n.header.kid]===void 0&&await he(e);const d=p.jwks[n.header.kid];if(!d)return p.jwks[n.header.kid]=null,{};await g.verify(a,d,n.header.alg)}else await g.verify(a,Q,n.header.alg);const o=n.payload.idpId||p.jwks[n.header.kid]?.idpId,r=e[o]||{},s=Ae(r),l=we(r);return{...n.payload,email:n.payload.email?.toLowerCase(),idpId:o,teams:Array.from(new Set([...E(n.payload.teams||[],l),..."defaultTeams"in r&&r.defaultTeams||[],...E("teamsClaimName"in r&&n.payload[s||""]||[],l),W])),name:Se(n.payload),isAuthenticated:!0,idpAccessToken:t.idp_access_token,authCookie:a}}catch(n){n instanceof G||oe.error("Malformed JWT token: %s",n.message)}return{}}function Se(e){return e.name||e.given_name||e.email}function we(e){switch(e.type){case u.SAML2:return e.teamsAttributeMap;case u.OIDC:return e.teamsClaimMap;default:return}}function Ae(e){switch(e.type){case u.SAML2:return e.teamsAttributeName;case u.OIDC:return e.teamsClaimName;default:return z}}function i(e,t){return B.select(t,e)||[]}export{Ve as buildLoginUrl,ce as buildOidcLoginUrl,Ee as buildOidcLogoutUrl,le as buildSAML2LoginUrl,$e as decodeSamlResponse,pe as encodeSAML2,He as extractUserClaims,Ne as getAuthProviderLoginParams,se as getOidcLoginParams,N as getOidcMetadata,Je as getRedoclyTokenPayload,ie as getSaml2LoginParams,We as getUserParamsFromCookies,Se as getUsernameFromPayload,R as isOidcProviderConfig,qe as isRedoclySso,re as isSaml2ProviderConfig,ve as oidcExchangeCodeForToken,Be as parseOidcState,ue as parsePreviewBranch,Fe as parseSamlResponse,j as rewritePreviewAuthRedirectUri,ze as verifySAMLResponse};
