@dainprotocol/oauth2-token-manager 0.1.1 → 0.1.2
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/README.md +224 -694
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +119 -775
- package/dist/index.d.ts +119 -775
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {createHash,randomBytes}from'crypto';import {sealData,unsealData}from'iron-session';var P=class{buildUrlParams(e){return Object.entries(e).filter(([,t])=>t!==void 0).map(([t,s])=>`${t}=${encodeURIComponent(s)}`).join("&")}generateAuthorizationUrl(e,r,t){let s={client_id:e.clientId,redirect_uri:e.redirectUri,response_type:"code",scope:e.scopes.join(" "),state:r};(e.usePKCE||e.pkce)&&t&&(s.code_challenge=t,s.code_challenge_method="S256");let o={...e.additionalParams,...e.extraAuthParams};return Object.assign(s,o),`${e.authorizationUrl}?${this.buildUrlParams(s)}`}};var S=class{buildUrlParams(e){return Object.entries(e).filter(([,t])=>t!==void 0).map(([t,s])=>`${t}=${encodeURIComponent(s)}`).join("&")}async exchangeCodeForToken(e,r,t){let s={grant_type:"authorization_code",code:e,redirect_uri:r.redirectUri,client_id:r.clientId};(r.usePKCE||r.pkce)&&t?s.code_verifier=t:r.clientSecret&&(s.client_secret=r.clientSecret);let o=await fetch(r.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildUrlParams(s)});if(!o.ok){let c=await o.text();throw new Error(`Token exchange failed: ${o.statusText} - ${c}`)}let n=await o.json(),a=r.responseRootKey?n[r.responseRootKey]:n,i=Date.now(),d=a.expires_in||3600;return {accessToken:a.access_token,refreshToken:a.refresh_token,expiresAt:new Date(i+d*1e3),expiresIn:d,tokenType:a.token_type||"Bearer",scope:a.scope,createdAt:i,raw:n}}async refreshToken(e,r){let t={grant_type:"refresh_token",refresh_token:e,client_id:r.clientId};!(r.usePKCE||r.pkce)&&r.clientSecret&&(t.client_secret=r.clientSecret);let s=await fetch(r.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildUrlParams(t)});if(!s.ok){let d=await s.text();throw new Error(`Token refresh failed: ${s.statusText} - ${d}`)}let o=await s.json(),n=r.responseRootKey?o[r.responseRootKey]:o,a=Date.now(),i=n.expires_in||3600;return {accessToken:n.access_token,refreshToken:n.refresh_token||e,expiresAt:new Date(a+i*1e3),expiresIn:i,tokenType:n.token_type||"Bearer",scope:n.scope,createdAt:a,raw:o}}};var k=class{constructor(e,r,t,s){this.config=e;this.authUrlStrategy=r||this.createAuthorizationUrlStrategy(),this.tokenStrategy=t||this.createTokenExchangeStrategy(),this.profileFetcher=s;}authUrlStrategy;tokenStrategy;profileFetcher;async fetchProfile(e){if(!this.profileFetcher)throw new Error("Profile fetcher not configured for this provider");return this.profileFetcher.fetchUserInfo(e)}getProfileEndpoint(){if(!this.profileFetcher)throw new Error("Profile fetcher not configured for this provider");return this.profileFetcher.getEndpoint()}setProfileFetcher(e){this.profileFetcher=e;}hasProfileFetcher(){return !!this.profileFetcher}generateAuthorizationUrl(e,r){return this.authUrlStrategy.generateAuthorizationUrl(this.config,e,r)}async exchangeCodeForToken(e,r){return this.tokenStrategy.exchangeCodeForToken(e,this.config,r)}async refreshToken(e){return this.tokenStrategy.refreshToken(e,this.config)}};var U=class extends k{constructor(e,r,t,s){super(e,r,t,s);}createAuthorizationUrlStrategy(){return new P}createTokenExchangeStrategy(){return new S}};var p=class{constructor(e){this.profileEndpoint=e;}async fetchUserInfo(e){let r=await fetch(this.profileEndpoint,{headers:{Authorization:`Bearer ${e}`,Accept:"application/json",...this.getAdditionalHeaders()}});if(!r.ok)throw new Error(`Failed to fetch profile from ${this.profileEndpoint}: ${r.statusText}`);let t=await r.json();return this.mapToUserProfile(t)}getAdditionalHeaders(){return {}}getEndpoint(){return this.profileEndpoint}};var w=class extends p{constructor(){super("https://www.googleapis.com/oauth2/v2/userinfo");}mapToUserProfile(e){return {email:e.email,name:e.name,id:e.id,avatar:e.picture,username:e.email,raw:e}}};var I=class extends p{constructor(){super("https://api.github.com/user");}mapToUserProfile(e){var r;return {email:e.email,name:e.name||e.login,id:(r=e.id)==null?void 0:r.toString(),avatar:e.avatar_url,username:e.login,raw:e}}getAdditionalHeaders(){return {"User-Agent":"OAuth2-Token-Manager"}}};var E=class extends p{constructor(){super("https://graph.microsoft.com/v1.0/me");}mapToUserProfile(e){return {email:e.mail||e.userPrincipalName,name:e.displayName,id:e.id,avatar:void 0,username:e.userPrincipalName,raw:e}}};var h=class extends p{constructor(r,t,s){super(r);this.mapping=t;this.additionalHeaders=s;}mapToUserProfile(r){return this.mapping?{email:this.getNestedProperty(r,this.mapping.email),name:this.mapping.name?this.getNestedProperty(r,this.mapping.name):void 0,id:this.mapping.id?this.getNestedProperty(r,this.mapping.id):void 0,avatar:this.mapping.avatar?this.getNestedProperty(r,this.mapping.avatar):void 0,username:this.mapping.username?this.getNestedProperty(r,this.mapping.username):void 0,raw:r}:{email:r.email||r.mail||r.emailAddress,name:r.name||r.displayName||r.full_name,id:r.id||r.sub||r.user_id,avatar:r.avatar||r.picture||r.avatar_url,username:r.username||r.login||r.preferred_username,raw:r}}getAdditionalHeaders(){return this.additionalHeaders||{}}getNestedProperty(r,t){return t.split(".").reduce((s,o)=>s==null?void 0:s[o],r)}};var A=class{static createProfileFetcher(e,r,t){if(t!=null&&t.profileUrl)return new h(t.profileUrl,t.profileMapping,t.profileHeaders);switch(e){case "google":return new w;case "github":return new I;case "microsoft":case "outlook":return new E;case "facebook":return new h("https://graph.facebook.com/me?fields=id,name,email,picture");case "generic":default:let s=r.profileUrl||r.userInfoUrl;if(!s)throw new Error(`Profile URL must be provided for ${e} provider`);return new h(s)}}static registerCustomProfileFetcher(e,r){this.customFetchers.set(e,r);}static customFetchers=new Map;static getCustomProfileFetcher(e){return this.customFetchers.get(e)}};var x=class u{static presetConfigs={google:{authorizationUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",profileUrl:"https://www.googleapis.com/oauth2/v2/userinfo",usePKCE:true,extraAuthParams:{access_type:"offline",prompt:"consent"}},github:{authorizationUrl:"https://github.com/login/oauth/authorize",tokenUrl:"https://github.com/login/oauth/access_token",profileUrl:"https://api.github.com/user"},microsoft:{authorizationUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",tokenUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/token",profileUrl:"https://graph.microsoft.com/v1.0/me",usePKCE:true},outlook:{authorizationUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",tokenUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/token",profileUrl:"https://graph.microsoft.com/v1.0/me",usePKCE:true,extraAuthParams:{prompt:"select_account"}},facebook:{authorizationUrl:"https://www.facebook.com/v12.0/dialog/oauth",tokenUrl:"https://graph.facebook.com/v12.0/oauth/access_token",profileUrl:"https://graph.facebook.com/me?fields=id,name,email,picture"}};createProvider(e,r){let t=e!=="generic"?u.presetConfigs[e]||{}:{},s={...t,...r,extraAuthParams:{...t.extraAuthParams||{},...r.extraAuthParams||{}}},o=A.createProfileFetcher(e,s);return new U(s,void 0,void 0,o)}static registerPreset(e,r){u.presetConfigs[e]=r;}static getPresetConfig(e){return u.presetConfigs[e]}};var y=class{systems=new Map;scopes=new Map;users=new Map;tokens=new Map;states=new Map;generateId(){return Math.random().toString(36).substring(2)+Date.now().toString(36)}async createSystem(e){let r={...e,id:this.generateId(),createdAt:new Date,updatedAt:new Date};return this.systems.set(r.id,r),r}async getOrCreateSystem(e){let r=Array.from(this.systems.values()).find(t=>t.name===e.name);return r||this.createSystem(e)}async getSystem(e){return this.systems.get(e)||null}async updateSystem(e,r){let t=this.systems.get(e);if(!t)throw new Error("System not found");let s={...t,...r,updatedAt:new Date};return this.systems.set(e,s),s}async deleteSystem(e){this.systems.delete(e);}async listSystems(){return Array.from(this.systems.values())}async createScope(e){let r={...e,id:this.generateId()};return this.scopes.set(r.id,r),r}async getOrCreateScope(e){let r=Array.from(this.scopes.values()).find(t=>t.systemId===e.systemId&&t.name===e.name);return r||this.createScope(e)}async getScope(e){return this.scopes.get(e)||null}async getScopesBySystem(e){return Array.from(this.scopes.values()).filter(r=>r.systemId===e)}async updateScope(e,r){let t=this.scopes.get(e);if(!t)throw new Error("Scope not found");let s={...t,...r};return this.scopes.set(e,s),s}async deleteScope(e){this.scopes.delete(e);}async createUser(e){let r={...e,id:this.generateId(),createdAt:new Date,updatedAt:new Date};return this.users.set(r.id,r),r}async getOrCreateUser(e){if(e.email){let r=await this.findUserByEmail(e.systemId,e.email);if(r)return r}if(e.externalId){let r=await this.findUserByExternalId(e.systemId,e.externalId);if(r)return r}return this.createUser({systemId:e.systemId,metadata:{...e.metadata,...e.email&&{email:e.email},...e.externalId&&{externalId:e.externalId}}})}async findUserByEmail(e,r){return Array.from(this.users.values()).find(s=>{var o;return s.systemId===e&&((o=s.metadata)==null?void 0:o.email)===r})||null}async findUserByExternalId(e,r){return Array.from(this.users.values()).find(s=>{var o;return s.systemId===e&&((o=s.metadata)==null?void 0:o.externalId)===r})||null}async getUser(e){return this.users.get(e)||null}async getUsersBySystem(e){return Array.from(this.users.values()).filter(r=>r.systemId===e)}async updateUser(e,r){let t=this.users.get(e);if(!t)throw new Error("User not found");let s={...t,...r,updatedAt:new Date};return this.users.set(e,s),s}async deleteUser(e){this.users.delete(e);}async saveToken(e){let r={...e,id:this.generateId(),createdAt:new Date,updatedAt:new Date};return this.tokens.set(r.id,r),r}async saveTokenWithEmailValidation(e,r,t,s,o,n){if((await this.findTokensByEmailInUserScopeProvider(e,t,s,o)).length>0)return this.replaceTokensByEmailInUserScopeProvider(e,t,s,o,n);let i={...n,userId:e,systemId:r,scopeId:t,provider:s,email:o};return this.saveToken(i)}async getTokensByUser(e){return Array.from(this.tokens.values()).filter(r=>r.userId===e)}async getTokensByUserAndScope(e,r){return Array.from(this.tokens.values()).filter(t=>t.userId===e&&t.scopeId===r)}async getTokensByUserAndProvider(e,r){return Array.from(this.tokens.values()).filter(t=>t.userId===e&&t.provider===r)}async getTokensByUserScopeProvider(e,r,t){return Array.from(this.tokens.values()).filter(s=>s.userId===e&&s.scopeId===r&&s.provider===t)}async getTokensByScope(e,r){return Array.from(this.tokens.values()).filter(t=>t.systemId===e&&t.scopeId===r)}async getTokensByProvider(e,r){return Array.from(this.tokens.values()).filter(t=>t.systemId===e&&t.provider===r)}async getTokensBySystem(e){return Array.from(this.tokens.values()).filter(r=>r.systemId===e)}async findTokensByEmail(e,r){return Array.from(this.tokens.values()).filter(t=>t.systemId===r&&t.email===e)}async findTokensByEmailAndScope(e,r,t){return Array.from(this.tokens.values()).filter(s=>s.systemId===r&&s.scopeId===t&&s.email===e)}async findTokensByEmailAndProvider(e,r,t){return Array.from(this.tokens.values()).filter(s=>s.systemId===r&&s.provider===t&&s.email===e)}async findTokenByEmailScopeProvider(e,r,t,s){return Array.from(this.tokens.values()).find(o=>o.systemId===r&&o.scopeId===t&&o.provider===s&&o.email===e)||null}async findTokensByEmailInUserScopeProvider(e,r,t,s){return Array.from(this.tokens.values()).filter(o=>o.userId===e&&o.scopeId===r&&o.provider===t&&o.email===s)}async hasTokenWithEmailInUserScopeProvider(e,r,t,s){return (await this.findTokensByEmailInUserScopeProvider(e,r,t,s)).length>0}async replaceTokensByEmailInUserScopeProvider(e,r,t,s,o){(await this.findTokensByEmailInUserScopeProvider(e,r,t,s)).forEach(i=>{this.tokens.delete(i.id);});let a={...o,userId:e,systemId:o.systemId,scopeId:r,provider:t};return this.saveToken(a)}async getTokenById(e){return this.tokens.get(e)||null}async updateToken(e,r){let t=this.tokens.get(e);if(!t)throw new Error("Token not found");let s={...t,...r,updatedAt:new Date};return this.tokens.set(e,s),s}async deleteToken(e){this.tokens.delete(e);}async deleteTokensByUser(e){Array.from(this.tokens.entries()).filter(([,t])=>t.userId===e).map(([t])=>t).forEach(t=>this.tokens.delete(t));}async deleteTokensByUserAndScope(e,r){Array.from(this.tokens.entries()).filter(([,s])=>s.userId===e&&s.scopeId===r).map(([s])=>s).forEach(s=>this.tokens.delete(s));}async deleteTokensByUserAndProvider(e,r){Array.from(this.tokens.entries()).filter(([,s])=>s.userId===e&&s.provider===r).map(([s])=>s).forEach(s=>this.tokens.delete(s));}async saveAuthorizationState(e){this.states.set(e.state,e);}async getAuthorizationState(e){return this.states.get(e)||null}async deleteAuthorizationState(e){this.states.delete(e);}async cleanupExpiredStates(e){let r=new Date;Array.from(this.states.entries()).filter(([,s])=>r.getTime()-s.timestamp.getTime()>e).map(([s])=>s).forEach(s=>this.states.delete(s));}async getTokensByUserWithProfile(e){var s,o,n;let r=await this.getTokensByUser(e),t=[];for(let a of r){let i=this.users.get(a.userId);i&&t.push({...a,user:{email:(s=i.metadata)==null?void 0:s.email,name:(o=i.metadata)==null?void 0:o.name,externalId:(n=i.metadata)==null?void 0:n.externalId,metadata:i.metadata}});}return t}async getTokensByUserAndScopeWithProfile(e,r){var o,n,a;let t=await this.getTokensByUserAndScope(e,r),s=[];for(let i of t){let d=this.users.get(i.userId);d&&s.push({...i,user:{email:(o=d.metadata)==null?void 0:o.email,name:(n=d.metadata)==null?void 0:n.name,externalId:(a=d.metadata)==null?void 0:a.externalId,metadata:d.metadata}});}return s}async getTokensByUserAndProviderWithProfile(e,r){var o,n,a;let t=await this.getTokensByUserAndProvider(e,r),s=[];for(let i of t){let d=this.users.get(i.userId);d&&s.push({...i,user:{email:(o=d.metadata)==null?void 0:o.email,name:(n=d.metadata)==null?void 0:n.name,externalId:(a=d.metadata)==null?void 0:a.externalId,metadata:d.metadata}});}return s}async getTokensByUserScopeProviderWithProfile(e,r,t){var n,a,i;let s=await this.getTokensByUserScopeProvider(e,r,t),o=[];for(let d of s){let c=this.users.get(d.userId);c&&o.push({...d,user:{email:(n=c.metadata)==null?void 0:n.email,name:(a=c.metadata)==null?void 0:a.name,externalId:(i=c.metadata)==null?void 0:i.externalId,metadata:c.metadata}});}return o}async getTokensByScopeWithProfile(e,r){var o,n,a;let t=await this.getTokensByScope(e,r),s=[];for(let i of t){let d=this.users.get(i.userId);d&&s.push({...i,user:{email:(o=d.metadata)==null?void 0:o.email,name:(n=d.metadata)==null?void 0:n.name,externalId:(a=d.metadata)==null?void 0:a.externalId,metadata:d.metadata}});}return s}async getTokensBySystemWithProfile(e){var s,o,n;let r=await this.getTokensBySystem(e),t=[];for(let a of r){let i=this.users.get(a.userId);i&&t.push({...a,user:{email:(s=i.metadata)==null?void 0:s.email,name:(o=i.metadata)==null?void 0:o.name,externalId:(n=i.metadata)==null?void 0:n.externalId,metadata:i.metadata}});}return t}};var _=()=>randomBytes(32).toString("base64").replace(/[^a-zA-Z0-9]/g,"").substring(0,128),N=u=>createHash("sha256").update(u).digest("base64url"),V=()=>randomBytes(16).toString("base64url");var T=class{constructor(e,r,t=Date.now){this.storage=e;this.providers=r;this.now=t;}async createUserInSystem(e,r={}){return this.storage.createUser({systemId:e,metadata:{...r.metadata,...r.email&&{email:r.email},...r.externalId&&{externalId:r.externalId}}})}async getOrCreateUserInSystem(e,r={}){return this.storage.getOrCreateUser({systemId:e,email:r.email,externalId:r.externalId,metadata:r.metadata})}async getUserById(e){return this.storage.getUser(e)}async findUserByEmailInSystem(e,r){return this.storage.findUserByEmail(e,r)}async findUserByExternalIdInSystem(e,r){return this.storage.findUserByExternalId(e,r)}async getUsersBySystem(e){return this.storage.getUsersBySystem(e)}async saveTokenForUser(e,r,t,s,o,n){return this.storage.saveTokenWithEmailValidation(e,r,t,s,o,{userId:e,systemId:r,scopeId:t,provider:s,token:n})}async getTokensByUser(e){return this.storage.getTokensByUser(e)}async getTokensByUserAndScope(e,r){return this.storage.getTokensByUserAndScope(e,r)}async getTokensByUserAndProvider(e,r){return this.storage.getTokensByUserAndProvider(e,r)}async getTokensByUserScopeProvider(e,r,t){return this.storage.getTokensByUserScopeProvider(e,r,t)}async getTokensByScope(e,r){return this.storage.getTokensByScope(e,r)}async getTokensByProvider(e,r){return this.storage.getTokensByProvider(e,r)}async getTokensBySystem(e){return this.storage.getTokensBySystem(e)}async findTokensByEmail(e,r){return this.storage.findTokensByEmail(e,r)}async findTokensByEmailAndScope(e,r,t){return this.storage.findTokensByEmailAndScope(e,r,t)}async findTokensByEmailAndProvider(e,r,t){return this.storage.findTokensByEmailAndProvider(e,r,t)}async findTokenByEmailScopeProvider(e,r,t,s){return this.storage.findTokenByEmailScopeProvider(e,r,t,s)}async getValidTokenByEmail(e,r,t,s,o={}){let n=await this.storage.findTokenByEmailScopeProvider(e,r,t,s);if(!n)throw new Error(`No token found for email ${e} and provider ${s}`);if(!(o.autoRefresh!==false&&this.isTokenExpired(n.token,o)))return n.token;if(!n.token.refreshToken)throw new Error("Token expired and no refresh token available");let i=this.providers.get(s);if(!i)throw new Error(`Provider ${s} not found`);let d=await i.refreshToken(n.token.refreshToken);return await this.storage.updateToken(n.id,{token:d}),d}async getAccessTokenByEmail(e,r,t,s,o={}){return (await this.getValidTokenByEmail(e,r,t,s,o)).accessToken}async getAllValidTokensForUser(e,r={}){let t=await this.storage.getTokensByUser(e),s=[];for(let o of t)if(o)try{let n=r.autoRefresh!==!1&&this.isTokenExpired(o.token,r),a=o.token;if(n){if(!o.token.refreshToken){console.warn(`Token for provider ${o.provider} expired and no refresh token available`);continue}let i=this.providers.get(o.provider);if(!i){console.warn(`Provider ${o.provider} not found`);continue}try{let d=await i.refreshToken(o.token.refreshToken);await this.storage.updateToken(o.id,{token:d}),a=d;}catch(d){console.warn(`Failed to refresh token for provider ${o.provider}:`,d);continue}}s.push({provider:o.provider,scopeId:o.scopeId,token:a,userToken:{...o,token:a}});}catch(n){console.warn(`Error processing token for provider ${o.provider}:`,n);continue}return s}async getAllValidTokensForUserScopeProvider(e,r,t,s={}){var a;let o=await this.storage.getTokensByUserScopeProvider(e,r,t),n=[];for(let i of o)if(i)try{let d=await this.storage.getUser(i.userId),c=(a=d==null?void 0:d.metadata)==null?void 0:a.email;if(!c){console.warn(`No email found for user ${i.userId}, skipping token`);continue}let l=s.autoRefresh!==!1&&this.isTokenExpired(i.token,s),m=i.token;if(l){if(!i.token.refreshToken){console.warn(`Token for provider ${i.provider} expired and no refresh token available`);continue}let g=this.providers.get(i.provider);if(!g){console.warn(`Provider ${i.provider} not found`);continue}try{let f=await g.refreshToken(i.token.refreshToken);await this.storage.updateToken(i.id,{token:f}),m=f;}catch(f){console.warn(`Failed to refresh token for provider ${i.provider}:`,f);continue}}n.push({email:c,token:m,userToken:{...i,token:m}});}catch(d){console.warn(`Error processing token for provider ${i.provider}:`,d);continue}return n}async getAllValidTokensForEmail(e,r,t={}){let s=await this.storage.findTokensByEmail(e,r),o=[];for(let n of s)if(n)try{let a=t.autoRefresh!==!1&&this.isTokenExpired(n.token,t),i=n.token;if(a){if(!n.token.refreshToken){console.warn(`Token for provider ${n.provider} expired and no refresh token available`);continue}let d=this.providers.get(n.provider);if(!d){console.warn(`Provider ${n.provider} not found`);continue}try{let c=await d.refreshToken(n.token.refreshToken);await this.storage.updateToken(n.id,{token:c}),i=c;}catch(c){console.warn(`Failed to refresh token for provider ${n.provider}:`,c);continue}}o.push({provider:n.provider,scopeId:n.scopeId,token:i,userToken:{...n,token:i}});}catch(a){console.warn(`Error processing token for provider ${n.provider}:`,a);continue}return o}async withValidTokenByEmail(e,r,t,s,o,n={}){let a=await this.getValidTokenByEmail(e,r,t,s,n);return await o(a.accessToken)}async hasTokensForUserScopeProvider(e,r,t){return (await this.storage.getTokensByUserScopeProvider(e,r,t)).length>0}async hasTokenByEmail(e,r,t,s){return await this.storage.findTokenByEmailScopeProvider(e,r,t,s)!==null}async hasTokenWithEmailInUserScopeProvider(e,r,t,s){return this.storage.hasTokenWithEmailInUserScopeProvider(e,r,t,s)}async replaceTokensByEmailInUserScopeProvider(e,r,t,s,o){var n;return this.storage.replaceTokensByEmailInUserScopeProvider(e,r,t,s,{userId:e,systemId:((n=await this.storage.getUser(e))==null?void 0:n.systemId)||"",scopeId:r,provider:t,token:o})}async deleteTokensByUser(e){return this.storage.deleteTokensByUser(e)}async deleteTokensByUserAndScope(e,r){return this.storage.deleteTokensByUserAndScope(e,r)}async deleteTokensByUserAndProvider(e,r){return this.storage.deleteTokensByUserAndProvider(e,r)}async deleteTokensByUserScopeProvider(e,r,t){let s=await this.storage.getTokensByUserScopeProvider(e,r,t);for(let o of s)await this.storage.deleteToken(o.id);}async deleteTokenByEmail(e,r,t,s){let o=await this.storage.findTokenByEmailScopeProvider(e,r,t,s);o&&await this.storage.deleteToken(o.id);}async createSystem(e,r){return this.storage.createSystem({name:e,description:r,scopes:[]})}async getSystem(e){return this.storage.getSystem(e)}async createScopeInSystem(e,r,t={}){return this.storage.createScope({systemId:e,name:r,type:t.type||"authentication",permissions:t.permissions||[],isolated:t.isolated??true})}async getScope(e){return this.storage.getScope(e)}async getScopesBySystem(e){return this.storage.getScopesBySystem(e)}isTokenExpired(e,r={}){let{expirationBuffer:t=300}=r;if(e.createdAt&&e.expiresIn!==void 0){let n=e.createdAt+e.expiresIn*1e3;return this.now()+t*1e3>=n}let s=new Date(e.expiresAt).getTime();return this.now()+t*1e3>=s}};var M="oauth2-token-manager-default-system",W="oauth2-token-manager-default-scope",B={name:M,description:"Default system for OAuth2 token management",metadata:{isDefault:true},scopes:[]},O={name:W,type:"access",permissions:["read","write"],isolated:false,metadata:{isDefault:true}};async function b(u){let e=await u.getOrCreateSystem(B),r=await u.getOrCreateScope({...O,systemId:e.id});return {system:e,scope:r}}async function C(u){return (await u.listSystems()).find(r=>r.name===B.name)||null}async function K(u){let e=await C(u);return e&&(await u.getScopesBySystem(e.id)).find(t=>t.name===O.name)||null}var v=class{constructor(e,r,t,s=Date.now){this.storage=e;this.providers=r;this.getContext=t;this.now=s;}defaultSystem=null;defaultScope=null;defaultsInitialized=false;async ensureDefaults(){if(this.defaultsInitialized&&this.defaultSystem&&this.defaultScope)return {system:this.defaultSystem,scope:this.defaultScope};let{system:e,scope:r}=await b(this.storage);return this.defaultSystem=e,this.defaultScope=r,this.defaultsInitialized=true,{system:e,scope:r}}async resolveSystemId(e){var s;if(e)return e;let r=this.getContext();if((s=r.currentSystem)!=null&&s.id)return r.currentSystem.id;let{system:t}=await this.ensureDefaults();return t.id}async resolveScopeId(e){var s;if(e)return e;let r=this.getContext();if((s=r.defaultScope)!=null&&s.id)return r.defaultScope.id;let{scope:t}=await this.ensureDefaults();return t.id}async createUser(e){var t;let r=await this.resolveSystemId(e.systemId);return this.storage.createUser({systemId:r,metadata:{...(t=e.options)==null?void 0:t.metadata,...e.email&&{email:e.email},...e.externalId&&{externalId:e.externalId}}})}async getOrCreateUser(e){var t;let r=await this.resolveSystemId(e.systemId);return this.storage.getOrCreateUser({systemId:r,email:e.email,externalId:e.externalId,metadata:(t=e.options)==null?void 0:t.metadata})}async getUserById(e){return this.storage.getUser(e)}async findUserByEmail(e){let r=await this.resolveSystemId(e.systemId);return this.storage.findUserByEmail(r,e.email)}async findUserByExternalId(e){let r=await this.resolveSystemId(e.systemId);return this.storage.findUserByExternalId(r,e.externalId)}async getUsersBySystem(e){let r=await this.resolveSystemId(e);return this.storage.getUsersBySystem(r)}async saveToken(e){let r=await this.resolveSystemId(e.systemId),t=await this.resolveScopeId(e.scopeId);return this.storage.saveTokenWithEmailValidation(e.userId,r,t,e.provider,e.email,{userId:e.userId,systemId:r,scopeId:t,provider:e.provider,token:e.token})}async getTokens(e){if(e.userId&&e.scopeId&&e.provider)return this.storage.getTokensByUserScopeProvider(e.userId,e.scopeId,e.provider);if(e.userId&&e.provider)return this.storage.getTokensByUserAndProvider(e.userId,e.provider);if(e.userId&&e.scopeId)return this.storage.getTokensByUserAndScope(e.userId,e.scopeId);if(e.userId)return this.storage.getTokensByUser(e.userId);if(e.email&&e.systemId&&e.scopeId&&e.provider){let r=await this.storage.findTokenByEmailScopeProvider(e.email,e.systemId,e.scopeId,e.provider);return r?[r]:[]}if(e.email&&e.systemId&&e.scopeId)return this.storage.findTokensByEmailAndScope(e.email,e.systemId,e.scopeId);if(e.email&&e.systemId&&e.provider)return this.storage.findTokensByEmailAndProvider(e.email,e.systemId,e.provider);if(e.email&&e.systemId)return this.storage.findTokensByEmail(e.email,e.systemId);if(e.systemId&&e.scopeId)return this.storage.getTokensByScope(e.systemId,e.scopeId);if(e.systemId&&e.provider)return this.storage.getTokensByProvider(e.systemId,e.provider);if(e.systemId)return this.storage.getTokensBySystem(e.systemId);if(e.email){let r=await this.resolveSystemId(e.systemId);return this.storage.findTokensByEmail(e.email,r)}throw new Error("Invalid token query parameters")}async getValidToken(e){let r=null;if("email"in e){let a=await this.resolveSystemId(e.systemId),i=await this.resolveScopeId(e.scopeId);if(r=await this.storage.findTokenByEmailScopeProvider(e.email,a,i,e.provider),!r)throw new Error(`No token found for email ${e.email} and provider ${e.provider}`)}else {let a=await this.resolveScopeId(e.scopeId),i=await this.storage.getTokensByUserScopeProvider(e.userId,a,e.provider);if(i.length===0)throw new Error(`No token found for user ${e.userId} and provider ${e.provider}`);let d=i[0];if(!d)throw new Error(`No token found for user ${e.userId} and provider ${e.provider}`);r=d;}if(!r)throw new Error("No token found for the specified parameters");let t=e.options||{};if(!(t.autoRefresh!==false&&this.isTokenExpired(r.token,t)))return r.token;if(!r.token.refreshToken)throw new Error("Token expired and no refresh token available");let o=this.providers.get(e.provider);if(!o)throw new Error(`Provider ${e.provider} not found`);let n=await o.refreshToken(r.token.refreshToken);return await this.storage.updateToken(r.id,{token:n}),n}async getAccessToken(e){return (await this.getValidToken(e)).accessToken}async withValidToken(e,r){let t=await this.getValidToken(e);return await r(t.accessToken)}async getAllValidTokens(e){let r=[];if(e.userId)r=await this.storage.getTokensByUser(e.userId);else if(e.email){let o=await this.resolveSystemId(e.systemId);r=await this.storage.findTokensByEmail(e.email,o);}else if(e.systemId&&e.scopeId)r=await this.storage.getTokensByScope(e.systemId,e.scopeId);else if(e.systemId)r=await this.storage.getTokensBySystem(e.systemId);else throw new Error("Must provide userId, email, or systemId");e.scopeId&&!e.systemId&&(r=r.filter(o=>o.scopeId===e.scopeId)),e.provider&&(r=r.filter(o=>o.provider===e.provider));let t=[],s=e.options||{};for(let o of r)try{let n=s.autoRefresh!==!1&&this.isTokenExpired(o.token,s),a=o.token;if(n){if(!o.token.refreshToken){console.warn(`Token for provider ${o.provider} expired and no refresh token available`);continue}let i=this.providers.get(o.provider);if(!i){console.warn(`Provider ${o.provider} not found`);continue}try{let d=await i.refreshToken(o.token.refreshToken);await this.storage.updateToken(o.id,{token:d}),a=d;}catch(d){console.warn(`Failed to refresh token for provider ${o.provider}:`,d);continue}}t.push({provider:o.provider,scopeId:o.scopeId,token:a,userToken:{...o,token:a}});}catch(n){console.warn(`Error processing token for provider ${o.provider}:`,n);continue}return t}async hasToken(e){if(e.email){let r=await this.resolveSystemId(e.systemId),t=await this.resolveScopeId(e.scopeId);return await this.storage.findTokenByEmailScopeProvider(e.email,r,t,e.provider)!==null}if(e.userId){let r=await this.resolveScopeId(e.scopeId);return (await this.storage.getTokensByUserScopeProvider(e.userId,r,e.provider)).length>0}throw new Error("Must provide either email or userId")}async deleteTokens(e){if(e.email&&e.provider){let r=await this.resolveSystemId(e.systemId),t=await this.resolveScopeId(e.scopeId),s=await this.storage.findTokenByEmailScopeProvider(e.email,r,t,e.provider);s&&await this.storage.deleteToken(s.id);return}if(e.userId&&e.scopeId&&e.provider){let r=await this.storage.getTokensByUserScopeProvider(e.userId,e.scopeId,e.provider);for(let t of r)await this.storage.deleteToken(t.id);return}if(e.userId&&e.provider){await this.storage.deleteTokensByUserAndProvider(e.userId,e.provider);return}if(e.userId&&e.scopeId){await this.storage.deleteTokensByUserAndScope(e.userId,e.scopeId);return}if(e.userId){await this.storage.deleteTokensByUser(e.userId);return}throw new Error("Invalid deletion parameters")}async createSystem(e,r){return this.storage.createSystem({name:e,description:r,scopes:[]})}async getSystem(e){if(e)return this.storage.getSystem(e);let{system:r}=await this.ensureDefaults();return r}async createScope(e){let r=await this.resolveSystemId(e.systemId);return this.storage.createScope({systemId:r,name:e.name,type:e.type||"authentication",permissions:e.permissions||[],isolated:e.isolated??true})}async getScope(e){if(e)return this.storage.getScope(e);let{scope:r}=await this.ensureDefaults();return r}async getScopesBySystem(e){let r=await this.resolveSystemId(e);return this.storage.getScopesBySystem(r)}isTokenExpired(e,r={}){let{expirationBuffer:t=300}=r;if(e.createdAt&&e.expiresIn!==void 0){let n=e.createdAt+e.expiresIn*1e3;return this.now()+t*1e3>=n}let s=new Date(e.expiresAt).getTime();return this.now()+t*1e3>=s}};var F=class u{storage;providerFactory;providers=new Map;providerConfigs=new Map;now;currentSystem;currentUser;defaultScope;granular;granularV2;constructor(e={}){this.storage=e.storage||new y,this.providerFactory=new x,this.now=Date.now,this.granular=new T(this.storage,this.providers,this.now),this.granularV2=new v(this.storage,this.providers,()=>({currentSystem:this.currentSystem,currentUser:this.currentUser,defaultScope:this.defaultScope}),this.now),e.providers&&Object.entries(e.providers).forEach(([r,t])=>{this.registerProvider(r,t);});}static async quickSetup(e,r){let t=new u({providers:r}),s=await t.createSystem(e);await t.useSystem(s.id);let o=await t.createScope("default",{type:"authentication",permissions:["*"],isolated:false});return t.setDefaultScope(o.id),t}registerProvider(e,r){this.providerConfigs.set(e,r);let t=this.detectProviderType(e,r),s=this.providerFactory.createProvider(t,r);this.providers.set(e,s);}async initializeDefaults(){let{system:e,scope:r}=await b(this.storage);return this.currentSystem||(this.currentSystem=e),this.defaultScope||(this.defaultScope=r),{system:e,scope:r}}async getDefaultSystem(){return C(this.storage)}async getDefaultScope(){return K(this.storage)}async createSystem(e,r){let t=await this.storage.createSystem({name:e,description:r,scopes:[]});return this.currentSystem=t,t}async useSystem(e){let r=await this.storage.getSystem(e);if(!r)throw new Error("System not found");this.currentSystem=r;}async createScope(e,r={}){if(!this.currentSystem)throw new Error("No system selected");return this.storage.createScope({systemId:this.currentSystem.id,name:e,type:r.type||"authentication",permissions:r.permissions||[],isolated:r.isolated??true})}setDefaultScope(e){this.defaultScope={id:e};}async createUser(e){if(!this.currentSystem)throw new Error("No system selected");let r=await this.storage.createUser({systemId:this.currentSystem.id,metadata:e});return this.currentUser=r,r}async getOrCreateUser(e={}){if(!this.currentSystem)throw new Error("No system selected");let r={systemId:this.currentSystem.id,email:e.email,externalId:e.externalId,metadata:e.metadata},t=await this.storage.getOrCreateUser(r);return this.currentUser=t,t}async getOrCreateUserStateless(e,r={}){let t={systemId:e,email:r.email,externalId:r.externalId,metadata:r.metadata};return this.storage.getOrCreateUser(t)}async authorizeForUser(e,r,t={}){var n,a;let s=t.systemId||((n=this.currentSystem)==null?void 0:n.id),o=t.scopeId||((a=this.defaultScope)==null?void 0:a.id);if(!s)throw new Error("System ID must be provided or current system must be set");return this.authorize({provider:r,scopes:t.scopes,metadata:{...t.metadata,systemId:s,scopeId:o},usePKCE:t.usePKCE,userId:e})}async createUserAndAuthorize(e,r,t,s={}){let o=await this.getOrCreateUserStateless(e,t),{url:n,state:a}=await this.authorizeForUser(o.id,r,{systemId:e,...s});return {user:o,authUrl:n,state:a}}async findUserByEmail(e){if(!this.currentSystem)throw new Error("No system selected");return this.storage.findUserByEmail(this.currentSystem.id,e)}async findUserByEmailStateless(e,r){return this.storage.findUserByEmail(e,r)}async findUserByExternalId(e){if(!this.currentSystem)throw new Error("No system selected");return this.storage.findUserByExternalId(this.currentSystem.id,e)}async findUserByExternalIdStateless(e,r){return this.storage.findUserByExternalId(e,r)}async useUser(e){let r=await this.storage.getUser(e);if(!r)throw new Error("User not found");this.currentUser=r;}async authorize(e){var l,m,g;let r=this.providerConfigs.get(e.provider);if(!r)throw new Error(`Provider ${e.provider} not registered`);(!this.currentSystem||!this.defaultScope)&&await this.initializeDefaults();let t={...r,scopes:e.scopes||r.scopes,usePKCE:e.usePKCE??r.usePKCE??r.pkce},s=V(),o,n;(t.usePKCE||t.pkce)&&(o=_(),n=N(o));let a=e.userId||((l=this.currentUser)==null?void 0:l.id),i={state:s,codeVerifier:o,config:t,timestamp:new Date,metadata:{...e.metadata,provider:e.provider,userId:a,systemId:(m=this.currentSystem)==null?void 0:m.id,scopeId:(g=this.defaultScope)==null?void 0:g.id}};await this.storage.saveAuthorizationState(i);let d=this.providers.get(e.provider);if(!d)throw new Error(`Provider ${e.provider} not found`);return {url:d.generateAuthorizationUrl(s,n),state:s}}async handleCallback(e,r,t){var f,$,z,R;let s=await this.storage.getAuthorizationState(r);if(!s)throw new Error("Invalid or expired state");let o=s.metadata||{},n=o.provider;if(console.log("metadata [",o,"]"),!n)throw new Error("Provider not found in state");(!this.currentSystem||!this.defaultScope)&&await this.initializeDefaults();let a=(t==null?void 0:t.userId)||o.userId||((f=this.currentUser)==null?void 0:f.id);console.log("userId [",a,"]");let i=o.systemId||(($=this.currentSystem)==null?void 0:$.id),d=(t==null?void 0:t.scopeId)||o.scopeId||((z=this.defaultScope)==null?void 0:z.id);if(!a||!i||!d)throw new Error("Missing required context: userId, systemId, or scopeId");let c=this.providers.get(n);if(!c)throw new Error(`Provider ${n} not found`);let l=await c.exchangeCodeForToken(e,s.codeVerifier);await this.storage.deleteAuthorizationState(r);let m,g;if(console.log("providerInstance.hasProfileFetcher() [",c.hasProfileFetcher(),"]"),c.hasProfileFetcher())try{g=await c.fetchProfile(l.accessToken),console.log("profile [",g,"]"),m=await this.storage.saveTokenWithEmailValidation(a,i,d,n,g.email,{userId:a,systemId:i,scopeId:d,provider:n,token:l}),(R=t==null?void 0:t.profileOptions)!=null&&R.mergeUserData&&await this.mergeUserDataFromProfile(a,g);}catch(G){console.warn("Failed to fetch profile or save with email validation:",G),m=await this.storage.saveToken({userId:a,systemId:i,scopeId:d,provider:n,token:l});}else m=await this.storage.saveToken({userId:a,systemId:i,scopeId:d,provider:n,token:l});return {userToken:m,userId:a,systemId:i,scopeId:d,provider:n,profile:g}}async mergeUserDataFromProfile(e,r){var o,n,a,i;let t=await this.storage.getUser(e);if(!t)return;let s={...t.metadata,email:r.email,name:r.name||((o=t.metadata)==null?void 0:o.name),avatar:r.avatar||((n=t.metadata)==null?void 0:n.avatar),username:r.username||((a=t.metadata)==null?void 0:a.username),profileId:r.id||((i=t.metadata)==null?void 0:i.profileId),lastProfileUpdate:new Date().toISOString()};await this.storage.updateUser(e,{metadata:s});}async fetchUserProfile(e,r){var c,l;if(!r&&!this.currentUser)throw new Error("No user specified and no current user set");(!this.currentSystem||!this.defaultScope)&&await this.initializeDefaults();let t=r||this.currentUser.id,s=(c=this.currentSystem)==null?void 0:c.id,o=(l=this.defaultScope)==null?void 0:l.id;if(!s||!o)throw new Error("Missing system or scope context");let n=await this.storage.getTokensByUserScopeProvider(t,o,e);if(n.length===0)throw new Error("No token found for user and provider");if(n.length>1)throw new Error(`Multiple tokens found for provider ${e}. Use fetchUserProfileByEmail() to specify which token to use.`);let a=this.providers.get(e);if(!a)throw new Error(`Provider ${e} not found`);let i=n[0];if(!i)throw new Error("Token not found");let d=i.token.accessToken;return a.fetchProfile(d)}async fetchUserProfileByEmail(e,r,t,s){var d,c;let o=t||((d=this.currentSystem)==null?void 0:d.id),n=s||((c=this.defaultScope)==null?void 0:c.id);if(!o)throw new Error("System ID must be provided or current system must be set");if(!n)throw new Error("Scope ID must be provided or default scope must be set");let a=await this.getAccessTokenByEmail(r,e,o,n),i=this.providers.get(e);if(!i)throw new Error(`Provider ${e} not found`);return i.fetchProfile(a)}async replaceConflictingTokensByEmail(e,r,t,s){if(!this.currentSystem||!this.defaultScope)throw new Error("Missing system or scope context");return this.storage.replaceTokensByEmailInUserScopeProvider(t,this.defaultScope.id,r,e,{userId:t,systemId:this.currentSystem.id,scopeId:this.defaultScope.id,provider:r,token:s})}isTokenExpired(e,r={}){let{expirationBuffer:t=300}=r;if(e.createdAt&&e.expiresIn!==void 0){let n=e.createdAt+e.expiresIn*1e3;return this.now()+t*1e3>=n}let s=new Date(e.expiresAt).getTime();return this.now()+t*1e3>=s}async getAccessToken(e,r={}){if(!this.currentUser||!this.currentSystem||!this.defaultScope)throw new Error("Missing required context");let t=await this.storage.getTokensByUserScopeProvider(this.currentUser.id,this.defaultScope.id,e);if(t.length===0)throw new Error("No token found for provider");if(t.length>1)throw new Error(`Multiple tokens found for provider ${e}. Use getAccessTokenByEmail() or getAllValidTokensForUser() to specify which token to use.`);let s=t[0];if(!s)throw new Error("No token found for provider");if(!(r.autoRefresh!==false&&this.isTokenExpired(s.token,r)))return s.token.accessToken;if(!s.token.refreshToken)throw new Error("Token expired and no refresh token available");let n=this.providers.get(e);if(!n)throw new Error(`Provider ${e} not found`);let a=await n.refreshToken(s.token.refreshToken);return await this.storage.updateToken(s.id,{token:a}),a.accessToken}async getAccessTokenByEmail(e,r,t,s,o={}){return (await this.getValidTokenForEmail(e,s,r,t,o)).accessToken}async ensureValidToken(e,r={}){if(!this.currentUser||!this.currentSystem||!this.defaultScope)throw new Error("Missing required context");let t=await this.storage.getTokensByUserScopeProvider(this.currentUser.id,this.defaultScope.id,e);if(t.length===0)throw new Error(`No tokens found for provider ${e}`);if(t.length>1)throw new Error(`Multiple tokens found for provider ${e}. Use getValidTokenForEmail() to specify which token to use.`);let s=t[0];if(!s)throw new Error(`No tokens found for provider ${e}`);if(!this.isTokenExpired(s.token,r))return s.token;if(!s.token.refreshToken)throw new Error("Token expired and no refresh token available");let o=this.providers.get(e);if(!o)throw new Error(`Provider ${e} not found`);let n=await o.refreshToken(s.token.refreshToken);return await this.storage.updateToken(s.id,{token:n}),n}async withValidToken(e,r,t={}){let s=await this.ensureValidToken(e,t);return await r(s.accessToken)}async getUserTokenForUser(e,r,t,s){let o=await this.storage.getTokensByUserScopeProvider(e,t,s);return o.length>0&&o[0]?o[0]:null}async hasTokenForUser(e,r,t,s){return (await this.storage.getTokensByUserScopeProvider(e,t,s)).length>0}async revokeTokensForUser(e,r,t,s){let o=await this.storage.getTokensByUserScopeProvider(e,t,s);for(let n of o)await this.storage.deleteToken(n.id);}async revokeTokens(e){if(!this.currentUser||!this.currentSystem||!this.defaultScope)throw new Error("Missing required context");let r=await this.storage.getTokensByUserScopeProvider(this.currentUser.id,this.defaultScope.id,e);for(let t of r)await this.storage.deleteToken(t.id);}async getUserTokens(){if(!this.currentUser)throw new Error("No user selected");return this.storage.getTokensByUser(this.currentUser.id)}async getAllValidTokensForUser(e,r={}){let t=await this.storage.getTokensByUser(e),s=[];for(let o of t)if(o)try{let n=r.autoRefresh!==!1&&this.isTokenExpired(o.token,r),a=o.token;if(n){if(!o.token.refreshToken){console.warn(`Token for provider ${o.provider} expired and no refresh token available`);continue}let i=this.providers.get(o.provider);if(!i){console.warn(`Provider ${o.provider} not found`);continue}try{let d=await i.refreshToken(o.token.refreshToken);await this.storage.updateToken(o.id,{token:d}),a=d;}catch(d){console.warn(`Failed to refresh token for provider ${o.provider}:`,d);continue}}s.push({provider:o.provider,scopeId:o.scopeId,token:a,userToken:{...o,token:a}});}catch(n){console.warn(`Error processing token for provider ${o.provider}:`,n);continue}return s}async getAllValidTokensForEmail(e,r,t={}){var a;let s=r||((a=this.currentSystem)==null?void 0:a.id);if(!s)throw new Error("System ID must be provided or current system must be set");let o=await this.storage.findTokensByEmail(e,s),n=[];for(let i of o)if(i)try{let d=t.autoRefresh!==!1&&this.isTokenExpired(i.token,t),c=i.token;if(d){if(!i.token.refreshToken){console.warn(`Token for provider ${i.provider} expired and no refresh token available`);continue}let l=this.providers.get(i.provider);if(!l){console.warn(`Provider ${i.provider} not found`);continue}try{let m=await l.refreshToken(i.token.refreshToken);await this.storage.updateToken(i.id,{token:m}),c=m;}catch(m){console.warn(`Failed to refresh token for provider ${i.provider}:`,m);continue}}n.push({provider:i.provider,scopeId:i.scopeId,token:c,userToken:{...i,token:c}});}catch(d){console.warn(`Error processing token for provider ${i.provider}:`,d);continue}return n}async getTokenForEmail(e,r,t,s){var a,i;let o=t||((a=this.currentSystem)==null?void 0:a.id),n=s||((i=this.defaultScope)==null?void 0:i.id);if(!o)throw new Error("System ID must be provided or current system must be set");if(!n)throw new Error("Scope ID must be provided or default scope must be set");return this.storage.findTokenByEmailScopeProvider(e,o,n,r)}async getValidTokenForEmail(e,r,t,s,o={}){var m,g;let n=t||((m=this.currentSystem)==null?void 0:m.id),a=s||((g=this.defaultScope)==null?void 0:g.id);if(!n)throw new Error("System ID must be provided or current system must be set");if(!a)throw new Error("Scope ID must be provided or default scope must be set");let i=await this.storage.findTokenByEmailScopeProvider(e,n,a,r);if(!i)throw new Error(`No token found for email ${e} and provider ${r}`);if(!(o.autoRefresh!==false&&this.isTokenExpired(i.token,o)))return i.token;if(!i.token.refreshToken)throw new Error("Token expired and no refresh token available");let c=this.providers.get(r);if(!c)throw new Error(`Provider ${r} not found`);let l=await c.refreshToken(i.token.refreshToken);return await this.storage.updateToken(i.id,{token:l}),l}async getAccessTokenForEmail(e,r,t,s,o={}){return (await this.getValidTokenForEmail(e,r,t,s,o)).accessToken}async withValidTokenForEmail(e,r,t,s,o,n={}){let a=await this.getValidTokenForEmail(e,r,s,o,n);return await t(a.accessToken)}async hasTokenForEmail(e,r,t,s){var i,d;let o=t||((i=this.currentSystem)==null?void 0:i.id),n=s||((d=this.defaultScope)==null?void 0:d.id);if(!o)throw new Error("System ID must be provided or current system must be set");if(!n)throw new Error("Scope ID must be provided or default scope must be set");return await this.storage.findTokenByEmailScopeProvider(e,o,n,r)!==null}async revokeTokensForEmail(e,r,t,s){var i,d;let o=t||((i=this.currentSystem)==null?void 0:i.id),n=s||((d=this.defaultScope)==null?void 0:d.id);if(!o)throw new Error("System ID must be provided or current system must be set");if(!n)throw new Error("Scope ID must be provided or default scope must be set");let a=await this.storage.findTokenByEmailScopeProvider(e,o,n,r);a&&await this.storage.deleteToken(a.id);}async getTokensByScope(e,r){var o,n;let t=e||((o=this.currentSystem)==null?void 0:o.id),s=r||((n=this.defaultScope)==null?void 0:n.id);if(!t)throw new Error("System ID must be provided or current system must be set");if(!s)throw new Error("Scope ID must be provided or default scope must be set");return this.storage.getTokensByScope(t,s)}async findTokenByEmailAndScope(e,r,t,s){var a,i;let o=t||((a=this.currentSystem)==null?void 0:a.id),n=s||((i=this.defaultScope)==null?void 0:i.id);if(!o)throw new Error("System ID must be provided or current system must be set");if(!n)throw new Error("Scope ID must be provided or default scope must be set");return this.storage.findTokenByEmailScopeProvider(e,o,n,r)}async findAllTokensByEmailAndScope(e,r,t,s){var a,i;let o=t||((a=this.currentSystem)==null?void 0:a.id),n=s||((i=this.defaultScope)==null?void 0:i.id);if(!o)throw new Error("System ID must be provided or current system must be set");if(!n)throw new Error("Scope ID must be provided or default scope must be set");return this.storage.findTokensByEmailAndScope(e,o,n).then(d=>d.filter(c=>c.provider===r))}detectProviderType(e,r){return ["google","github","microsoft","outlook","facebook"].includes(e)?e:r.authorizationUrl.includes("google.com")?"google":r.authorizationUrl.includes("github.com")?"github":r.authorizationUrl.includes("microsoft.com")||r.authorizationUrl.includes("microsoftonline.com")?"microsoft":r.authorizationUrl.includes("facebook.com")?"facebook":"generic"}async cleanup(e=10*60*1e3){await this.storage.cleanupExpiredStates(e);}async getAllValidTokensWithProviderProfiles(e,r={}){let t=await this.storage.getTokensByUser(e),s=[];for(let o of t)if(o)try{let n=r.autoRefresh!==!1&&this.isTokenExpired(o.token,r),a=o.token;if(n){if(!o.token.refreshToken){console.warn(`Token for provider ${o.provider} expired and no refresh token available`);continue}let c=this.providers.get(o.provider);if(!c){console.warn(`Provider ${o.provider} not found`);continue}try{let l=await c.refreshToken(o.token.refreshToken);await this.storage.updateToken(o.id,{token:l}),a=l;}catch(l){console.warn(`Failed to refresh token for provider ${o.provider}:`,l);continue}}let i,d=this.providers.get(o.provider);if(d&&d.hasProfileFetcher())try{i=await d.fetchProfile(a.accessToken);}catch(c){console.warn(`Failed to fetch profile for provider ${o.provider}:`,c);}s.push({provider:o.provider,scopeId:o.scopeId,token:a,userToken:{...o,token:a},profile:i});}catch(n){console.warn(`Error processing token for provider ${o.provider}:`,n);continue}return s}async getAllValidTokensForUserAndScopeWithProviderProfiles(e,r,t={}){let s=await this.storage.getTokensByUserAndScope(e,r),o=[];for(let n of s)if(n)try{let a=t.autoRefresh!==!1&&this.isTokenExpired(n.token,t),i=n.token;if(a){if(!n.token.refreshToken){console.warn(`Token for provider ${n.provider} expired and no refresh token available`);continue}let l=this.providers.get(n.provider);if(!l){console.warn(`Provider ${n.provider} not found`);continue}try{let m=await l.refreshToken(n.token.refreshToken);await this.storage.updateToken(n.id,{token:m}),i=m;}catch(m){console.warn(`Failed to refresh token for provider ${n.provider}:`,m);continue}}let d,c=this.providers.get(n.provider);if(c&&c.hasProfileFetcher())try{d=await c.fetchProfile(i.accessToken);}catch(l){console.warn(`Failed to fetch profile for provider ${n.provider}:`,l);}o.push({provider:n.provider,token:i,userToken:{...n,token:i},profile:d});}catch(a){console.warn(`Error processing token for provider ${n.provider}:`,a);continue}return o}async getAllValidTokensForUserAndProviderWithProviderProfiles(e,r,t={}){let s=await this.storage.getTokensByUserAndProvider(e,r),o=[];for(let n of s)if(n)try{let a=t.autoRefresh!==!1&&this.isTokenExpired(n.token,t),i=n.token;if(a){if(!n.token.refreshToken){console.warn(`Token for provider ${n.provider} expired and no refresh token available`);continue}let l=this.providers.get(n.provider);if(!l){console.warn(`Provider ${n.provider} not found`);continue}try{let m=await l.refreshToken(n.token.refreshToken);await this.storage.updateToken(n.id,{token:m}),i=m;}catch(m){console.warn(`Failed to refresh token for provider ${n.provider}:`,m);continue}}let d,c=this.providers.get(n.provider);if(c&&c.hasProfileFetcher())try{d=await c.fetchProfile(i.accessToken);}catch(l){console.warn(`Failed to fetch profile for provider ${n.provider}:`,l);}o.push({scopeId:n.scopeId,token:i,userToken:{...n,token:i},profile:d});}catch(a){console.warn(`Error processing token for provider ${n.provider}:`,a);continue}return o}async getTokenProfile(e,r){let t=this.providers.get(r);if(!t||!t.hasProfileFetcher())return null;try{return await t.fetchProfile(e.accessToken)}catch(s){return console.warn(`Failed to fetch profile for provider ${r}:`,s),null}}async getUserTokenProfile(e){return this.getTokenProfile(e.token,e.provider)}};var _e=(u,e)=>sealData(u,{password:e}),Ne=(u,e)=>unsealData(u,{password:e});
|
|
2
|
-
export{
|
|
1
|
+
import {createHash,randomBytes}from'crypto';import {sealData,unsealData}from'iron-session';var f=class{buildUrlParams(e){return Object.entries(e).filter(([,r])=>r!==void 0).map(([r,o])=>`${r}=${encodeURIComponent(o)}`).join("&")}generateAuthorizationUrl(e,t,r){let o={client_id:e.clientId,redirect_uri:e.redirectUri,response_type:"code",scope:e.scopes.join(" "),state:t};(e.usePKCE||e.pkce)&&r&&(o.code_challenge=r,o.code_challenge_method="S256");let i={...e.additionalParams,...e.extraAuthParams};return Object.assign(o,i),`${e.authorizationUrl}?${this.buildUrlParams(o)}`}};var g=class{buildUrlParams(e){return Object.entries(e).filter(([,r])=>r!==void 0).map(([r,o])=>`${r}=${encodeURIComponent(o)}`).join("&")}async exchangeCodeForToken(e,t,r){let o={grant_type:"authorization_code",code:e,redirect_uri:t.redirectUri,client_id:t.clientId};(t.usePKCE||t.pkce)&&r?o.code_verifier=r:t.clientSecret&&(o.client_secret=t.clientSecret);let i=await fetch(t.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildUrlParams(o)});if(!i.ok){let x=await i.text();throw new Error(`Token exchange failed: ${i.statusText} - ${x}`)}let s=await i.json(),a=t.responseRootKey?s[t.responseRootKey]:s,c=Date.now(),p=a.expires_in||3600;return {accessToken:a.access_token,refreshToken:a.refresh_token,expiresAt:new Date(c+p*1e3),expiresIn:p,tokenType:a.token_type||"Bearer",scope:a.scope,createdAt:c,raw:s}}async refreshToken(e,t){let r={grant_type:"refresh_token",refresh_token:e,client_id:t.clientId};!(t.usePKCE||t.pkce)&&t.clientSecret&&(r.client_secret=t.clientSecret);let o=await fetch(t.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildUrlParams(r)});if(!o.ok){let p=await o.text();throw new Error(`Token refresh failed: ${o.statusText} - ${p}`)}let i=await o.json(),s=t.responseRootKey?i[t.responseRootKey]:i,a=Date.now(),c=s.expires_in||3600;return {accessToken:s.access_token,refreshToken:s.refresh_token||e,expiresAt:new Date(a+c*1e3),expiresIn:c,tokenType:s.token_type||"Bearer",scope:s.scope,createdAt:a,raw:i}}};var u=class{constructor(e,t,r,o){this.config=e;this.authUrlStrategy=t||this.createAuthorizationUrlStrategy(),this.tokenStrategy=r||this.createTokenExchangeStrategy(),this.profileFetcher=o;}authUrlStrategy;tokenStrategy;profileFetcher;async fetchProfile(e){if(!this.profileFetcher)throw new Error("Profile fetcher not configured for this provider");return this.profileFetcher.fetchUserInfo(e)}getProfileEndpoint(){if(!this.profileFetcher)throw new Error("Profile fetcher not configured for this provider");return this.profileFetcher.getEndpoint()}setProfileFetcher(e){this.profileFetcher=e;}hasProfileFetcher(){return !!this.profileFetcher}generateAuthorizationUrl(e,t){return this.authUrlStrategy.generateAuthorizationUrl(this.config,e,t)}async exchangeCodeForToken(e,t){return this.tokenStrategy.exchangeCodeForToken(e,this.config,t)}async refreshToken(e){return this.tokenStrategy.refreshToken(e,this.config)}};var k=class extends u{constructor(e,t,r,o){super(e,t,r,o);}createAuthorizationUrlStrategy(){return new f}createTokenExchangeStrategy(){return new g}};var d=class{constructor(e){this.profileEndpoint=e;}async fetchUserInfo(e){let t=await fetch(this.profileEndpoint,{headers:{Authorization:`Bearer ${e}`,Accept:"application/json",...this.getAdditionalHeaders()}});if(!t.ok)throw new Error(`Failed to fetch profile from ${this.profileEndpoint}: ${t.statusText}`);let r=await t.json();return this.mapToUserProfile(r)}getAdditionalHeaders(){return {}}getEndpoint(){return this.profileEndpoint}};var P=class extends d{constructor(){super("https://www.googleapis.com/oauth2/v2/userinfo");}mapToUserProfile(e){return {email:e.email,name:e.name,id:e.id,avatar:e.picture,username:e.email,raw:e}}};var T=class extends d{constructor(){super("https://api.github.com/user");}mapToUserProfile(e){var t;return {email:e.email,name:e.name||e.login,id:(t=e.id)==null?void 0:t.toString(),avatar:e.avatar_url,username:e.login,raw:e}}getAdditionalHeaders(){return {"User-Agent":"OAuth2-Token-Manager"}}};var v=class extends d{constructor(){super("https://graph.microsoft.com/v1.0/me");}mapToUserProfile(e){return {email:e.mail||e.userPrincipalName,name:e.displayName,id:e.id,avatar:void 0,username:e.userPrincipalName,raw:e}}};var l=class extends d{constructor(t,r,o){super(t);this.mapping=r;this.additionalHeaders=o;}mapToUserProfile(t){return this.mapping?{email:this.getNestedProperty(t,this.mapping.email),name:this.mapping.name?this.getNestedProperty(t,this.mapping.name):void 0,id:this.mapping.id?this.getNestedProperty(t,this.mapping.id):void 0,avatar:this.mapping.avatar?this.getNestedProperty(t,this.mapping.avatar):void 0,username:this.mapping.username?this.getNestedProperty(t,this.mapping.username):void 0,raw:t}:{email:t.email||t.mail||t.emailAddress,name:t.name||t.displayName||t.full_name,id:t.id||t.sub||t.user_id,avatar:t.avatar||t.picture||t.avatar_url,username:t.username||t.login||t.preferred_username,raw:t}}getAdditionalHeaders(){return this.additionalHeaders||{}}getNestedProperty(t,r){return r.split(".").reduce((o,i)=>o==null?void 0:o[i],t)}};var y=class{static createProfileFetcher(e,t,r){if(r!=null&&r.profileUrl)return new l(r.profileUrl,r.profileMapping,r.profileHeaders);switch(e){case "google":return new P;case "github":return new T;case "microsoft":case "outlook":return new v;case "facebook":return new l("https://graph.facebook.com/me?fields=id,name,email,picture");case "generic":default:let o=t.profileUrl||t.userInfoUrl;if(!o)throw new Error(`Profile URL must be provided for ${e} provider`);return new l(o)}}static registerCustomProfileFetcher(e,t){this.customFetchers.set(e,t);}static customFetchers=new Map;static getCustomProfileFetcher(e){return this.customFetchers.get(e)}};var A=class n{static presetConfigs={google:{authorizationUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",profileUrl:"https://www.googleapis.com/oauth2/v2/userinfo",usePKCE:true,extraAuthParams:{access_type:"offline",prompt:"consent"}},github:{authorizationUrl:"https://github.com/login/oauth/authorize",tokenUrl:"https://github.com/login/oauth/access_token",profileUrl:"https://api.github.com/user"},microsoft:{authorizationUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",tokenUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/token",profileUrl:"https://graph.microsoft.com/v1.0/me",usePKCE:true},outlook:{authorizationUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",tokenUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/token",profileUrl:"https://graph.microsoft.com/v1.0/me",usePKCE:true,extraAuthParams:{prompt:"select_account"}},facebook:{authorizationUrl:"https://www.facebook.com/v12.0/dialog/oauth",tokenUrl:"https://graph.facebook.com/v12.0/oauth/access_token",profileUrl:"https://graph.facebook.com/me?fields=id,name,email,picture"}};createProvider(e,t){let r=e!=="generic"?n.presetConfigs[e]||{}:{},o={...r,...t,authorizationUrl:t.authorizationUrl||r.authorizationUrl||"",tokenUrl:t.tokenUrl||r.tokenUrl||"",profileUrl:t.profileUrl||r.profileUrl,extraAuthParams:{...r.extraAuthParams||{},...t.extraAuthParams||{}}},i=y.createProfileFetcher(e,o);return new k(o,void 0,void 0,i)}static registerPreset(e,t){n.presetConfigs[e]=t;}static getPresetConfig(e){return n.presetConfigs[e]}};var h=class{tokens=new Map;states=new Map;generateId(){return Math.random().toString(36).substring(2)+Date.now().toString(36)}async saveToken(e){let t=await this.getToken(e.provider,e.email);if(t){let o={...t,...e,id:t.id,createdAt:t.createdAt,updatedAt:new Date};return this.tokens.set(t.id,o),o}let r={...e,id:this.generateId(),createdAt:new Date,updatedAt:new Date};return this.tokens.set(r.id,r),r}async getToken(e,t){return Array.from(this.tokens.values()).find(o=>o.provider===e&&o.email===t)||null}async getTokenById(e){return this.tokens.get(e)||null}async getTokensByUserId(e){return Array.from(this.tokens.values()).filter(t=>t.userId===e)}async getTokensByEmail(e){return Array.from(this.tokens.values()).filter(t=>t.email===e)}async getTokensByProvider(e){return Array.from(this.tokens.values()).filter(t=>t.provider===e)}async updateToken(e,t){let r=this.tokens.get(e);if(!r)return null;let o={...r,...t.token&&{token:t.token},...t.metadata&&{metadata:{...r.metadata,...t.metadata}},updatedAt:new Date};return this.tokens.set(e,o),o}async deleteToken(e){return this.tokens.delete(e)}async deleteTokenByProviderEmail(e,t){let r=await this.getToken(e,t);return r?this.tokens.delete(r.id):false}async deleteExpiredTokens(){let e=new Date().getTime(),t=Array.from(this.tokens.entries()).filter(([,r])=>new Date(r.token.expiresAt).getTime()<e).map(([r])=>r);return t.forEach(r=>this.tokens.delete(r)),t.length}async saveAuthorizationState(e){let t={...e,createdAt:new Date(Date.now())};return this.states.set(e.state,t),t}async getAuthorizationState(e){return this.states.get(e)||null}async deleteAuthorizationState(e){return this.states.delete(e)}async cleanupExpiredStates(){let e=new Date().getTime(),t=10*60*1e3,r=Array.from(this.states.entries()).filter(([,o])=>e-o.createdAt.getTime()>t).map(([o])=>o);return r.forEach(o=>this.states.delete(o)),r.length}};var O=()=>randomBytes(32).toString("base64").replace(/[^a-zA-Z0-9]/g,"").substring(0,128),E=n=>createHash("sha256").update(n).digest("base64url"),z=()=>randomBytes(16).toString("base64url");var U=class{storage;providerFactory;providers=new Map;providerConfigs=new Map;now;constructor(e={}){this.storage=e.storage||new h,this.providerFactory=new A,this.now=Date.now,e.providers&&Object.entries(e.providers).forEach(([t,r])=>{this.registerProvider(t,r);});}registerProvider(e,t){this.providerConfigs.set(e,t);let r=this.detectProviderType(e,t),o=this.providerFactory.createProvider(r,t);this.providers.set(e,o);}async authorize(e){var a;let t=this.providers.get(e.provider);if(!t)throw new Error(`Provider ${e.provider} not found`);let r=z(),o,i;if(((a=this.providerConfigs.get(e.provider))==null?void 0:a.usePKCE)||e.usePKCE){let c=O(),p=E(c);o=t.generateAuthorizationUrl(r,p),i={state:r,codeVerifier:c,config:this.providerConfigs.get(e.provider),metadata:{...e.metadata,userId:e.userId,email:e.email,provider:e.provider}};}else o=t.generateAuthorizationUrl(r),i={state:r,config:this.providerConfigs.get(e.provider),metadata:{...e.metadata,userId:e.userId,email:e.email,provider:e.provider}};return await this.storage.saveAuthorizationState(i),{url:o,state:r}}async handleCallback(e,t){var S,w,C;let r=await this.storage.getAuthorizationState(t);if(!r)throw new Error("Invalid or expired state");let o=(S=r.metadata)==null?void 0:S.provider;if(!o)throw new Error("Provider not found in authorization state");let i=this.providers.get(o);if(!i)throw new Error(`Provider ${o} not found`);let s=await i.exchangeCodeForToken(e,r.codeVerifier),a=(w=r.metadata)==null?void 0:w.userId,c=(C=r.metadata)==null?void 0:C.email;if(!a||!c)throw new Error("User ID and email are required in authorization state");let p;if(i.hasProfileFetcher())try{p=await i.fetchProfile(s.accessToken);}catch(F){console.warn("Failed to fetch user profile:",F);}let x=await this.storage.saveToken({provider:o,userId:a,email:c,token:s,metadata:{...r.metadata,profileFetched:!!p}});await this.storage.deleteAuthorizationState(t);let m=this.providerConfigs.get(o);return m!=null&&m.onSuccess&&await m.onSuccess(a,s),{token:x,profile:p}}async getAccessToken(e,t,r={}){return (await this.getValidToken(e,t,r)).accessToken}async getValidToken(e,t,r={}){let o=await this.storage.getToken(e,t);if(!o)throw new Error(`No token found for provider ${e} and email ${t}`);if(!(r.autoRefresh!==false&&this.isTokenExpired(o.token,r)))return o.token;if(!o.token.refreshToken)throw new Error("Token expired and no refresh token available");let s=this.providers.get(e);if(!s)throw new Error(`Provider ${e} not found`);let a=await s.refreshToken(o.token.refreshToken);return await this.storage.updateToken(o.id,{token:a}),a}async getTokensByUserId(e){return this.storage.getTokensByUserId(e)}async getTokensByEmail(e){return this.storage.getTokensByEmail(e)}async deleteToken(e,t){return this.storage.deleteTokenByProviderEmail(e,t)}async cleanupExpiredTokens(){return this.storage.deleteExpiredTokens()}async cleanupExpiredStates(){return this.storage.cleanupExpiredStates()}isTokenExpired(e,t={}){let{expirationBuffer:r=300}=t;if(e.createdAt&&e.expiresIn!==void 0){let s=e.createdAt+e.expiresIn*1e3;return this.now()+r*1e3>=s}let o=new Date(e.expiresAt).getTime();return this.now()+r*1e3>=o}detectProviderType(e,t){var o;let r=t.authorizationUrl.toLowerCase();return r.includes("accounts.google.com")?"google":r.includes("github.com")?"github":r.includes("facebook.com")?"facebook":r.includes("microsoft.com")||r.includes("microsoftonline.com")?e.toLowerCase().includes("outlook")||(o=t.scopes)!=null&&o.some(i=>i.includes("outlook"))?"outlook":"microsoft":"generic"}};var ge=(n,e)=>sealData(n,{password:e}),ke=(n,e)=>unsealData(n,{password:e});
|
|
2
|
+
export{d as BaseProfileFetcher,k as GenericOAuth2Provider,l as GenericProfileFetcher,T as GitHubProfileFetcher,P as GoogleProfileFetcher,h as InMemoryStorageAdapter,v as MicrosoftProfileFetcher,U as OAuth2Client,u as OAuth2Provider,y as ProfileFetcherFactory,f as StandardAuthorizationUrlStrategy,g as StandardTokenExchangeStrategy,E as createCodeChallenge,O as createCodeVerifier,z as generateState,ge as seal,ke as unseal};//# sourceMappingURL=index.js.map
|
|
3
3
|
//# sourceMappingURL=index.js.map
|