authrix
Version:
Lightweight, flexible authentication library for Node.js and TypeScript.
2 lines • 9.36 kB
JavaScript
export{f as checkGitHubOrgMembership,a as getGitHubOAuthURL,j as getGitHubRateLimit,e as getGitHubUserOrganizations,b as handleGitHubCallback,i as resetGitHubOAuthConfig,c as revokeGitHubToken,d as validateGitHubToken}from'./chunk-UZDBZZRO.mjs';export{e as generateOAuthState,a as getGoogleOAuthURL,b as handleGoogleCallback,f as parseOAuthState,g as resetGoogleOAuthConfig,c as revokeGoogleTokens,d as validateGoogleIdToken}from'./chunk-5ZG4N626.mjs';export{h as generateAppleNonce,f as generateAppleOAuthState,a as getAppleOAuthURL,b as handleAppleCallback,g as parseAppleOAuthState,d as refreshAppleAccessToken,i as resetAppleOAuthConfig,c as revokeAppleTokens,j as signWithES256,e as validateAppleIdToken}from'./chunk-7FX5HRMU.mjs';export{a as DiscordPermissions,n as calculatePermissions,g as checkGuildMembership,j as getDiscordBotInviteURL,b as getDiscordOAuthURL,f as getDiscordUserById,h as getGuildMemberRoles,c as handleDiscordCallback,d as refreshDiscordToken,m as resetDiscordOAuthConfig,e as revokeDiscordToken,i as validateDiscordToken}from'./chunk-AHCVFDIR.mjs';export{d as debugFacebookToken,l as deleteFacebookUserData,c as exchangeForLongLivedToken,i as getFacebookAppAccessToken,n as getFacebookLoginStatusURL,a as getFacebookOAuthURL,g as getFacebookUserById,e as getFacebookUserPermissions,b as handleFacebookCallback,m as resetFacebookOAuthConfig,f as revokeFacebookPermission,h as validateFacebookToken,o as verifyFacebookWebhookSignature}from'./chunk-XXFK4JHO.mjs';export{g as generateLinkedInOAuthState,a as getLinkedInOAuthURL,b as handleLinkedInCallback,d as introspectLinkedInToken,h as parseLinkedInOAuthState,e as refreshLinkedInAccessToken,i as resetLinkedInOAuthConfig,c as revokeLinkedInTokens,f as validateLinkedInIdToken}from'./chunk-TY6HHPAD.mjs';export{a as PKCEUtils,j as cleanupPKCEStorage,b as getXOAuthURL,f as getXUserById,c as handleXCallback,d as refreshXToken,k as resetXOAuthConfig,e as revokeXToken,g as validateXToken}from'./chunk-JDZGS3WX.mjs';import'./chunk-3SAEGOMQ.mjs';var l=class d{static base64URLEncode(e){let t=e instanceof Uint8Array?e:new Uint8Array(e),r="";for(let n=0;n<t.length;n++)r+=String.fromCharCode(t[n]);return btoa(r).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}static async generateChallenge(){let e=d.base64URLEncode(crypto.getRandomValues(new Uint8Array(32))),r=new TextEncoder().encode(e),n=await crypto.subtle.digest("SHA-256",r),i=d.base64URLEncode(n);return {verifier:e,challenge:i}}},g=class{constructor(e){this.pkceStore=new Map;this.validateConfig(e),this.config=this.normalizeConfig(e);}validateConfig(e){let r=["name","clientId","clientSecret","redirectUri","endpoints"].filter(n=>!e[n]);if(r.length>0)throw new Error(`Missing required OAuth configuration: ${r.join(", ")}`);if(!e.endpoints.authorization||!e.endpoints.token)throw new Error("Authorization and token endpoints are required");try{new URL(e.endpoints.authorization),new URL(e.endpoints.token),e.endpoints.userInfo&&new URL(e.endpoints.userInfo),e.endpoints.revoke&&new URL(e.endpoints.revoke);}catch{throw new Error("Invalid endpoint URL format")}}normalizeConfig(e){return {...e,scopes:e.scopes||["openid","profile","email"],authorizationParams:e.authorizationParams||{},tokenParams:e.tokenParams||{},userInfoHeaders:e.userInfoHeaders||{},state:e.state!==false,userProfileMapping:e.userProfileMapping||{id:"sub",email:"email",name:"name",avatar:"picture",emailVerified:"email_verified"}}}async getAuthorizationURL(e={}){let t=new URLSearchParams({client_id:this.config.clientId,redirect_uri:this.config.redirectUri,response_type:"code",scope:(e.scopes||this.config.scopes||[]).join(" "),...this.config.authorizationParams,...e.additionalParams});if(this.config.state){let r=e.state||this.generateState();t.set("state",r);}if(this.config.pkce){let{verifier:r,challenge:n}=await l.generateChallenge(),i=e.state||t.get("state")||this.generateState();this.pkceStore.set(i,r),t.set("code_challenge",n),t.set("code_challenge_method","S256"),t.has("state")||t.set("state",i);}return e.loginHint&&t.set("login_hint",e.loginHint),e.prompt&&t.set("prompt",e.prompt),e.accessType&&t.set("access_type",e.accessType),`${this.config.endpoints.authorization}?${t.toString()}`}async handleCallback(e,t={}){try{let r=await this.exchangeCodeForTokens(e,t.state),n={};if(r.id_token){let s=this.decodeJWT(r.id_token);s&&(n=s);}if(this.config.endpoints.userInfo&&r.access_token)try{let s=await this.fetchUserInfo(r.access_token);n={...n,...s};}catch(s){if(!r.id_token)throw s}if(!n||Object.keys(n).length===0)throw new Error("No user profile data available");let i=this.mapUserProfile(n);if(!t.skipEmailVerification&&i.emailVerified===!1)throw new Error("Email address is not verified");t.includeRawResponse&&(i.raw=n);let o={user:i};return t.includeTokens&&(o.tokens={access:r.access_token,refresh:r.refresh_token,idToken:r.id_token,expiresIn:r.expires_in,tokenType:r.token_type}),this.config.pkce&&t.state&&this.pkceStore.delete(t.state),o}catch(r){throw this.config.pkce&&t.state&&this.pkceStore.delete(t.state),r instanceof Error?new Error(`${this.config.name} authentication failed: ${r.message}`):new Error(`An unexpected error occurred during ${this.config.name} authentication`)}}async exchangeCodeForTokens(e,t){let r=new URLSearchParams({code:e,client_id:this.config.clientId,client_secret:this.config.clientSecret,redirect_uri:this.config.redirectUri,grant_type:"authorization_code",...this.config.tokenParams});if(this.config.pkce&&t){let a=this.pkceStore.get(t);if(a)r.set("code_verifier",a);else throw new Error("PKCE verifier not found for state")}let n=await fetch(this.config.endpoints.token,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:r.toString()});if(!n.ok){let a=await n.text();throw new Error(`Token exchange failed: ${n.status} - ${a}`)}let i=n.headers.get("content-type");if(i&&i.includes("application/json"))return await n.json();let o=await n.text(),s={};return new URLSearchParams(o).forEach((a,h)=>{s[h]=a;}),s}async fetchUserInfo(e){if(!this.config.endpoints.userInfo)return null;let t={Authorization:`Bearer ${e}`,Accept:"application/json",...this.config.userInfoHeaders},r=await fetch(this.config.endpoints.userInfo,{headers:t});if(!r.ok)throw new Error(`Failed to fetch user info: ${r.status}`);return await r.json()}mapUserProfile(e){let t=this.config.userProfileMapping,r=(i,o)=>{if(!i)return o;if(typeof i=="function")try{return i(e)||o}catch{return o}let s=i.split("."),c=e;for(let a of s)if(c=c?.[a],c===void 0)return o;return c||o},n={id:r(t.id,""),email:r(t.email,""),name:r(t.name),avatar:r(t.avatar),provider:this.config.name,emailVerified:r(t.emailVerified)};if(t.metadata){n.metadata={};for(let[i,o]of Object.entries(t.metadata)){let s=r(o);s!==void 0&&(n.metadata[i]=s);}}return n}async revokeTokens(e,t="access_token"){if(!this.config.endpoints.revoke)return false;try{let r=new URLSearchParams({token:e,token_type_hint:t,client_id:this.config.clientId,client_secret:this.config.clientSecret});return (await fetch(this.config.endpoints.revoke,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:r.toString()})).ok}catch{return false}}async refreshAccessToken(e){let t=new URLSearchParams({refresh_token:e,client_id:this.config.clientId,client_secret:this.config.clientSecret,grant_type:"refresh_token"}),r=await fetch(this.config.endpoints.token,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:t.toString()});if(!r.ok){let n=await r.text();throw new Error(`Token refresh failed: ${r.status} - ${n}`)}return await r.json()}async validateIdToken(e){try{let t=this.decodeJWT(e);if(!t)return null;let r=Math.floor(Date.now()/1e3);return t.exp&&t.exp<r||t.aud&&t.aud!==this.config.clientId?null:t}catch{return null}}decodeJWT(e){try{let t=e.split(".");if(t.length!==3)return null;let r=t[1],n=r+"=".repeat((4-r.length%4)%4),i=atob(n.replace(/-/g,"+").replace(/_/g,"/"));return JSON.parse(i)}catch{return null}}generateState(e){let t=crypto.getRandomValues(new Uint8Array(32)),r=Array.from(t,n=>n.toString(16).padStart(2,"0")).join("");if(e){let n=JSON.stringify(e),i=btoa(n).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"");return `${r}.${i}`}return r}parseState(e){let t=e.split(".");if(t.length===1)return {token:t[0]};try{let r=t[1],n=r+"=".repeat((4-r.length%4)%4),i=atob(n.replace(/-/g,"+").replace(/_/g,"/")),o=JSON.parse(i);return {token:t[0],data:o}}catch{return {token:t[0]}}}getConfig(){return {...this.config}}updateConfig(e){let{name:t,endpoints:r,...n}=e;if(t||r)throw new Error("Cannot update provider name or endpoints after initialization");this.config={...this.config,...n};}clearPKCEStore(){this.pkceStore.clear();}},f=class{constructor(){this.providers=new Map;}register(e){if(this.providers.has(e.name))throw new Error(`Provider "${e.name}" is already registered`);let t=new g(e);return this.providers.set(e.name,t),t}get(e){return this.providers.get(e)}remove(e){let t=this.providers.get(e);return t&&t.clearPKCEStore(),this.providers.delete(e)}list(){return Array.from(this.providers.keys())}has(e){return this.providers.has(e)}clear(){this.providers.forEach(e=>e.clearPKCEStore()),this.providers.clear();}},Oe=new f;
export{g as CustomOAuthProvider,f as OAuthProviderManager,Oe as oAuthManager};