@dainprotocol/oauth2-token-manager 0.1.2 → 0.1.5
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/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
'use strict';var crypto=require('crypto'),ironSession=require('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=()=>crypto.randomBytes(32).toString("base64").replace(/[^a-zA-Z0-9]/g,"").substring(0,128),E=n=>crypto.createHash("sha256").update(n).digest("base64url"),z=()=>crypto.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)=>ironSession.sealData(n,{password:e}),ke=(n,e)=>ironSession.unsealData(n,{password:e});
|
|
2
|
-
exports.BaseProfileFetcher=d;exports.GenericOAuth2Provider=k;exports.GenericProfileFetcher=l;exports.GitHubProfileFetcher=T;exports.GoogleProfileFetcher=P;exports.InMemoryStorageAdapter=h;exports.MicrosoftProfileFetcher=v;exports.OAuth2Client=U;exports.OAuth2Provider=u;exports.ProfileFetcherFactory=y;exports.StandardAuthorizationUrlStrategy=f;exports.StandardTokenExchangeStrategy=g;exports.createCodeChallenge=
|
|
1
|
+
'use strict';var crypto=require('crypto'),ironSession=require('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 getAccounts(e,t){return Array.from(this.tokens.values()).filter(r=>r.userId===e&&r.provider===t)}async getTokensForEmail(e,t,r){let o=await this.getToken(t,r);return o&&o.userId===e?o:null}async getTokens(e,t){return Array.from(this.tokens.values()).filter(r=>r.userId===e&&r.provider===t)}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 E=()=>crypto.randomBytes(32).toString("base64").replace(/[^a-zA-Z0-9]/g,"").substring(0,128),O=n=>crypto.createHash("sha256").update(n).digest("base64url"),z=()=>crypto.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=E(),p=O(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)=>ironSession.sealData(n,{password:e}),ke=(n,e)=>ironSession.unsealData(n,{password:e});
|
|
2
|
+
exports.BaseProfileFetcher=d;exports.GenericOAuth2Provider=k;exports.GenericProfileFetcher=l;exports.GitHubProfileFetcher=T;exports.GoogleProfileFetcher=P;exports.InMemoryStorageAdapter=h;exports.MicrosoftProfileFetcher=v;exports.OAuth2Client=U;exports.OAuth2Provider=u;exports.ProfileFetcherFactory=y;exports.StandardAuthorizationUrlStrategy=f;exports.StandardTokenExchangeStrategy=g;exports.createCodeChallenge=O;exports.createCodeVerifier=E;exports.generateState=z;exports.seal=ge;exports.unseal=ke;//# sourceMappingURL=index.cjs.map
|
|
3
3
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/strategies/standard-authorization-url.strategy.ts","../src/strategies/standard-token-exchange.strategy.ts","../src/providers/base.provider.ts","../src/providers/generic.provider.ts","../src/profile/base-profile-fetcher.ts","../src/profile/google-profile-fetcher.ts","../src/profile/github-profile-fetcher.ts","../src/profile/microsoft-profile-fetcher.ts","../src/profile/generic-profile-fetcher.ts","../src/profile/profile-fetcher-factory.ts","../src/providers/provider.factory.ts","../src/storage/memory.adapter.ts","../src/utils/crypto.ts","../src/facade/oauth2.facade.ts","../src/utils/seal.ts"],"names":["StandardAuthorizationUrlStrategy","params","value","key","config","state","codeChallenge","extraParams","StandardTokenExchangeStrategy","code","codeVerifier","response","errorText","data","tokenData","now","expiresIn","refreshToken","OAuth2Provider","authUrlStrategy","tokenStrategy","profileFetcher","accessToken","GenericOAuth2Provider","BaseProfileFetcher","profileEndpoint","rawData","GoogleProfileFetcher","GitHubProfileFetcher","_a","MicrosoftProfileFetcher","GenericProfileFetcher","mapping","additionalHeaders","obj","path","current","ProfileFetcherFactory","providerType","options","profileUrl","providerName","OAuth2ProviderFactory","_OAuth2ProviderFactory","type","presetConfig","mergedConfig","name","InMemoryStorageAdapter","input","existingToken","updatedToken","newToken","provider","email","t","id","userId","update","token","expiredTokens","newState","maxAge","expiredStates","createCodeVerifier","randomBytes","createCodeChallenge","verifier","createHash","generateState","OAuth2Client","authUrl","authState","_b","_c","providerInstance","tokens","profile","error","savedToken","storedToken","expirationBuffer","expiresAt","s","seal","d","sealData","unseal","unsealData"],"mappings":"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","file":"index.cjs","sourcesContent":["import { OAuth2Config } from '../types';\nimport { AuthorizationUrlStrategy } from './authorization-url.strategy';\n\nexport class StandardAuthorizationUrlStrategy implements AuthorizationUrlStrategy {\n protected buildUrlParams(params: Record<string, string | undefined>): string {\n const filtered = Object.entries(params)\n .filter(([, value]) => value !== undefined)\n\n .map(([key, value]) => `${key}=${encodeURIComponent(value as string)}`);\n\n return filtered.join('&');\n }\n\n generateAuthorizationUrl(config: OAuth2Config, state: string, codeChallenge?: string): string {\n const params: Record<string, string | undefined> = {\n client_id: config.clientId,\n redirect_uri: config.redirectUri,\n response_type: 'code',\n scope: config.scopes.join(' '),\n state,\n };\n\n // Add PKCE parameters\n if ((config.usePKCE || config.pkce) && codeChallenge) {\n params.code_challenge = codeChallenge;\n params.code_challenge_method = 'S256';\n }\n\n // Merge additional parameters (for both additionalParams and extraAuthParams)\n const extraParams = {\n ...config.additionalParams,\n ...config.extraAuthParams,\n };\n\n Object.assign(params, extraParams);\n\n return `${config.authorizationUrl}?${this.buildUrlParams(params)}`;\n }\n}\n","import { OAuth2Config, OAuth2Token } from '../types';\nimport { TokenExchangeStrategy } from './token-exchange.strategy';\n\nexport class StandardTokenExchangeStrategy implements TokenExchangeStrategy {\n protected buildUrlParams(params: Record<string, string | undefined>): string {\n const filtered = Object.entries(params)\n .filter(([, value]) => value !== undefined)\n .map(([key, value]) => `${key}=${encodeURIComponent(value as string)}`);\n\n return filtered.join('&');\n }\n\n async exchangeCodeForToken(\n code: string,\n config: OAuth2Config,\n codeVerifier?: string,\n ): Promise<OAuth2Token> {\n const params: Record<string, string | undefined> = {\n grant_type: 'authorization_code',\n code,\n redirect_uri: config.redirectUri,\n client_id: config.clientId,\n };\n\n // Handle PKCE\n if ((config.usePKCE || config.pkce) && codeVerifier) {\n params.code_verifier = codeVerifier;\n } else if (config.clientSecret) {\n params.client_secret = config.clientSecret;\n }\n\n const response = await fetch(config.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: this.buildUrlParams(params),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token exchange failed: ${response.statusText} - ${errorText}`);\n }\n\n const data = await response.json();\n\n // Handle nested response (e.g., Outlook might nest tokens)\n const tokenData = config.responseRootKey ? data[config.responseRootKey] : data;\n\n const now = Date.now();\n const expiresIn = tokenData.expires_in || 3600;\n\n return {\n accessToken: tokenData.access_token,\n refreshToken: tokenData.refresh_token,\n expiresAt: new Date(now + expiresIn * 1000),\n expiresIn: expiresIn,\n tokenType: tokenData.token_type || 'Bearer',\n scope: tokenData.scope,\n createdAt: now,\n raw: data,\n };\n }\n\n async refreshToken(refreshToken: string, config: OAuth2Config): Promise<OAuth2Token> {\n const params: Record<string, string | undefined> = {\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: config.clientId,\n };\n\n // Only add client_secret if not using PKCE\n if (!(config.usePKCE || config.pkce) && config.clientSecret) {\n params.client_secret = config.clientSecret;\n }\n\n const response = await fetch(config.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: this.buildUrlParams(params),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token refresh failed: ${response.statusText} - ${errorText}`);\n }\n\n const data = await response.json();\n const tokenData = config.responseRootKey ? data[config.responseRootKey] : data;\n\n const now = Date.now();\n const expiresIn = tokenData.expires_in || 3600;\n\n return {\n accessToken: tokenData.access_token,\n refreshToken: tokenData.refresh_token || refreshToken,\n expiresAt: new Date(now + expiresIn * 1000),\n expiresIn: expiresIn,\n tokenType: tokenData.token_type || 'Bearer',\n scope: tokenData.scope,\n createdAt: now,\n raw: data,\n };\n }\n}\n","import { OAuth2Config, OAuth2Token } from '../types';\n\nimport { AuthorizationUrlStrategy } from '../strategies/authorization-url.strategy';\nimport { TokenExchangeStrategy } from '../strategies/token-exchange.strategy';\nimport { UserProfile } from './interfaces/profile-fetcher.interface';\nimport { BaseProfileFetcher } from '../profile/base-profile-fetcher';\n\nexport abstract class OAuth2Provider {\n protected authUrlStrategy: AuthorizationUrlStrategy;\n protected tokenStrategy: TokenExchangeStrategy;\n protected profileFetcher?: BaseProfileFetcher;\n\n constructor(\n protected config: OAuth2Config,\n authUrlStrategy?: AuthorizationUrlStrategy,\n tokenStrategy?: TokenExchangeStrategy,\n profileFetcher?: BaseProfileFetcher,\n ) {\n this.authUrlStrategy = authUrlStrategy || this.createAuthorizationUrlStrategy();\n this.tokenStrategy = tokenStrategy || this.createTokenExchangeStrategy();\n this.profileFetcher = profileFetcher;\n }\n\n // Factory methods\n protected abstract createAuthorizationUrlStrategy(): AuthorizationUrlStrategy;\n protected abstract createTokenExchangeStrategy(): TokenExchangeStrategy;\n\n // Profile fetching methods\n async fetchProfile(accessToken: string): Promise<UserProfile> {\n if (!this.profileFetcher) {\n throw new Error('Profile fetcher not configured for this provider');\n }\n return this.profileFetcher.fetchUserInfo(accessToken);\n }\n\n getProfileEndpoint(): string {\n if (!this.profileFetcher) {\n throw new Error('Profile fetcher not configured for this provider');\n }\n return this.profileFetcher.getEndpoint();\n }\n\n setProfileFetcher(profileFetcher: BaseProfileFetcher): void {\n this.profileFetcher = profileFetcher;\n }\n\n hasProfileFetcher(): boolean {\n return !!this.profileFetcher;\n }\n\n generateAuthorizationUrl(state: string, codeChallenge?: string): string {\n return this.authUrlStrategy.generateAuthorizationUrl(this.config, state, codeChallenge);\n }\n\n async exchangeCodeForToken(code: string, codeVerifier?: string): Promise<OAuth2Token> {\n return this.tokenStrategy.exchangeCodeForToken(code, this.config, codeVerifier);\n }\n\n async refreshToken(refreshToken: string): Promise<OAuth2Token> {\n return this.tokenStrategy.refreshToken(refreshToken, this.config);\n }\n}\n","import { AuthorizationUrlStrategy } from '../strategies/authorization-url.strategy';\nimport { StandardAuthorizationUrlStrategy } from '../strategies/standard-authorization-url.strategy';\nimport { StandardTokenExchangeStrategy } from '../strategies/standard-token-exchange.strategy';\nimport { TokenExchangeStrategy } from '../strategies/token-exchange.strategy';\nimport { OAuth2Provider } from './base.provider';\nimport { BaseProfileFetcher } from '../profile/base-profile-fetcher';\n\nexport class GenericOAuth2Provider extends OAuth2Provider {\n constructor(\n config: any,\n authUrlStrategy?: AuthorizationUrlStrategy,\n tokenStrategy?: TokenExchangeStrategy,\n profileFetcher?: BaseProfileFetcher,\n ) {\n super(config, authUrlStrategy, tokenStrategy, profileFetcher);\n }\n\n protected createAuthorizationUrlStrategy(): AuthorizationUrlStrategy {\n return new StandardAuthorizationUrlStrategy();\n }\n\n protected createTokenExchangeStrategy(): TokenExchangeStrategy {\n return new StandardTokenExchangeStrategy();\n }\n}\n","import { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport abstract class BaseProfileFetcher {\n constructor(protected profileEndpoint: string) {}\n\n /**\n * Fetch user profile information from the OAuth provider\n * @param accessToken The OAuth access token\n * @returns Promise resolving to standardized user profile\n */\n async fetchUserInfo(accessToken: string): Promise<UserProfile> {\n const response = await fetch(this.profileEndpoint, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n Accept: 'application/json',\n ...this.getAdditionalHeaders(),\n },\n });\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch profile from ${this.profileEndpoint}: ${response.statusText}`,\n );\n }\n\n const rawData = await response.json();\n return this.mapToUserProfile(rawData);\n }\n\n /**\n * Map the raw API response to our standardized UserProfile structure\n * Override this method to customize mapping for different providers\n */\n protected abstract mapToUserProfile(rawData: any): UserProfile;\n\n /**\n * Get additional headers if needed for the profile request\n * Override this method to add provider-specific headers\n */\n protected getAdditionalHeaders(): Record<string, string> {\n return {};\n }\n\n /**\n * Get the profile endpoint URL\n */\n getEndpoint(): string {\n return this.profileEndpoint;\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class GoogleProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://www.googleapis.com/oauth2/v2/userinfo');\n }\n\n mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.email,\n name: rawData.name,\n id: rawData.id,\n avatar: rawData.picture,\n username: rawData.email,\n raw: rawData,\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class GitHubProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://api.github.com/user');\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.email,\n name: rawData.name || rawData.login,\n id: rawData.id?.toString(),\n avatar: rawData.avatar_url,\n username: rawData.login,\n raw: rawData,\n };\n }\n\n protected getAdditionalHeaders(): Record<string, string> {\n return {\n 'User-Agent': 'OAuth2-Token-Manager', // GitHub requires User-Agent\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class MicrosoftProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://graph.microsoft.com/v1.0/me');\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.mail || rawData.userPrincipalName,\n name: rawData.displayName,\n id: rawData.id,\n avatar: undefined, // Microsoft Graph doesn't include avatar in basic profile\n username: rawData.userPrincipalName,\n raw: rawData,\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport interface ProfileMapping {\n email: string;\n name?: string;\n id?: string;\n avatar?: string;\n username?: string;\n}\n\nexport class GenericProfileFetcher extends BaseProfileFetcher {\n constructor(\n profileEndpoint: string,\n private mapping?: ProfileMapping,\n private additionalHeaders?: Record<string, string>,\n ) {\n super(profileEndpoint);\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n if (this.mapping) {\n return {\n email: this.getNestedProperty(rawData, this.mapping.email),\n name: this.mapping.name ? this.getNestedProperty(rawData, this.mapping.name) : undefined,\n id: this.mapping.id ? this.getNestedProperty(rawData, this.mapping.id) : undefined,\n avatar: this.mapping.avatar\n ? this.getNestedProperty(rawData, this.mapping.avatar)\n : undefined,\n username: this.mapping.username\n ? this.getNestedProperty(rawData, this.mapping.username)\n : undefined,\n raw: rawData,\n };\n }\n\n // Default generic mapping\n return {\n email: rawData.email || rawData.mail || rawData.emailAddress,\n name: rawData.name || rawData.displayName || rawData.full_name,\n id: rawData.id || rawData.sub || rawData.user_id,\n avatar: rawData.avatar || rawData.picture || rawData.avatar_url,\n username: rawData.username || rawData.login || rawData.preferred_username,\n raw: rawData,\n };\n }\n\n protected getAdditionalHeaders(): Record<string, string> {\n return this.additionalHeaders || {};\n }\n\n private getNestedProperty(obj: any, path: string): any {\n return path.split('.').reduce((current, key) => current?.[key], obj);\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { GoogleProfileFetcher } from './google-profile-fetcher';\nimport { GitHubProfileFetcher } from './github-profile-fetcher';\nimport { MicrosoftProfileFetcher } from './microsoft-profile-fetcher';\nimport { GenericProfileFetcher, ProfileMapping } from './generic-profile-fetcher';\nimport { ProviderType } from '../providers/provider.factory';\nimport { OAuth2Config } from '../types';\n\nexport interface ProfileFetcherOptions {\n profileUrl?: string;\n profileMapping?: ProfileMapping;\n profileHeaders?: Record<string, string>;\n}\n\nexport class ProfileFetcherFactory {\n static createProfileFetcher(\n providerType: ProviderType,\n config: OAuth2Config,\n options?: ProfileFetcherOptions,\n ): BaseProfileFetcher {\n // If custom options are provided, use GenericProfileFetcher\n if (options?.profileUrl) {\n return new GenericProfileFetcher(\n options.profileUrl,\n options.profileMapping,\n options.profileHeaders,\n );\n }\n\n // Use provider-specific fetchers for known providers\n switch (providerType) {\n case 'google':\n return new GoogleProfileFetcher();\n case 'github':\n return new GitHubProfileFetcher();\n case 'microsoft':\n case 'outlook':\n return new MicrosoftProfileFetcher();\n case 'facebook':\n return new GenericProfileFetcher(\n 'https://graph.facebook.com/me?fields=id,name,email,picture',\n );\n case 'generic':\n default:\n // For generic providers, use the profileUrl from config\n const profileUrl = config.profileUrl || config.userInfoUrl;\n if (!profileUrl) {\n throw new Error(`Profile URL must be provided for ${providerType} provider`);\n }\n return new GenericProfileFetcher(profileUrl);\n }\n }\n\n static registerCustomProfileFetcher(\n providerName: string,\n profileFetcher: BaseProfileFetcher,\n ): void {\n // Store custom profile fetchers for later use\n this.customFetchers.set(providerName, profileFetcher);\n }\n\n private static customFetchers = new Map<string, BaseProfileFetcher>();\n\n static getCustomProfileFetcher(providerName: string): BaseProfileFetcher | undefined {\n return this.customFetchers.get(providerName);\n }\n}\n","import { OAuth2Config } from '../types';\nimport { OAuth2Provider } from './base.provider';\nimport { GenericOAuth2Provider } from './generic.provider';\nimport { ProfileFetcherFactory } from '../profile/profile-fetcher-factory';\n\nexport type ProviderType = 'google' | 'github' | 'microsoft' | 'outlook' | 'facebook' | 'generic';\n\nexport interface ProviderFactory {\n createProvider(type: ProviderType, config: OAuth2Config): OAuth2Provider;\n}\n\nexport class OAuth2ProviderFactory implements ProviderFactory {\n private static presetConfigs: Record<string, Partial<OAuth2Config>> = {\n google: {\n authorizationUrl: 'https://accounts.google.com/o/oauth2/v2/auth',\n tokenUrl: 'https://oauth2.googleapis.com/token',\n profileUrl: 'https://www.googleapis.com/oauth2/v2/userinfo',\n usePKCE: true,\n extraAuthParams: {\n access_type: 'offline',\n prompt: 'consent',\n },\n },\n github: {\n authorizationUrl: 'https://github.com/login/oauth/authorize',\n tokenUrl: 'https://github.com/login/oauth/access_token',\n profileUrl: 'https://api.github.com/user',\n },\n microsoft: {\n authorizationUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',\n tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',\n profileUrl: 'https://graph.microsoft.com/v1.0/me',\n usePKCE: true,\n },\n outlook: {\n authorizationUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',\n tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',\n profileUrl: 'https://graph.microsoft.com/v1.0/me',\n usePKCE: true,\n extraAuthParams: {\n prompt: 'select_account',\n },\n },\n facebook: {\n authorizationUrl: 'https://www.facebook.com/v12.0/dialog/oauth',\n tokenUrl: 'https://graph.facebook.com/v12.0/oauth/access_token',\n profileUrl: 'https://graph.facebook.com/me?fields=id,name,email,picture',\n },\n };\n\n createProvider(type: ProviderType, config: OAuth2Config): OAuth2Provider {\n const presetConfig = type !== 'generic' ? OAuth2ProviderFactory.presetConfigs[type] || {} : {};\n\n // Only override preset values if the user explicitly provides them (not empty strings)\n const mergedConfig: OAuth2Config = {\n ...presetConfig,\n ...config,\n // Don't override preset URLs with empty strings\n authorizationUrl: config.authorizationUrl || presetConfig.authorizationUrl || '',\n tokenUrl: config.tokenUrl || presetConfig.tokenUrl || '',\n profileUrl: config.profileUrl || presetConfig.profileUrl,\n extraAuthParams: {\n ...(presetConfig.extraAuthParams || {}),\n ...(config.extraAuthParams || {}),\n },\n };\n\n const profileFetcher = ProfileFetcherFactory.createProfileFetcher(type, mergedConfig);\n\n return new GenericOAuth2Provider(mergedConfig, undefined, undefined, profileFetcher);\n }\n\n static registerPreset(name: string, config: Partial<OAuth2Config>): void {\n OAuth2ProviderFactory.presetConfigs[name] = config;\n }\n\n static getPresetConfig(name: string): Partial<OAuth2Config> | undefined {\n return OAuth2ProviderFactory.presetConfigs[name];\n }\n}\n","import { AuthorizationState } from '../types';\nimport { StorageAdapter, StoredToken, SaveTokenInput, UpdateTokenInput } from './interfaces';\n\nexport class InMemoryStorageAdapter implements StorageAdapter {\n private tokens: Map<string, StoredToken> = new Map();\n private states: Map<string, AuthorizationState> = new Map();\n\n private generateId(): string {\n return Math.random().toString(36).substring(2) + Date.now().toString(36);\n }\n\n // Token operations\n async saveToken(input: SaveTokenInput): Promise<StoredToken> {\n // Check if token with same provider + email exists\n const existingToken = await this.getToken(input.provider, input.email);\n\n if (existingToken) {\n // Replace existing token\n const updatedToken: StoredToken = {\n ...existingToken,\n ...input,\n id: existingToken.id,\n createdAt: existingToken.createdAt,\n updatedAt: new Date(),\n };\n this.tokens.set(existingToken.id, updatedToken);\n return updatedToken;\n }\n\n // Create new token\n const newToken: StoredToken = {\n ...input,\n id: this.generateId(),\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n this.tokens.set(newToken.id, newToken);\n return newToken;\n }\n\n async getToken(provider: string, email: string): Promise<StoredToken | null> {\n const tokens = Array.from(this.tokens.values());\n return tokens.find((t) => t.provider === provider && t.email === email) || null;\n }\n\n async getTokenById(id: string): Promise<StoredToken | null> {\n return this.tokens.get(id) || null;\n }\n\n async getTokensByUserId(userId: string): Promise<StoredToken[]> {\n return Array.from(this.tokens.values()).filter((t) => t.userId === userId);\n }\n\n async getTokensByEmail(email: string): Promise<StoredToken[]> {\n return Array.from(this.tokens.values()).filter((t) => t.email === email);\n }\n\n async getTokensByProvider(provider: string): Promise<StoredToken[]> {\n return Array.from(this.tokens.values()).filter((t) => t.provider === provider);\n }\n\n async updateToken(id: string, update: UpdateTokenInput): Promise<StoredToken | null> {\n const token = this.tokens.get(id);\n if (!token) return null;\n\n const updatedToken: StoredToken = {\n ...token,\n ...(update.token && { token: update.token }),\n ...(update.metadata && { metadata: { ...token.metadata, ...update.metadata } }),\n updatedAt: new Date(),\n };\n this.tokens.set(id, updatedToken);\n return updatedToken;\n }\n\n async deleteToken(id: string): Promise<boolean> {\n return this.tokens.delete(id);\n }\n\n async deleteTokenByProviderEmail(provider: string, email: string): Promise<boolean> {\n const token = await this.getToken(provider, email);\n if (!token) return false;\n return this.tokens.delete(token.id);\n }\n\n async deleteExpiredTokens(): Promise<number> {\n const now = new Date().getTime();\n const expiredTokens = Array.from(this.tokens.entries())\n .filter(([, token]) => {\n const expiresAt = new Date(token.token.expiresAt).getTime();\n return expiresAt < now;\n })\n .map(([id]) => id);\n\n expiredTokens.forEach((id) => this.tokens.delete(id));\n return expiredTokens.length;\n }\n\n // Authorization state operations\n async saveAuthorizationState(\n state: Omit<AuthorizationState, 'createdAt'>,\n ): Promise<AuthorizationState> {\n const newState: AuthorizationState = {\n ...state,\n createdAt: new Date(Date.now()),\n };\n this.states.set(state.state, newState);\n return newState;\n }\n\n async getAuthorizationState(state: string): Promise<AuthorizationState | null> {\n return this.states.get(state) || null;\n }\n\n async deleteAuthorizationState(state: string): Promise<boolean> {\n return this.states.delete(state);\n }\n\n async cleanupExpiredStates(): Promise<number> {\n const now = new Date().getTime();\n const maxAge = 10 * 60 * 1000; // 10 minutes\n\n const expiredStates = Array.from(this.states.entries())\n .filter(([, state]) => {\n const stateAge = now - state.createdAt.getTime();\n return stateAge > maxAge;\n })\n .map(([key]) => key);\n\n expiredStates.forEach((key) => this.states.delete(key));\n return expiredStates.length;\n }\n}\n","import { createHash, randomBytes } from 'crypto';\n\nexport const createCodeVerifier = () =>\n randomBytes(32)\n .toString('base64')\n .replace(/[^a-zA-Z0-9]/g, '')\n .substring(0, 128);\n\nexport const createCodeChallenge = (verifier: string): string => {\n return createHash('sha256').update(verifier).digest('base64url');\n};\n\nexport const generateState = (): string => {\n return randomBytes(16).toString('base64url');\n};\n","import { OAuth2Config, OAuth2Token, AuthorizationState } from '../types';\nimport { OAuth2ProviderFactory, ProviderType } from '../providers/provider.factory';\nimport { StorageAdapter, StoredToken } from '../storage/interfaces';\nimport { InMemoryStorageAdapter } from '../storage/memory.adapter';\nimport { ProviderFactory } from '../providers/provider.factory';\nimport { createCodeVerifier, createCodeChallenge, generateState } from '../utils/crypto';\nimport { OAuth2Provider } from '../providers/base.provider';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport interface OAuth2Options {\n storage?: StorageAdapter;\n providers?: Record<string, OAuth2Config>;\n}\n\nexport interface AuthorizationOptions {\n provider: string;\n userId: string;\n email: string;\n scopes?: string[];\n metadata?: Record<string, any>;\n usePKCE?: boolean;\n}\n\nexport interface TokenOptions {\n autoRefresh?: boolean;\n refreshBuffer?: number; // minutes before expiry to refresh\n expirationBuffer?: number; // seconds before expiry to consider expired\n defaultExpiresIn?: number; // default expiration in seconds\n}\n\nexport interface CallbackResult {\n token: StoredToken;\n profile?: UserProfile;\n}\n\nexport class OAuth2Client {\n private storage: StorageAdapter;\n private providerFactory: ProviderFactory;\n private providers: Map<string, OAuth2Provider> = new Map();\n private providerConfigs: Map<string, OAuth2Config> = new Map();\n private now: () => number;\n\n constructor(options: OAuth2Options = {}) {\n this.storage = options.storage || new InMemoryStorageAdapter();\n this.providerFactory = new OAuth2ProviderFactory();\n this.now = Date.now;\n\n // Register predefined providers\n if (options.providers) {\n Object.entries(options.providers).forEach(([name, config]) => {\n this.registerProvider(name, config);\n });\n }\n }\n\n /**\n * Register a provider configuration\n */\n registerProvider(name: string, config: OAuth2Config): void {\n this.providerConfigs.set(name, config);\n\n // Determine provider type based on configuration\n const providerType = this.detectProviderType(name, config);\n const provider = this.providerFactory.createProvider(providerType, config);\n this.providers.set(name, provider);\n }\n\n /**\n * Start OAuth2 authorization flow\n */\n async authorize(options: AuthorizationOptions): Promise<{ url: string; state: string }> {\n const provider = this.providers.get(options.provider);\n if (!provider) throw new Error(`Provider ${options.provider} not found`);\n\n const state = generateState();\n let authUrl: string;\n let authState: Omit<AuthorizationState, 'createdAt'>;\n\n const requiresPKCE = this.providerConfigs.get(options.provider)?.usePKCE || options.usePKCE;\n\n if (requiresPKCE) {\n const codeVerifier = createCodeVerifier();\n const codeChallenge = createCodeChallenge(codeVerifier);\n authUrl = provider.generateAuthorizationUrl(state, codeChallenge);\n authState = {\n state,\n codeVerifier,\n config: this.providerConfigs.get(options.provider)!,\n metadata: {\n ...options.metadata,\n userId: options.userId,\n email: options.email,\n provider: options.provider,\n },\n };\n } else {\n authUrl = provider.generateAuthorizationUrl(state);\n authState = {\n state,\n config: this.providerConfigs.get(options.provider)!,\n metadata: {\n ...options.metadata,\n userId: options.userId,\n email: options.email,\n provider: options.provider,\n },\n };\n }\n\n await this.storage.saveAuthorizationState(authState);\n return { url: authUrl, state };\n }\n\n /**\n * Handle OAuth2 callback\n */\n async handleCallback(code: string, state: string): Promise<CallbackResult> {\n const authState = await this.storage.getAuthorizationState(state);\n if (!authState) throw new Error('Invalid or expired state');\n\n const provider = authState.metadata?.provider;\n if (!provider) throw new Error('Provider not found in authorization state');\n\n const providerInstance = this.providers.get(provider);\n if (!providerInstance) throw new Error(`Provider ${provider} not found`);\n\n // Exchange code for tokens\n const tokens = await providerInstance.exchangeCodeForToken(code, authState.codeVerifier);\n\n // Extract user data from metadata\n const userId = authState.metadata?.userId;\n const email = authState.metadata?.email;\n\n if (!userId || !email) {\n throw new Error('User ID and email are required in authorization state');\n }\n\n // Fetch profile if available\n let profile: UserProfile | undefined;\n if (providerInstance.hasProfileFetcher()) {\n try {\n profile = await providerInstance.fetchProfile(tokens.accessToken);\n } catch (error) {\n console.warn('Failed to fetch user profile:', error);\n }\n }\n\n // Save token\n const savedToken = await this.storage.saveToken({\n provider,\n userId,\n email,\n token: tokens,\n metadata: {\n ...authState.metadata,\n profileFetched: !!profile,\n },\n });\n\n // Clean up authorization state\n await this.storage.deleteAuthorizationState(state);\n\n // Call onSuccess callback if defined\n const config = this.providerConfigs.get(provider);\n if (config?.onSuccess) {\n await config.onSuccess(userId, tokens);\n }\n\n return {\n token: savedToken,\n profile,\n };\n }\n\n /**\n * Get a valid access token (auto-refresh if needed)\n */\n async getAccessToken(\n provider: string,\n email: string,\n options: TokenOptions = {},\n ): Promise<string> {\n const token = await this.getValidToken(provider, email, options);\n return token.accessToken;\n }\n\n /**\n * Get a valid token (auto-refresh if needed)\n */\n async getValidToken(\n provider: string,\n email: string,\n options: TokenOptions = {},\n ): Promise<OAuth2Token> {\n const storedToken = await this.storage.getToken(provider, email);\n if (!storedToken) {\n throw new Error(`No token found for provider ${provider} and email ${email}`);\n }\n\n const needsRefresh =\n options.autoRefresh !== false && this.isTokenExpired(storedToken.token, options);\n\n if (!needsRefresh) {\n return storedToken.token;\n }\n\n // Refresh the token\n if (!storedToken.token.refreshToken) {\n throw new Error('Token expired and no refresh token available');\n }\n\n const providerInstance = this.providers.get(provider);\n if (!providerInstance) throw new Error(`Provider ${provider} not found`);\n\n const newToken = await providerInstance.refreshToken(storedToken.token.refreshToken);\n await this.storage.updateToken(storedToken.id, { token: newToken });\n\n return newToken;\n }\n\n /**\n * Get all tokens for a user\n */\n async getTokensByUserId(userId: string): Promise<StoredToken[]> {\n return this.storage.getTokensByUserId(userId);\n }\n\n /**\n * Get all tokens for an email\n */\n async getTokensByEmail(email: string): Promise<StoredToken[]> {\n return this.storage.getTokensByEmail(email);\n }\n\n /**\n * Delete a token\n */\n async deleteToken(provider: string, email: string): Promise<boolean> {\n return this.storage.deleteTokenByProviderEmail(provider, email);\n }\n\n /**\n * Delete all expired tokens\n */\n async cleanupExpiredTokens(): Promise<number> {\n return this.storage.deleteExpiredTokens();\n }\n\n /**\n * Clean up expired authorization states\n */\n async cleanupExpiredStates(): Promise<number> {\n return this.storage.cleanupExpiredStates();\n }\n\n // Helper methods\n private isTokenExpired(token: OAuth2Token, options: TokenOptions = {}): boolean {\n const { expirationBuffer = 300 } = options;\n\n if (token.createdAt && token.expiresIn !== undefined) {\n const expiresAt = token.createdAt + token.expiresIn * 1000;\n const effectiveNow = this.now() + expirationBuffer * 1000;\n return effectiveNow >= expiresAt;\n }\n\n const expiresAt = new Date(token.expiresAt).getTime();\n const effectiveNow = this.now() + expirationBuffer * 1000;\n return effectiveNow >= expiresAt;\n }\n\n private detectProviderType(name: string, config: OAuth2Config): ProviderType {\n // Try to detect based on the authorization URL\n const authUrl = config.authorizationUrl.toLowerCase();\n\n // Check for known providers that have specific implementations\n if (authUrl.includes('accounts.google.com')) return 'google';\n if (authUrl.includes('github.com')) return 'github';\n if (authUrl.includes('facebook.com')) return 'facebook';\n if (authUrl.includes('microsoft.com') || authUrl.includes('microsoftonline.com')) {\n // Check if it's specifically for Outlook\n if (\n name.toLowerCase().includes('outlook') ||\n config.scopes?.some((s) => s.includes('outlook'))\n ) {\n return 'outlook';\n }\n return 'microsoft';\n }\n\n // Default to generic provider for all others\n return 'generic';\n }\n}\n","import { sealData, unsealData } from 'iron-session';\n\nexport const seal = <T>(d: T, key: string) => sealData(d, { password: key });\nexport const unseal = <T>(s: string, key: string) => unsealData<T>(s, { password: key });\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/strategies/standard-authorization-url.strategy.ts","../src/strategies/standard-token-exchange.strategy.ts","../src/providers/base.provider.ts","../src/providers/generic.provider.ts","../src/profile/base-profile-fetcher.ts","../src/profile/google-profile-fetcher.ts","../src/profile/github-profile-fetcher.ts","../src/profile/microsoft-profile-fetcher.ts","../src/profile/generic-profile-fetcher.ts","../src/profile/profile-fetcher-factory.ts","../src/providers/provider.factory.ts","../src/storage/memory.adapter.ts","../src/utils/crypto.ts","../src/facade/oauth2.facade.ts","../src/utils/seal.ts"],"names":["StandardAuthorizationUrlStrategy","params","value","key","config","state","codeChallenge","extraParams","StandardTokenExchangeStrategy","code","codeVerifier","response","errorText","data","tokenData","now","expiresIn","refreshToken","OAuth2Provider","authUrlStrategy","tokenStrategy","profileFetcher","accessToken","GenericOAuth2Provider","BaseProfileFetcher","profileEndpoint","rawData","GoogleProfileFetcher","GitHubProfileFetcher","_a","MicrosoftProfileFetcher","GenericProfileFetcher","mapping","additionalHeaders","obj","path","current","ProfileFetcherFactory","providerType","options","profileUrl","providerName","OAuth2ProviderFactory","_OAuth2ProviderFactory","type","presetConfig","mergedConfig","name","InMemoryStorageAdapter","input","existingToken","updatedToken","newToken","provider","email","t","id","userId","token","update","expiredTokens","newState","maxAge","expiredStates","createCodeVerifier","randomBytes","createCodeChallenge","verifier","createHash","generateState","OAuth2Client","authUrl","authState","_b","_c","providerInstance","tokens","profile","error","savedToken","storedToken","expirationBuffer","expiresAt","s","seal","d","sealData","unseal","unsealData"],"mappings":"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","file":"index.cjs","sourcesContent":["import { OAuth2Config } from '../types';\nimport { AuthorizationUrlStrategy } from './authorization-url.strategy';\n\nexport class StandardAuthorizationUrlStrategy implements AuthorizationUrlStrategy {\n protected buildUrlParams(params: Record<string, string | undefined>): string {\n const filtered = Object.entries(params)\n .filter(([, value]) => value !== undefined)\n\n .map(([key, value]) => `${key}=${encodeURIComponent(value as string)}`);\n\n return filtered.join('&');\n }\n\n generateAuthorizationUrl(config: OAuth2Config, state: string, codeChallenge?: string): string {\n const params: Record<string, string | undefined> = {\n client_id: config.clientId,\n redirect_uri: config.redirectUri,\n response_type: 'code',\n scope: config.scopes.join(' '),\n state,\n };\n\n // Add PKCE parameters\n if ((config.usePKCE || config.pkce) && codeChallenge) {\n params.code_challenge = codeChallenge;\n params.code_challenge_method = 'S256';\n }\n\n // Merge additional parameters (for both additionalParams and extraAuthParams)\n const extraParams = {\n ...config.additionalParams,\n ...config.extraAuthParams,\n };\n\n Object.assign(params, extraParams);\n\n return `${config.authorizationUrl}?${this.buildUrlParams(params)}`;\n }\n}\n","import { OAuth2Config, OAuth2Token } from '../types';\nimport { TokenExchangeStrategy } from './token-exchange.strategy';\n\nexport class StandardTokenExchangeStrategy implements TokenExchangeStrategy {\n protected buildUrlParams(params: Record<string, string | undefined>): string {\n const filtered = Object.entries(params)\n .filter(([, value]) => value !== undefined)\n .map(([key, value]) => `${key}=${encodeURIComponent(value as string)}`);\n\n return filtered.join('&');\n }\n\n async exchangeCodeForToken(\n code: string,\n config: OAuth2Config,\n codeVerifier?: string,\n ): Promise<OAuth2Token> {\n const params: Record<string, string | undefined> = {\n grant_type: 'authorization_code',\n code,\n redirect_uri: config.redirectUri,\n client_id: config.clientId,\n };\n\n // Handle PKCE\n if ((config.usePKCE || config.pkce) && codeVerifier) {\n params.code_verifier = codeVerifier;\n } else if (config.clientSecret) {\n params.client_secret = config.clientSecret;\n }\n\n const response = await fetch(config.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: this.buildUrlParams(params),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token exchange failed: ${response.statusText} - ${errorText}`);\n }\n\n const data = await response.json();\n\n // Handle nested response (e.g., Outlook might nest tokens)\n const tokenData = config.responseRootKey ? data[config.responseRootKey] : data;\n\n const now = Date.now();\n const expiresIn = tokenData.expires_in || 3600;\n\n return {\n accessToken: tokenData.access_token,\n refreshToken: tokenData.refresh_token,\n expiresAt: new Date(now + expiresIn * 1000),\n expiresIn: expiresIn,\n tokenType: tokenData.token_type || 'Bearer',\n scope: tokenData.scope,\n createdAt: now,\n raw: data,\n };\n }\n\n async refreshToken(refreshToken: string, config: OAuth2Config): Promise<OAuth2Token> {\n const params: Record<string, string | undefined> = {\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: config.clientId,\n };\n\n // Only add client_secret if not using PKCE\n if (!(config.usePKCE || config.pkce) && config.clientSecret) {\n params.client_secret = config.clientSecret;\n }\n\n const response = await fetch(config.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: this.buildUrlParams(params),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token refresh failed: ${response.statusText} - ${errorText}`);\n }\n\n const data = await response.json();\n const tokenData = config.responseRootKey ? data[config.responseRootKey] : data;\n\n const now = Date.now();\n const expiresIn = tokenData.expires_in || 3600;\n\n return {\n accessToken: tokenData.access_token,\n refreshToken: tokenData.refresh_token || refreshToken,\n expiresAt: new Date(now + expiresIn * 1000),\n expiresIn: expiresIn,\n tokenType: tokenData.token_type || 'Bearer',\n scope: tokenData.scope,\n createdAt: now,\n raw: data,\n };\n }\n}\n","import { OAuth2Config, OAuth2Token } from '../types';\n\nimport { AuthorizationUrlStrategy } from '../strategies/authorization-url.strategy';\nimport { TokenExchangeStrategy } from '../strategies/token-exchange.strategy';\nimport { UserProfile } from './interfaces/profile-fetcher.interface';\nimport { BaseProfileFetcher } from '../profile/base-profile-fetcher';\n\nexport abstract class OAuth2Provider {\n protected authUrlStrategy: AuthorizationUrlStrategy;\n protected tokenStrategy: TokenExchangeStrategy;\n protected profileFetcher?: BaseProfileFetcher;\n\n constructor(\n protected config: OAuth2Config,\n authUrlStrategy?: AuthorizationUrlStrategy,\n tokenStrategy?: TokenExchangeStrategy,\n profileFetcher?: BaseProfileFetcher,\n ) {\n this.authUrlStrategy = authUrlStrategy || this.createAuthorizationUrlStrategy();\n this.tokenStrategy = tokenStrategy || this.createTokenExchangeStrategy();\n this.profileFetcher = profileFetcher;\n }\n\n // Factory methods\n protected abstract createAuthorizationUrlStrategy(): AuthorizationUrlStrategy;\n protected abstract createTokenExchangeStrategy(): TokenExchangeStrategy;\n\n // Profile fetching methods\n async fetchProfile(accessToken: string): Promise<UserProfile> {\n if (!this.profileFetcher) {\n throw new Error('Profile fetcher not configured for this provider');\n }\n return this.profileFetcher.fetchUserInfo(accessToken);\n }\n\n getProfileEndpoint(): string {\n if (!this.profileFetcher) {\n throw new Error('Profile fetcher not configured for this provider');\n }\n return this.profileFetcher.getEndpoint();\n }\n\n setProfileFetcher(profileFetcher: BaseProfileFetcher): void {\n this.profileFetcher = profileFetcher;\n }\n\n hasProfileFetcher(): boolean {\n return !!this.profileFetcher;\n }\n\n generateAuthorizationUrl(state: string, codeChallenge?: string): string {\n return this.authUrlStrategy.generateAuthorizationUrl(this.config, state, codeChallenge);\n }\n\n async exchangeCodeForToken(code: string, codeVerifier?: string): Promise<OAuth2Token> {\n return this.tokenStrategy.exchangeCodeForToken(code, this.config, codeVerifier);\n }\n\n async refreshToken(refreshToken: string): Promise<OAuth2Token> {\n return this.tokenStrategy.refreshToken(refreshToken, this.config);\n }\n}\n","import { AuthorizationUrlStrategy } from '../strategies/authorization-url.strategy';\nimport { StandardAuthorizationUrlStrategy } from '../strategies/standard-authorization-url.strategy';\nimport { StandardTokenExchangeStrategy } from '../strategies/standard-token-exchange.strategy';\nimport { TokenExchangeStrategy } from '../strategies/token-exchange.strategy';\nimport { OAuth2Provider } from './base.provider';\nimport { BaseProfileFetcher } from '../profile/base-profile-fetcher';\n\nexport class GenericOAuth2Provider extends OAuth2Provider {\n constructor(\n config: any,\n authUrlStrategy?: AuthorizationUrlStrategy,\n tokenStrategy?: TokenExchangeStrategy,\n profileFetcher?: BaseProfileFetcher,\n ) {\n super(config, authUrlStrategy, tokenStrategy, profileFetcher);\n }\n\n protected createAuthorizationUrlStrategy(): AuthorizationUrlStrategy {\n return new StandardAuthorizationUrlStrategy();\n }\n\n protected createTokenExchangeStrategy(): TokenExchangeStrategy {\n return new StandardTokenExchangeStrategy();\n }\n}\n","import { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport abstract class BaseProfileFetcher {\n constructor(protected profileEndpoint: string) {}\n\n /**\n * Fetch user profile information from the OAuth provider\n * @param accessToken The OAuth access token\n * @returns Promise resolving to standardized user profile\n */\n async fetchUserInfo(accessToken: string): Promise<UserProfile> {\n const response = await fetch(this.profileEndpoint, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n Accept: 'application/json',\n ...this.getAdditionalHeaders(),\n },\n });\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch profile from ${this.profileEndpoint}: ${response.statusText}`,\n );\n }\n\n const rawData = await response.json();\n return this.mapToUserProfile(rawData);\n }\n\n /**\n * Map the raw API response to our standardized UserProfile structure\n * Override this method to customize mapping for different providers\n */\n protected abstract mapToUserProfile(rawData: any): UserProfile;\n\n /**\n * Get additional headers if needed for the profile request\n * Override this method to add provider-specific headers\n */\n protected getAdditionalHeaders(): Record<string, string> {\n return {};\n }\n\n /**\n * Get the profile endpoint URL\n */\n getEndpoint(): string {\n return this.profileEndpoint;\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class GoogleProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://www.googleapis.com/oauth2/v2/userinfo');\n }\n\n mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.email,\n name: rawData.name,\n id: rawData.id,\n avatar: rawData.picture,\n username: rawData.email,\n raw: rawData,\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class GitHubProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://api.github.com/user');\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.email,\n name: rawData.name || rawData.login,\n id: rawData.id?.toString(),\n avatar: rawData.avatar_url,\n username: rawData.login,\n raw: rawData,\n };\n }\n\n protected getAdditionalHeaders(): Record<string, string> {\n return {\n 'User-Agent': 'OAuth2-Token-Manager', // GitHub requires User-Agent\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class MicrosoftProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://graph.microsoft.com/v1.0/me');\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.mail || rawData.userPrincipalName,\n name: rawData.displayName,\n id: rawData.id,\n avatar: undefined, // Microsoft Graph doesn't include avatar in basic profile\n username: rawData.userPrincipalName,\n raw: rawData,\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport interface ProfileMapping {\n email: string;\n name?: string;\n id?: string;\n avatar?: string;\n username?: string;\n}\n\nexport class GenericProfileFetcher extends BaseProfileFetcher {\n constructor(\n profileEndpoint: string,\n private mapping?: ProfileMapping,\n private additionalHeaders?: Record<string, string>,\n ) {\n super(profileEndpoint);\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n if (this.mapping) {\n return {\n email: this.getNestedProperty(rawData, this.mapping.email),\n name: this.mapping.name ? this.getNestedProperty(rawData, this.mapping.name) : undefined,\n id: this.mapping.id ? this.getNestedProperty(rawData, this.mapping.id) : undefined,\n avatar: this.mapping.avatar\n ? this.getNestedProperty(rawData, this.mapping.avatar)\n : undefined,\n username: this.mapping.username\n ? this.getNestedProperty(rawData, this.mapping.username)\n : undefined,\n raw: rawData,\n };\n }\n\n // Default generic mapping\n return {\n email: rawData.email || rawData.mail || rawData.emailAddress,\n name: rawData.name || rawData.displayName || rawData.full_name,\n id: rawData.id || rawData.sub || rawData.user_id,\n avatar: rawData.avatar || rawData.picture || rawData.avatar_url,\n username: rawData.username || rawData.login || rawData.preferred_username,\n raw: rawData,\n };\n }\n\n protected getAdditionalHeaders(): Record<string, string> {\n return this.additionalHeaders || {};\n }\n\n private getNestedProperty(obj: any, path: string): any {\n return path.split('.').reduce((current, key) => current?.[key], obj);\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { GoogleProfileFetcher } from './google-profile-fetcher';\nimport { GitHubProfileFetcher } from './github-profile-fetcher';\nimport { MicrosoftProfileFetcher } from './microsoft-profile-fetcher';\nimport { GenericProfileFetcher, ProfileMapping } from './generic-profile-fetcher';\nimport { ProviderType } from '../providers/provider.factory';\nimport { OAuth2Config } from '../types';\n\nexport interface ProfileFetcherOptions {\n profileUrl?: string;\n profileMapping?: ProfileMapping;\n profileHeaders?: Record<string, string>;\n}\n\nexport class ProfileFetcherFactory {\n static createProfileFetcher(\n providerType: ProviderType,\n config: OAuth2Config,\n options?: ProfileFetcherOptions,\n ): BaseProfileFetcher {\n // If custom options are provided, use GenericProfileFetcher\n if (options?.profileUrl) {\n return new GenericProfileFetcher(\n options.profileUrl,\n options.profileMapping,\n options.profileHeaders,\n );\n }\n\n // Use provider-specific fetchers for known providers\n switch (providerType) {\n case 'google':\n return new GoogleProfileFetcher();\n case 'github':\n return new GitHubProfileFetcher();\n case 'microsoft':\n case 'outlook':\n return new MicrosoftProfileFetcher();\n case 'facebook':\n return new GenericProfileFetcher(\n 'https://graph.facebook.com/me?fields=id,name,email,picture',\n );\n case 'generic':\n default:\n // For generic providers, use the profileUrl from config\n const profileUrl = config.profileUrl || config.userInfoUrl;\n if (!profileUrl) {\n throw new Error(`Profile URL must be provided for ${providerType} provider`);\n }\n return new GenericProfileFetcher(profileUrl);\n }\n }\n\n static registerCustomProfileFetcher(\n providerName: string,\n profileFetcher: BaseProfileFetcher,\n ): void {\n // Store custom profile fetchers for later use\n this.customFetchers.set(providerName, profileFetcher);\n }\n\n private static customFetchers = new Map<string, BaseProfileFetcher>();\n\n static getCustomProfileFetcher(providerName: string): BaseProfileFetcher | undefined {\n return this.customFetchers.get(providerName);\n }\n}\n","import { OAuth2Config } from '../types';\nimport { OAuth2Provider } from './base.provider';\nimport { GenericOAuth2Provider } from './generic.provider';\nimport { ProfileFetcherFactory } from '../profile/profile-fetcher-factory';\n\nexport type ProviderType = 'google' | 'github' | 'microsoft' | 'outlook' | 'facebook' | 'generic';\n\nexport interface ProviderFactory {\n createProvider(type: ProviderType, config: OAuth2Config): OAuth2Provider;\n}\n\nexport class OAuth2ProviderFactory implements ProviderFactory {\n private static presetConfigs: Record<string, Partial<OAuth2Config>> = {\n google: {\n authorizationUrl: 'https://accounts.google.com/o/oauth2/v2/auth',\n tokenUrl: 'https://oauth2.googleapis.com/token',\n profileUrl: 'https://www.googleapis.com/oauth2/v2/userinfo',\n usePKCE: true,\n extraAuthParams: {\n access_type: 'offline',\n prompt: 'consent',\n },\n },\n github: {\n authorizationUrl: 'https://github.com/login/oauth/authorize',\n tokenUrl: 'https://github.com/login/oauth/access_token',\n profileUrl: 'https://api.github.com/user',\n },\n microsoft: {\n authorizationUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',\n tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',\n profileUrl: 'https://graph.microsoft.com/v1.0/me',\n usePKCE: true,\n },\n outlook: {\n authorizationUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',\n tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',\n profileUrl: 'https://graph.microsoft.com/v1.0/me',\n usePKCE: true,\n extraAuthParams: {\n prompt: 'select_account',\n },\n },\n facebook: {\n authorizationUrl: 'https://www.facebook.com/v12.0/dialog/oauth',\n tokenUrl: 'https://graph.facebook.com/v12.0/oauth/access_token',\n profileUrl: 'https://graph.facebook.com/me?fields=id,name,email,picture',\n },\n };\n\n createProvider(type: ProviderType, config: OAuth2Config): OAuth2Provider {\n const presetConfig = type !== 'generic' ? OAuth2ProviderFactory.presetConfigs[type] || {} : {};\n\n // Only override preset values if the user explicitly provides them (not empty strings)\n const mergedConfig: OAuth2Config = {\n ...presetConfig,\n ...config,\n // Don't override preset URLs with empty strings\n authorizationUrl: config.authorizationUrl || presetConfig.authorizationUrl || '',\n tokenUrl: config.tokenUrl || presetConfig.tokenUrl || '',\n profileUrl: config.profileUrl || presetConfig.profileUrl,\n extraAuthParams: {\n ...(presetConfig.extraAuthParams || {}),\n ...(config.extraAuthParams || {}),\n },\n };\n\n const profileFetcher = ProfileFetcherFactory.createProfileFetcher(type, mergedConfig);\n\n return new GenericOAuth2Provider(mergedConfig, undefined, undefined, profileFetcher);\n }\n\n static registerPreset(name: string, config: Partial<OAuth2Config>): void {\n OAuth2ProviderFactory.presetConfigs[name] = config;\n }\n\n static getPresetConfig(name: string): Partial<OAuth2Config> | undefined {\n return OAuth2ProviderFactory.presetConfigs[name];\n }\n}\n","import { AuthorizationState } from '../types';\nimport { StorageAdapter, StoredToken, SaveTokenInput, UpdateTokenInput } from './interfaces';\n\nexport class InMemoryStorageAdapter implements StorageAdapter {\n private tokens: Map<string, StoredToken> = new Map();\n private states: Map<string, AuthorizationState> = new Map();\n\n private generateId(): string {\n return Math.random().toString(36).substring(2) + Date.now().toString(36);\n }\n\n // Token operations\n async saveToken(input: SaveTokenInput): Promise<StoredToken> {\n // Check if token with same provider + email exists\n const existingToken = await this.getToken(input.provider, input.email);\n\n if (existingToken) {\n // Replace existing token\n const updatedToken: StoredToken = {\n ...existingToken,\n ...input,\n id: existingToken.id,\n createdAt: existingToken.createdAt,\n updatedAt: new Date(),\n };\n this.tokens.set(existingToken.id, updatedToken);\n return updatedToken;\n }\n\n // Create new token\n const newToken: StoredToken = {\n ...input,\n id: this.generateId(),\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n this.tokens.set(newToken.id, newToken);\n return newToken;\n }\n\n async getToken(provider: string, email: string): Promise<StoredToken | null> {\n const tokens = Array.from(this.tokens.values());\n return tokens.find((t) => t.provider === provider && t.email === email) || null;\n }\n\n async getTokenById(id: string): Promise<StoredToken | null> {\n return this.tokens.get(id) || null;\n }\n\n async getTokensByUserId(userId: string): Promise<StoredToken[]> {\n return Array.from(this.tokens.values()).filter((t) => t.userId === userId);\n }\n\n async getTokensByEmail(email: string): Promise<StoredToken[]> {\n return Array.from(this.tokens.values()).filter((t) => t.email === email);\n }\n\n async getTokensByProvider(provider: string): Promise<StoredToken[]> {\n return Array.from(this.tokens.values()).filter((t) => t.provider === provider);\n }\n\n async getAccounts(userId: string, provider: string): Promise<StoredToken[]> {\n return Array.from(this.tokens.values()).filter(\n (t) => t.userId === userId && t.provider === provider,\n );\n }\n\n async getTokensForEmail(\n userId: string,\n provider: string,\n email: string,\n ): Promise<StoredToken | null> {\n // Since provider + email is unique, we can use getToken directly\n const token = await this.getToken(provider, email);\n // Verify it belongs to the requested userId\n if (token && token.userId === userId) {\n return token;\n }\n return null;\n }\n\n async getTokens(userId: string, provider: string): Promise<StoredToken[]> {\n return Array.from(this.tokens.values()).filter(\n (t) => t.userId === userId && t.provider === provider,\n );\n }\n\n async updateToken(id: string, update: UpdateTokenInput): Promise<StoredToken | null> {\n const token = this.tokens.get(id);\n if (!token) return null;\n\n const updatedToken: StoredToken = {\n ...token,\n ...(update.token && { token: update.token }),\n ...(update.metadata && { metadata: { ...token.metadata, ...update.metadata } }),\n updatedAt: new Date(),\n };\n this.tokens.set(id, updatedToken);\n return updatedToken;\n }\n\n async deleteToken(id: string): Promise<boolean> {\n return this.tokens.delete(id);\n }\n\n async deleteTokenByProviderEmail(provider: string, email: string): Promise<boolean> {\n const token = await this.getToken(provider, email);\n if (!token) return false;\n return this.tokens.delete(token.id);\n }\n\n async deleteExpiredTokens(): Promise<number> {\n const now = new Date().getTime();\n const expiredTokens = Array.from(this.tokens.entries())\n .filter(([, token]) => {\n const expiresAt = new Date(token.token.expiresAt).getTime();\n return expiresAt < now;\n })\n .map(([id]) => id);\n\n expiredTokens.forEach((id) => this.tokens.delete(id));\n return expiredTokens.length;\n }\n\n // Authorization state operations\n async saveAuthorizationState(\n state: Omit<AuthorizationState, 'createdAt'>,\n ): Promise<AuthorizationState> {\n const newState: AuthorizationState = {\n ...state,\n createdAt: new Date(Date.now()),\n };\n this.states.set(state.state, newState);\n return newState;\n }\n\n async getAuthorizationState(state: string): Promise<AuthorizationState | null> {\n return this.states.get(state) || null;\n }\n\n async deleteAuthorizationState(state: string): Promise<boolean> {\n return this.states.delete(state);\n }\n\n async cleanupExpiredStates(): Promise<number> {\n const now = new Date().getTime();\n const maxAge = 10 * 60 * 1000; // 10 minutes\n\n const expiredStates = Array.from(this.states.entries())\n .filter(([, state]) => {\n const stateAge = now - state.createdAt.getTime();\n return stateAge > maxAge;\n })\n .map(([key]) => key);\n\n expiredStates.forEach((key) => this.states.delete(key));\n return expiredStates.length;\n }\n}\n","import { createHash, randomBytes } from 'crypto';\n\nexport const createCodeVerifier = () =>\n randomBytes(32)\n .toString('base64')\n .replace(/[^a-zA-Z0-9]/g, '')\n .substring(0, 128);\n\nexport const createCodeChallenge = (verifier: string): string => {\n return createHash('sha256').update(verifier).digest('base64url');\n};\n\nexport const generateState = (): string => {\n return randomBytes(16).toString('base64url');\n};\n","import { OAuth2Config, OAuth2Token, AuthorizationState } from '../types';\nimport { OAuth2ProviderFactory, ProviderType } from '../providers/provider.factory';\nimport { StorageAdapter, StoredToken } from '../storage/interfaces';\nimport { InMemoryStorageAdapter } from '../storage/memory.adapter';\nimport { ProviderFactory } from '../providers/provider.factory';\nimport { createCodeVerifier, createCodeChallenge, generateState } from '../utils/crypto';\nimport { OAuth2Provider } from '../providers/base.provider';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport interface OAuth2Options {\n storage?: StorageAdapter;\n providers?: Record<string, OAuth2Config>;\n}\n\nexport interface AuthorizationOptions {\n provider: string;\n userId: string;\n email: string;\n scopes?: string[];\n metadata?: Record<string, any>;\n usePKCE?: boolean;\n}\n\nexport interface TokenOptions {\n autoRefresh?: boolean;\n refreshBuffer?: number; // minutes before expiry to refresh\n expirationBuffer?: number; // seconds before expiry to consider expired\n defaultExpiresIn?: number; // default expiration in seconds\n}\n\nexport interface CallbackResult {\n token: StoredToken;\n profile?: UserProfile;\n}\n\nexport class OAuth2Client {\n private storage: StorageAdapter;\n private providerFactory: ProviderFactory;\n private providers: Map<string, OAuth2Provider> = new Map();\n private providerConfigs: Map<string, OAuth2Config> = new Map();\n private now: () => number;\n\n constructor(options: OAuth2Options = {}) {\n this.storage = options.storage || new InMemoryStorageAdapter();\n this.providerFactory = new OAuth2ProviderFactory();\n this.now = Date.now;\n\n // Register predefined providers\n if (options.providers) {\n Object.entries(options.providers).forEach(([name, config]) => {\n this.registerProvider(name, config);\n });\n }\n }\n\n /**\n * Register a provider configuration\n */\n registerProvider(name: string, config: OAuth2Config): void {\n this.providerConfigs.set(name, config);\n\n // Determine provider type based on configuration\n const providerType = this.detectProviderType(name, config);\n const provider = this.providerFactory.createProvider(providerType, config);\n this.providers.set(name, provider);\n }\n\n /**\n * Start OAuth2 authorization flow\n */\n async authorize(options: AuthorizationOptions): Promise<{ url: string; state: string }> {\n const provider = this.providers.get(options.provider);\n if (!provider) throw new Error(`Provider ${options.provider} not found`);\n\n const state = generateState();\n let authUrl: string;\n let authState: Omit<AuthorizationState, 'createdAt'>;\n\n const requiresPKCE = this.providerConfigs.get(options.provider)?.usePKCE || options.usePKCE;\n\n if (requiresPKCE) {\n const codeVerifier = createCodeVerifier();\n const codeChallenge = createCodeChallenge(codeVerifier);\n authUrl = provider.generateAuthorizationUrl(state, codeChallenge);\n authState = {\n state,\n codeVerifier,\n config: this.providerConfigs.get(options.provider)!,\n metadata: {\n ...options.metadata,\n userId: options.userId,\n email: options.email,\n provider: options.provider,\n },\n };\n } else {\n authUrl = provider.generateAuthorizationUrl(state);\n authState = {\n state,\n config: this.providerConfigs.get(options.provider)!,\n metadata: {\n ...options.metadata,\n userId: options.userId,\n email: options.email,\n provider: options.provider,\n },\n };\n }\n\n await this.storage.saveAuthorizationState(authState);\n return { url: authUrl, state };\n }\n\n /**\n * Handle OAuth2 callback\n */\n async handleCallback(code: string, state: string): Promise<CallbackResult> {\n const authState = await this.storage.getAuthorizationState(state);\n if (!authState) throw new Error('Invalid or expired state');\n\n const provider = authState.metadata?.provider;\n if (!provider) throw new Error('Provider not found in authorization state');\n\n const providerInstance = this.providers.get(provider);\n if (!providerInstance) throw new Error(`Provider ${provider} not found`);\n\n // Exchange code for tokens\n const tokens = await providerInstance.exchangeCodeForToken(code, authState.codeVerifier);\n\n // Extract user data from metadata\n const userId = authState.metadata?.userId;\n const email = authState.metadata?.email;\n\n if (!userId || !email) {\n throw new Error('User ID and email are required in authorization state');\n }\n\n // Fetch profile if available\n let profile: UserProfile | undefined;\n if (providerInstance.hasProfileFetcher()) {\n try {\n profile = await providerInstance.fetchProfile(tokens.accessToken);\n } catch (error) {\n console.warn('Failed to fetch user profile:', error);\n }\n }\n\n // Save token\n const savedToken = await this.storage.saveToken({\n provider,\n userId,\n email,\n token: tokens,\n metadata: {\n ...authState.metadata,\n profileFetched: !!profile,\n },\n });\n\n // Clean up authorization state\n await this.storage.deleteAuthorizationState(state);\n\n // Call onSuccess callback if defined\n const config = this.providerConfigs.get(provider);\n if (config?.onSuccess) {\n await config.onSuccess(userId, tokens);\n }\n\n return {\n token: savedToken,\n profile,\n };\n }\n\n /**\n * Get a valid access token (auto-refresh if needed)\n */\n async getAccessToken(\n provider: string,\n email: string,\n options: TokenOptions = {},\n ): Promise<string> {\n const token = await this.getValidToken(provider, email, options);\n return token.accessToken;\n }\n\n /**\n * Get a valid token (auto-refresh if needed)\n */\n async getValidToken(\n provider: string,\n email: string,\n options: TokenOptions = {},\n ): Promise<OAuth2Token> {\n const storedToken = await this.storage.getToken(provider, email);\n if (!storedToken) {\n throw new Error(`No token found for provider ${provider} and email ${email}`);\n }\n\n const needsRefresh =\n options.autoRefresh !== false && this.isTokenExpired(storedToken.token, options);\n\n if (!needsRefresh) {\n return storedToken.token;\n }\n\n // Refresh the token\n if (!storedToken.token.refreshToken) {\n throw new Error('Token expired and no refresh token available');\n }\n\n const providerInstance = this.providers.get(provider);\n if (!providerInstance) throw new Error(`Provider ${provider} not found`);\n\n const newToken = await providerInstance.refreshToken(storedToken.token.refreshToken);\n await this.storage.updateToken(storedToken.id, { token: newToken });\n\n return newToken;\n }\n\n /**\n * Get all tokens for a user\n */\n async getTokensByUserId(userId: string): Promise<StoredToken[]> {\n return this.storage.getTokensByUserId(userId);\n }\n\n /**\n * Get all tokens for an email\n */\n async getTokensByEmail(email: string): Promise<StoredToken[]> {\n return this.storage.getTokensByEmail(email);\n }\n\n /**\n * Delete a token\n */\n async deleteToken(provider: string, email: string): Promise<boolean> {\n return this.storage.deleteTokenByProviderEmail(provider, email);\n }\n\n /**\n * Delete all expired tokens\n */\n async cleanupExpiredTokens(): Promise<number> {\n return this.storage.deleteExpiredTokens();\n }\n\n /**\n * Clean up expired authorization states\n */\n async cleanupExpiredStates(): Promise<number> {\n return this.storage.cleanupExpiredStates();\n }\n\n // Helper methods\n private isTokenExpired(token: OAuth2Token, options: TokenOptions = {}): boolean {\n const { expirationBuffer = 300 } = options;\n\n if (token.createdAt && token.expiresIn !== undefined) {\n const expiresAt = token.createdAt + token.expiresIn * 1000;\n const effectiveNow = this.now() + expirationBuffer * 1000;\n return effectiveNow >= expiresAt;\n }\n\n const expiresAt = new Date(token.expiresAt).getTime();\n const effectiveNow = this.now() + expirationBuffer * 1000;\n return effectiveNow >= expiresAt;\n }\n\n private detectProviderType(name: string, config: OAuth2Config): ProviderType {\n // Try to detect based on the authorization URL\n const authUrl = config.authorizationUrl.toLowerCase();\n\n // Check for known providers that have specific implementations\n if (authUrl.includes('accounts.google.com')) return 'google';\n if (authUrl.includes('github.com')) return 'github';\n if (authUrl.includes('facebook.com')) return 'facebook';\n if (authUrl.includes('microsoft.com') || authUrl.includes('microsoftonline.com')) {\n // Check if it's specifically for Outlook\n if (\n name.toLowerCase().includes('outlook') ||\n config.scopes?.some((s) => s.includes('outlook'))\n ) {\n return 'outlook';\n }\n return 'microsoft';\n }\n\n // Default to generic provider for all others\n return 'generic';\n }\n}\n","import { sealData, unsealData } from 'iron-session';\n\nexport const seal = <T>(d: T, key: string) => sealData(d, { password: key });\nexport const unseal = <T>(s: string, key: string) => unsealData<T>(s, { password: key });\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -44,6 +44,9 @@ interface StorageAdapter {
|
|
|
44
44
|
getTokensByUserId(userId: string): Promise<StoredToken[]>;
|
|
45
45
|
getTokensByEmail(email: string): Promise<StoredToken[]>;
|
|
46
46
|
getTokensByProvider(provider: string): Promise<StoredToken[]>;
|
|
47
|
+
getAccounts(userId: string, provider: string): Promise<StoredToken[]>;
|
|
48
|
+
getTokensForEmail(userId: string, provider: string, email: string): Promise<StoredToken | null>;
|
|
49
|
+
getTokens(userId: string, provider: string): Promise<StoredToken[]>;
|
|
47
50
|
updateToken(id: string, update: UpdateTokenInput): Promise<StoredToken | null>;
|
|
48
51
|
deleteToken(id: string): Promise<boolean>;
|
|
49
52
|
deleteTokenByProviderEmail(provider: string, email: string): Promise<boolean>;
|
|
@@ -188,6 +191,9 @@ declare class InMemoryStorageAdapter implements StorageAdapter {
|
|
|
188
191
|
getTokensByUserId(userId: string): Promise<StoredToken[]>;
|
|
189
192
|
getTokensByEmail(email: string): Promise<StoredToken[]>;
|
|
190
193
|
getTokensByProvider(provider: string): Promise<StoredToken[]>;
|
|
194
|
+
getAccounts(userId: string, provider: string): Promise<StoredToken[]>;
|
|
195
|
+
getTokensForEmail(userId: string, provider: string, email: string): Promise<StoredToken | null>;
|
|
196
|
+
getTokens(userId: string, provider: string): Promise<StoredToken[]>;
|
|
191
197
|
updateToken(id: string, update: UpdateTokenInput): Promise<StoredToken | null>;
|
|
192
198
|
deleteToken(id: string): Promise<boolean>;
|
|
193
199
|
deleteTokenByProviderEmail(provider: string, email: string): Promise<boolean>;
|
package/dist/index.d.ts
CHANGED
|
@@ -44,6 +44,9 @@ interface StorageAdapter {
|
|
|
44
44
|
getTokensByUserId(userId: string): Promise<StoredToken[]>;
|
|
45
45
|
getTokensByEmail(email: string): Promise<StoredToken[]>;
|
|
46
46
|
getTokensByProvider(provider: string): Promise<StoredToken[]>;
|
|
47
|
+
getAccounts(userId: string, provider: string): Promise<StoredToken[]>;
|
|
48
|
+
getTokensForEmail(userId: string, provider: string, email: string): Promise<StoredToken | null>;
|
|
49
|
+
getTokens(userId: string, provider: string): Promise<StoredToken[]>;
|
|
47
50
|
updateToken(id: string, update: UpdateTokenInput): Promise<StoredToken | null>;
|
|
48
51
|
deleteToken(id: string): Promise<boolean>;
|
|
49
52
|
deleteTokenByProviderEmail(provider: string, email: string): Promise<boolean>;
|
|
@@ -188,6 +191,9 @@ declare class InMemoryStorageAdapter implements StorageAdapter {
|
|
|
188
191
|
getTokensByUserId(userId: string): Promise<StoredToken[]>;
|
|
189
192
|
getTokensByEmail(email: string): Promise<StoredToken[]>;
|
|
190
193
|
getTokensByProvider(provider: string): Promise<StoredToken[]>;
|
|
194
|
+
getAccounts(userId: string, provider: string): Promise<StoredToken[]>;
|
|
195
|
+
getTokensForEmail(userId: string, provider: string, email: string): Promise<StoredToken | null>;
|
|
196
|
+
getTokens(userId: string, provider: string): Promise<StoredToken[]>;
|
|
191
197
|
updateToken(id: string, update: UpdateTokenInput): Promise<StoredToken | null>;
|
|
192
198
|
deleteToken(id: string): Promise<boolean>;
|
|
193
199
|
deleteTokenByProviderEmail(provider: string, email: string): Promise<boolean>;
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
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,
|
|
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 getAccounts(e,t){return Array.from(this.tokens.values()).filter(r=>r.userId===e&&r.provider===t)}async getTokensForEmail(e,t,r){let o=await this.getToken(t,r);return o&&o.userId===e?o:null}async getTokens(e,t){return Array.from(this.tokens.values()).filter(r=>r.userId===e&&r.provider===t)}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 E=()=>randomBytes(32).toString("base64").replace(/[^a-zA-Z0-9]/g,"").substring(0,128),O=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=E(),p=O(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,O as createCodeChallenge,E as createCodeVerifier,z as generateState,ge as seal,ke as unseal};//# sourceMappingURL=index.js.map
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/strategies/standard-authorization-url.strategy.ts","../src/strategies/standard-token-exchange.strategy.ts","../src/providers/base.provider.ts","../src/providers/generic.provider.ts","../src/profile/base-profile-fetcher.ts","../src/profile/google-profile-fetcher.ts","../src/profile/github-profile-fetcher.ts","../src/profile/microsoft-profile-fetcher.ts","../src/profile/generic-profile-fetcher.ts","../src/profile/profile-fetcher-factory.ts","../src/providers/provider.factory.ts","../src/storage/memory.adapter.ts","../src/utils/crypto.ts","../src/facade/oauth2.facade.ts","../src/utils/seal.ts"],"names":["StandardAuthorizationUrlStrategy","params","value","key","config","state","codeChallenge","extraParams","StandardTokenExchangeStrategy","code","codeVerifier","response","errorText","data","tokenData","now","expiresIn","refreshToken","OAuth2Provider","authUrlStrategy","tokenStrategy","profileFetcher","accessToken","GenericOAuth2Provider","BaseProfileFetcher","profileEndpoint","rawData","GoogleProfileFetcher","GitHubProfileFetcher","_a","MicrosoftProfileFetcher","GenericProfileFetcher","mapping","additionalHeaders","obj","path","current","ProfileFetcherFactory","providerType","options","profileUrl","providerName","OAuth2ProviderFactory","_OAuth2ProviderFactory","type","presetConfig","mergedConfig","name","InMemoryStorageAdapter","input","existingToken","updatedToken","newToken","provider","email","t","id","userId","update","token","expiredTokens","newState","maxAge","expiredStates","createCodeVerifier","randomBytes","createCodeChallenge","verifier","createHash","generateState","OAuth2Client","authUrl","authState","_b","_c","providerInstance","tokens","profile","error","savedToken","storedToken","expirationBuffer","expiresAt","s","seal","d","sealData","unseal","unsealData"],"mappings":"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","file":"index.js","sourcesContent":["import { OAuth2Config } from '../types';\nimport { AuthorizationUrlStrategy } from './authorization-url.strategy';\n\nexport class StandardAuthorizationUrlStrategy implements AuthorizationUrlStrategy {\n protected buildUrlParams(params: Record<string, string | undefined>): string {\n const filtered = Object.entries(params)\n .filter(([, value]) => value !== undefined)\n\n .map(([key, value]) => `${key}=${encodeURIComponent(value as string)}`);\n\n return filtered.join('&');\n }\n\n generateAuthorizationUrl(config: OAuth2Config, state: string, codeChallenge?: string): string {\n const params: Record<string, string | undefined> = {\n client_id: config.clientId,\n redirect_uri: config.redirectUri,\n response_type: 'code',\n scope: config.scopes.join(' '),\n state,\n };\n\n // Add PKCE parameters\n if ((config.usePKCE || config.pkce) && codeChallenge) {\n params.code_challenge = codeChallenge;\n params.code_challenge_method = 'S256';\n }\n\n // Merge additional parameters (for both additionalParams and extraAuthParams)\n const extraParams = {\n ...config.additionalParams,\n ...config.extraAuthParams,\n };\n\n Object.assign(params, extraParams);\n\n return `${config.authorizationUrl}?${this.buildUrlParams(params)}`;\n }\n}\n","import { OAuth2Config, OAuth2Token } from '../types';\nimport { TokenExchangeStrategy } from './token-exchange.strategy';\n\nexport class StandardTokenExchangeStrategy implements TokenExchangeStrategy {\n protected buildUrlParams(params: Record<string, string | undefined>): string {\n const filtered = Object.entries(params)\n .filter(([, value]) => value !== undefined)\n .map(([key, value]) => `${key}=${encodeURIComponent(value as string)}`);\n\n return filtered.join('&');\n }\n\n async exchangeCodeForToken(\n code: string,\n config: OAuth2Config,\n codeVerifier?: string,\n ): Promise<OAuth2Token> {\n const params: Record<string, string | undefined> = {\n grant_type: 'authorization_code',\n code,\n redirect_uri: config.redirectUri,\n client_id: config.clientId,\n };\n\n // Handle PKCE\n if ((config.usePKCE || config.pkce) && codeVerifier) {\n params.code_verifier = codeVerifier;\n } else if (config.clientSecret) {\n params.client_secret = config.clientSecret;\n }\n\n const response = await fetch(config.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: this.buildUrlParams(params),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token exchange failed: ${response.statusText} - ${errorText}`);\n }\n\n const data = await response.json();\n\n // Handle nested response (e.g., Outlook might nest tokens)\n const tokenData = config.responseRootKey ? data[config.responseRootKey] : data;\n\n const now = Date.now();\n const expiresIn = tokenData.expires_in || 3600;\n\n return {\n accessToken: tokenData.access_token,\n refreshToken: tokenData.refresh_token,\n expiresAt: new Date(now + expiresIn * 1000),\n expiresIn: expiresIn,\n tokenType: tokenData.token_type || 'Bearer',\n scope: tokenData.scope,\n createdAt: now,\n raw: data,\n };\n }\n\n async refreshToken(refreshToken: string, config: OAuth2Config): Promise<OAuth2Token> {\n const params: Record<string, string | undefined> = {\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: config.clientId,\n };\n\n // Only add client_secret if not using PKCE\n if (!(config.usePKCE || config.pkce) && config.clientSecret) {\n params.client_secret = config.clientSecret;\n }\n\n const response = await fetch(config.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: this.buildUrlParams(params),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token refresh failed: ${response.statusText} - ${errorText}`);\n }\n\n const data = await response.json();\n const tokenData = config.responseRootKey ? data[config.responseRootKey] : data;\n\n const now = Date.now();\n const expiresIn = tokenData.expires_in || 3600;\n\n return {\n accessToken: tokenData.access_token,\n refreshToken: tokenData.refresh_token || refreshToken,\n expiresAt: new Date(now + expiresIn * 1000),\n expiresIn: expiresIn,\n tokenType: tokenData.token_type || 'Bearer',\n scope: tokenData.scope,\n createdAt: now,\n raw: data,\n };\n }\n}\n","import { OAuth2Config, OAuth2Token } from '../types';\n\nimport { AuthorizationUrlStrategy } from '../strategies/authorization-url.strategy';\nimport { TokenExchangeStrategy } from '../strategies/token-exchange.strategy';\nimport { UserProfile } from './interfaces/profile-fetcher.interface';\nimport { BaseProfileFetcher } from '../profile/base-profile-fetcher';\n\nexport abstract class OAuth2Provider {\n protected authUrlStrategy: AuthorizationUrlStrategy;\n protected tokenStrategy: TokenExchangeStrategy;\n protected profileFetcher?: BaseProfileFetcher;\n\n constructor(\n protected config: OAuth2Config,\n authUrlStrategy?: AuthorizationUrlStrategy,\n tokenStrategy?: TokenExchangeStrategy,\n profileFetcher?: BaseProfileFetcher,\n ) {\n this.authUrlStrategy = authUrlStrategy || this.createAuthorizationUrlStrategy();\n this.tokenStrategy = tokenStrategy || this.createTokenExchangeStrategy();\n this.profileFetcher = profileFetcher;\n }\n\n // Factory methods\n protected abstract createAuthorizationUrlStrategy(): AuthorizationUrlStrategy;\n protected abstract createTokenExchangeStrategy(): TokenExchangeStrategy;\n\n // Profile fetching methods\n async fetchProfile(accessToken: string): Promise<UserProfile> {\n if (!this.profileFetcher) {\n throw new Error('Profile fetcher not configured for this provider');\n }\n return this.profileFetcher.fetchUserInfo(accessToken);\n }\n\n getProfileEndpoint(): string {\n if (!this.profileFetcher) {\n throw new Error('Profile fetcher not configured for this provider');\n }\n return this.profileFetcher.getEndpoint();\n }\n\n setProfileFetcher(profileFetcher: BaseProfileFetcher): void {\n this.profileFetcher = profileFetcher;\n }\n\n hasProfileFetcher(): boolean {\n return !!this.profileFetcher;\n }\n\n generateAuthorizationUrl(state: string, codeChallenge?: string): string {\n return this.authUrlStrategy.generateAuthorizationUrl(this.config, state, codeChallenge);\n }\n\n async exchangeCodeForToken(code: string, codeVerifier?: string): Promise<OAuth2Token> {\n return this.tokenStrategy.exchangeCodeForToken(code, this.config, codeVerifier);\n }\n\n async refreshToken(refreshToken: string): Promise<OAuth2Token> {\n return this.tokenStrategy.refreshToken(refreshToken, this.config);\n }\n}\n","import { AuthorizationUrlStrategy } from '../strategies/authorization-url.strategy';\nimport { StandardAuthorizationUrlStrategy } from '../strategies/standard-authorization-url.strategy';\nimport { StandardTokenExchangeStrategy } from '../strategies/standard-token-exchange.strategy';\nimport { TokenExchangeStrategy } from '../strategies/token-exchange.strategy';\nimport { OAuth2Provider } from './base.provider';\nimport { BaseProfileFetcher } from '../profile/base-profile-fetcher';\n\nexport class GenericOAuth2Provider extends OAuth2Provider {\n constructor(\n config: any,\n authUrlStrategy?: AuthorizationUrlStrategy,\n tokenStrategy?: TokenExchangeStrategy,\n profileFetcher?: BaseProfileFetcher,\n ) {\n super(config, authUrlStrategy, tokenStrategy, profileFetcher);\n }\n\n protected createAuthorizationUrlStrategy(): AuthorizationUrlStrategy {\n return new StandardAuthorizationUrlStrategy();\n }\n\n protected createTokenExchangeStrategy(): TokenExchangeStrategy {\n return new StandardTokenExchangeStrategy();\n }\n}\n","import { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport abstract class BaseProfileFetcher {\n constructor(protected profileEndpoint: string) {}\n\n /**\n * Fetch user profile information from the OAuth provider\n * @param accessToken The OAuth access token\n * @returns Promise resolving to standardized user profile\n */\n async fetchUserInfo(accessToken: string): Promise<UserProfile> {\n const response = await fetch(this.profileEndpoint, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n Accept: 'application/json',\n ...this.getAdditionalHeaders(),\n },\n });\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch profile from ${this.profileEndpoint}: ${response.statusText}`,\n );\n }\n\n const rawData = await response.json();\n return this.mapToUserProfile(rawData);\n }\n\n /**\n * Map the raw API response to our standardized UserProfile structure\n * Override this method to customize mapping for different providers\n */\n protected abstract mapToUserProfile(rawData: any): UserProfile;\n\n /**\n * Get additional headers if needed for the profile request\n * Override this method to add provider-specific headers\n */\n protected getAdditionalHeaders(): Record<string, string> {\n return {};\n }\n\n /**\n * Get the profile endpoint URL\n */\n getEndpoint(): string {\n return this.profileEndpoint;\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class GoogleProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://www.googleapis.com/oauth2/v2/userinfo');\n }\n\n mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.email,\n name: rawData.name,\n id: rawData.id,\n avatar: rawData.picture,\n username: rawData.email,\n raw: rawData,\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class GitHubProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://api.github.com/user');\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.email,\n name: rawData.name || rawData.login,\n id: rawData.id?.toString(),\n avatar: rawData.avatar_url,\n username: rawData.login,\n raw: rawData,\n };\n }\n\n protected getAdditionalHeaders(): Record<string, string> {\n return {\n 'User-Agent': 'OAuth2-Token-Manager', // GitHub requires User-Agent\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class MicrosoftProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://graph.microsoft.com/v1.0/me');\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.mail || rawData.userPrincipalName,\n name: rawData.displayName,\n id: rawData.id,\n avatar: undefined, // Microsoft Graph doesn't include avatar in basic profile\n username: rawData.userPrincipalName,\n raw: rawData,\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport interface ProfileMapping {\n email: string;\n name?: string;\n id?: string;\n avatar?: string;\n username?: string;\n}\n\nexport class GenericProfileFetcher extends BaseProfileFetcher {\n constructor(\n profileEndpoint: string,\n private mapping?: ProfileMapping,\n private additionalHeaders?: Record<string, string>,\n ) {\n super(profileEndpoint);\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n if (this.mapping) {\n return {\n email: this.getNestedProperty(rawData, this.mapping.email),\n name: this.mapping.name ? this.getNestedProperty(rawData, this.mapping.name) : undefined,\n id: this.mapping.id ? this.getNestedProperty(rawData, this.mapping.id) : undefined,\n avatar: this.mapping.avatar\n ? this.getNestedProperty(rawData, this.mapping.avatar)\n : undefined,\n username: this.mapping.username\n ? this.getNestedProperty(rawData, this.mapping.username)\n : undefined,\n raw: rawData,\n };\n }\n\n // Default generic mapping\n return {\n email: rawData.email || rawData.mail || rawData.emailAddress,\n name: rawData.name || rawData.displayName || rawData.full_name,\n id: rawData.id || rawData.sub || rawData.user_id,\n avatar: rawData.avatar || rawData.picture || rawData.avatar_url,\n username: rawData.username || rawData.login || rawData.preferred_username,\n raw: rawData,\n };\n }\n\n protected getAdditionalHeaders(): Record<string, string> {\n return this.additionalHeaders || {};\n }\n\n private getNestedProperty(obj: any, path: string): any {\n return path.split('.').reduce((current, key) => current?.[key], obj);\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { GoogleProfileFetcher } from './google-profile-fetcher';\nimport { GitHubProfileFetcher } from './github-profile-fetcher';\nimport { MicrosoftProfileFetcher } from './microsoft-profile-fetcher';\nimport { GenericProfileFetcher, ProfileMapping } from './generic-profile-fetcher';\nimport { ProviderType } from '../providers/provider.factory';\nimport { OAuth2Config } from '../types';\n\nexport interface ProfileFetcherOptions {\n profileUrl?: string;\n profileMapping?: ProfileMapping;\n profileHeaders?: Record<string, string>;\n}\n\nexport class ProfileFetcherFactory {\n static createProfileFetcher(\n providerType: ProviderType,\n config: OAuth2Config,\n options?: ProfileFetcherOptions,\n ): BaseProfileFetcher {\n // If custom options are provided, use GenericProfileFetcher\n if (options?.profileUrl) {\n return new GenericProfileFetcher(\n options.profileUrl,\n options.profileMapping,\n options.profileHeaders,\n );\n }\n\n // Use provider-specific fetchers for known providers\n switch (providerType) {\n case 'google':\n return new GoogleProfileFetcher();\n case 'github':\n return new GitHubProfileFetcher();\n case 'microsoft':\n case 'outlook':\n return new MicrosoftProfileFetcher();\n case 'facebook':\n return new GenericProfileFetcher(\n 'https://graph.facebook.com/me?fields=id,name,email,picture',\n );\n case 'generic':\n default:\n // For generic providers, use the profileUrl from config\n const profileUrl = config.profileUrl || config.userInfoUrl;\n if (!profileUrl) {\n throw new Error(`Profile URL must be provided for ${providerType} provider`);\n }\n return new GenericProfileFetcher(profileUrl);\n }\n }\n\n static registerCustomProfileFetcher(\n providerName: string,\n profileFetcher: BaseProfileFetcher,\n ): void {\n // Store custom profile fetchers for later use\n this.customFetchers.set(providerName, profileFetcher);\n }\n\n private static customFetchers = new Map<string, BaseProfileFetcher>();\n\n static getCustomProfileFetcher(providerName: string): BaseProfileFetcher | undefined {\n return this.customFetchers.get(providerName);\n }\n}\n","import { OAuth2Config } from '../types';\nimport { OAuth2Provider } from './base.provider';\nimport { GenericOAuth2Provider } from './generic.provider';\nimport { ProfileFetcherFactory } from '../profile/profile-fetcher-factory';\n\nexport type ProviderType = 'google' | 'github' | 'microsoft' | 'outlook' | 'facebook' | 'generic';\n\nexport interface ProviderFactory {\n createProvider(type: ProviderType, config: OAuth2Config): OAuth2Provider;\n}\n\nexport class OAuth2ProviderFactory implements ProviderFactory {\n private static presetConfigs: Record<string, Partial<OAuth2Config>> = {\n google: {\n authorizationUrl: 'https://accounts.google.com/o/oauth2/v2/auth',\n tokenUrl: 'https://oauth2.googleapis.com/token',\n profileUrl: 'https://www.googleapis.com/oauth2/v2/userinfo',\n usePKCE: true,\n extraAuthParams: {\n access_type: 'offline',\n prompt: 'consent',\n },\n },\n github: {\n authorizationUrl: 'https://github.com/login/oauth/authorize',\n tokenUrl: 'https://github.com/login/oauth/access_token',\n profileUrl: 'https://api.github.com/user',\n },\n microsoft: {\n authorizationUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',\n tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',\n profileUrl: 'https://graph.microsoft.com/v1.0/me',\n usePKCE: true,\n },\n outlook: {\n authorizationUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',\n tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',\n profileUrl: 'https://graph.microsoft.com/v1.0/me',\n usePKCE: true,\n extraAuthParams: {\n prompt: 'select_account',\n },\n },\n facebook: {\n authorizationUrl: 'https://www.facebook.com/v12.0/dialog/oauth',\n tokenUrl: 'https://graph.facebook.com/v12.0/oauth/access_token',\n profileUrl: 'https://graph.facebook.com/me?fields=id,name,email,picture',\n },\n };\n\n createProvider(type: ProviderType, config: OAuth2Config): OAuth2Provider {\n const presetConfig = type !== 'generic' ? OAuth2ProviderFactory.presetConfigs[type] || {} : {};\n\n // Only override preset values if the user explicitly provides them (not empty strings)\n const mergedConfig: OAuth2Config = {\n ...presetConfig,\n ...config,\n // Don't override preset URLs with empty strings\n authorizationUrl: config.authorizationUrl || presetConfig.authorizationUrl || '',\n tokenUrl: config.tokenUrl || presetConfig.tokenUrl || '',\n profileUrl: config.profileUrl || presetConfig.profileUrl,\n extraAuthParams: {\n ...(presetConfig.extraAuthParams || {}),\n ...(config.extraAuthParams || {}),\n },\n };\n\n const profileFetcher = ProfileFetcherFactory.createProfileFetcher(type, mergedConfig);\n\n return new GenericOAuth2Provider(mergedConfig, undefined, undefined, profileFetcher);\n }\n\n static registerPreset(name: string, config: Partial<OAuth2Config>): void {\n OAuth2ProviderFactory.presetConfigs[name] = config;\n }\n\n static getPresetConfig(name: string): Partial<OAuth2Config> | undefined {\n return OAuth2ProviderFactory.presetConfigs[name];\n }\n}\n","import { AuthorizationState } from '../types';\nimport { StorageAdapter, StoredToken, SaveTokenInput, UpdateTokenInput } from './interfaces';\n\nexport class InMemoryStorageAdapter implements StorageAdapter {\n private tokens: Map<string, StoredToken> = new Map();\n private states: Map<string, AuthorizationState> = new Map();\n\n private generateId(): string {\n return Math.random().toString(36).substring(2) + Date.now().toString(36);\n }\n\n // Token operations\n async saveToken(input: SaveTokenInput): Promise<StoredToken> {\n // Check if token with same provider + email exists\n const existingToken = await this.getToken(input.provider, input.email);\n\n if (existingToken) {\n // Replace existing token\n const updatedToken: StoredToken = {\n ...existingToken,\n ...input,\n id: existingToken.id,\n createdAt: existingToken.createdAt,\n updatedAt: new Date(),\n };\n this.tokens.set(existingToken.id, updatedToken);\n return updatedToken;\n }\n\n // Create new token\n const newToken: StoredToken = {\n ...input,\n id: this.generateId(),\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n this.tokens.set(newToken.id, newToken);\n return newToken;\n }\n\n async getToken(provider: string, email: string): Promise<StoredToken | null> {\n const tokens = Array.from(this.tokens.values());\n return tokens.find((t) => t.provider === provider && t.email === email) || null;\n }\n\n async getTokenById(id: string): Promise<StoredToken | null> {\n return this.tokens.get(id) || null;\n }\n\n async getTokensByUserId(userId: string): Promise<StoredToken[]> {\n return Array.from(this.tokens.values()).filter((t) => t.userId === userId);\n }\n\n async getTokensByEmail(email: string): Promise<StoredToken[]> {\n return Array.from(this.tokens.values()).filter((t) => t.email === email);\n }\n\n async getTokensByProvider(provider: string): Promise<StoredToken[]> {\n return Array.from(this.tokens.values()).filter((t) => t.provider === provider);\n }\n\n async updateToken(id: string, update: UpdateTokenInput): Promise<StoredToken | null> {\n const token = this.tokens.get(id);\n if (!token) return null;\n\n const updatedToken: StoredToken = {\n ...token,\n ...(update.token && { token: update.token }),\n ...(update.metadata && { metadata: { ...token.metadata, ...update.metadata } }),\n updatedAt: new Date(),\n };\n this.tokens.set(id, updatedToken);\n return updatedToken;\n }\n\n async deleteToken(id: string): Promise<boolean> {\n return this.tokens.delete(id);\n }\n\n async deleteTokenByProviderEmail(provider: string, email: string): Promise<boolean> {\n const token = await this.getToken(provider, email);\n if (!token) return false;\n return this.tokens.delete(token.id);\n }\n\n async deleteExpiredTokens(): Promise<number> {\n const now = new Date().getTime();\n const expiredTokens = Array.from(this.tokens.entries())\n .filter(([, token]) => {\n const expiresAt = new Date(token.token.expiresAt).getTime();\n return expiresAt < now;\n })\n .map(([id]) => id);\n\n expiredTokens.forEach((id) => this.tokens.delete(id));\n return expiredTokens.length;\n }\n\n // Authorization state operations\n async saveAuthorizationState(\n state: Omit<AuthorizationState, 'createdAt'>,\n ): Promise<AuthorizationState> {\n const newState: AuthorizationState = {\n ...state,\n createdAt: new Date(Date.now()),\n };\n this.states.set(state.state, newState);\n return newState;\n }\n\n async getAuthorizationState(state: string): Promise<AuthorizationState | null> {\n return this.states.get(state) || null;\n }\n\n async deleteAuthorizationState(state: string): Promise<boolean> {\n return this.states.delete(state);\n }\n\n async cleanupExpiredStates(): Promise<number> {\n const now = new Date().getTime();\n const maxAge = 10 * 60 * 1000; // 10 minutes\n\n const expiredStates = Array.from(this.states.entries())\n .filter(([, state]) => {\n const stateAge = now - state.createdAt.getTime();\n return stateAge > maxAge;\n })\n .map(([key]) => key);\n\n expiredStates.forEach((key) => this.states.delete(key));\n return expiredStates.length;\n }\n}\n","import { createHash, randomBytes } from 'crypto';\n\nexport const createCodeVerifier = () =>\n randomBytes(32)\n .toString('base64')\n .replace(/[^a-zA-Z0-9]/g, '')\n .substring(0, 128);\n\nexport const createCodeChallenge = (verifier: string): string => {\n return createHash('sha256').update(verifier).digest('base64url');\n};\n\nexport const generateState = (): string => {\n return randomBytes(16).toString('base64url');\n};\n","import { OAuth2Config, OAuth2Token, AuthorizationState } from '../types';\nimport { OAuth2ProviderFactory, ProviderType } from '../providers/provider.factory';\nimport { StorageAdapter, StoredToken } from '../storage/interfaces';\nimport { InMemoryStorageAdapter } from '../storage/memory.adapter';\nimport { ProviderFactory } from '../providers/provider.factory';\nimport { createCodeVerifier, createCodeChallenge, generateState } from '../utils/crypto';\nimport { OAuth2Provider } from '../providers/base.provider';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport interface OAuth2Options {\n storage?: StorageAdapter;\n providers?: Record<string, OAuth2Config>;\n}\n\nexport interface AuthorizationOptions {\n provider: string;\n userId: string;\n email: string;\n scopes?: string[];\n metadata?: Record<string, any>;\n usePKCE?: boolean;\n}\n\nexport interface TokenOptions {\n autoRefresh?: boolean;\n refreshBuffer?: number; // minutes before expiry to refresh\n expirationBuffer?: number; // seconds before expiry to consider expired\n defaultExpiresIn?: number; // default expiration in seconds\n}\n\nexport interface CallbackResult {\n token: StoredToken;\n profile?: UserProfile;\n}\n\nexport class OAuth2Client {\n private storage: StorageAdapter;\n private providerFactory: ProviderFactory;\n private providers: Map<string, OAuth2Provider> = new Map();\n private providerConfigs: Map<string, OAuth2Config> = new Map();\n private now: () => number;\n\n constructor(options: OAuth2Options = {}) {\n this.storage = options.storage || new InMemoryStorageAdapter();\n this.providerFactory = new OAuth2ProviderFactory();\n this.now = Date.now;\n\n // Register predefined providers\n if (options.providers) {\n Object.entries(options.providers).forEach(([name, config]) => {\n this.registerProvider(name, config);\n });\n }\n }\n\n /**\n * Register a provider configuration\n */\n registerProvider(name: string, config: OAuth2Config): void {\n this.providerConfigs.set(name, config);\n\n // Determine provider type based on configuration\n const providerType = this.detectProviderType(name, config);\n const provider = this.providerFactory.createProvider(providerType, config);\n this.providers.set(name, provider);\n }\n\n /**\n * Start OAuth2 authorization flow\n */\n async authorize(options: AuthorizationOptions): Promise<{ url: string; state: string }> {\n const provider = this.providers.get(options.provider);\n if (!provider) throw new Error(`Provider ${options.provider} not found`);\n\n const state = generateState();\n let authUrl: string;\n let authState: Omit<AuthorizationState, 'createdAt'>;\n\n const requiresPKCE = this.providerConfigs.get(options.provider)?.usePKCE || options.usePKCE;\n\n if (requiresPKCE) {\n const codeVerifier = createCodeVerifier();\n const codeChallenge = createCodeChallenge(codeVerifier);\n authUrl = provider.generateAuthorizationUrl(state, codeChallenge);\n authState = {\n state,\n codeVerifier,\n config: this.providerConfigs.get(options.provider)!,\n metadata: {\n ...options.metadata,\n userId: options.userId,\n email: options.email,\n provider: options.provider,\n },\n };\n } else {\n authUrl = provider.generateAuthorizationUrl(state);\n authState = {\n state,\n config: this.providerConfigs.get(options.provider)!,\n metadata: {\n ...options.metadata,\n userId: options.userId,\n email: options.email,\n provider: options.provider,\n },\n };\n }\n\n await this.storage.saveAuthorizationState(authState);\n return { url: authUrl, state };\n }\n\n /**\n * Handle OAuth2 callback\n */\n async handleCallback(code: string, state: string): Promise<CallbackResult> {\n const authState = await this.storage.getAuthorizationState(state);\n if (!authState) throw new Error('Invalid or expired state');\n\n const provider = authState.metadata?.provider;\n if (!provider) throw new Error('Provider not found in authorization state');\n\n const providerInstance = this.providers.get(provider);\n if (!providerInstance) throw new Error(`Provider ${provider} not found`);\n\n // Exchange code for tokens\n const tokens = await providerInstance.exchangeCodeForToken(code, authState.codeVerifier);\n\n // Extract user data from metadata\n const userId = authState.metadata?.userId;\n const email = authState.metadata?.email;\n\n if (!userId || !email) {\n throw new Error('User ID and email are required in authorization state');\n }\n\n // Fetch profile if available\n let profile: UserProfile | undefined;\n if (providerInstance.hasProfileFetcher()) {\n try {\n profile = await providerInstance.fetchProfile(tokens.accessToken);\n } catch (error) {\n console.warn('Failed to fetch user profile:', error);\n }\n }\n\n // Save token\n const savedToken = await this.storage.saveToken({\n provider,\n userId,\n email,\n token: tokens,\n metadata: {\n ...authState.metadata,\n profileFetched: !!profile,\n },\n });\n\n // Clean up authorization state\n await this.storage.deleteAuthorizationState(state);\n\n // Call onSuccess callback if defined\n const config = this.providerConfigs.get(provider);\n if (config?.onSuccess) {\n await config.onSuccess(userId, tokens);\n }\n\n return {\n token: savedToken,\n profile,\n };\n }\n\n /**\n * Get a valid access token (auto-refresh if needed)\n */\n async getAccessToken(\n provider: string,\n email: string,\n options: TokenOptions = {},\n ): Promise<string> {\n const token = await this.getValidToken(provider, email, options);\n return token.accessToken;\n }\n\n /**\n * Get a valid token (auto-refresh if needed)\n */\n async getValidToken(\n provider: string,\n email: string,\n options: TokenOptions = {},\n ): Promise<OAuth2Token> {\n const storedToken = await this.storage.getToken(provider, email);\n if (!storedToken) {\n throw new Error(`No token found for provider ${provider} and email ${email}`);\n }\n\n const needsRefresh =\n options.autoRefresh !== false && this.isTokenExpired(storedToken.token, options);\n\n if (!needsRefresh) {\n return storedToken.token;\n }\n\n // Refresh the token\n if (!storedToken.token.refreshToken) {\n throw new Error('Token expired and no refresh token available');\n }\n\n const providerInstance = this.providers.get(provider);\n if (!providerInstance) throw new Error(`Provider ${provider} not found`);\n\n const newToken = await providerInstance.refreshToken(storedToken.token.refreshToken);\n await this.storage.updateToken(storedToken.id, { token: newToken });\n\n return newToken;\n }\n\n /**\n * Get all tokens for a user\n */\n async getTokensByUserId(userId: string): Promise<StoredToken[]> {\n return this.storage.getTokensByUserId(userId);\n }\n\n /**\n * Get all tokens for an email\n */\n async getTokensByEmail(email: string): Promise<StoredToken[]> {\n return this.storage.getTokensByEmail(email);\n }\n\n /**\n * Delete a token\n */\n async deleteToken(provider: string, email: string): Promise<boolean> {\n return this.storage.deleteTokenByProviderEmail(provider, email);\n }\n\n /**\n * Delete all expired tokens\n */\n async cleanupExpiredTokens(): Promise<number> {\n return this.storage.deleteExpiredTokens();\n }\n\n /**\n * Clean up expired authorization states\n */\n async cleanupExpiredStates(): Promise<number> {\n return this.storage.cleanupExpiredStates();\n }\n\n // Helper methods\n private isTokenExpired(token: OAuth2Token, options: TokenOptions = {}): boolean {\n const { expirationBuffer = 300 } = options;\n\n if (token.createdAt && token.expiresIn !== undefined) {\n const expiresAt = token.createdAt + token.expiresIn * 1000;\n const effectiveNow = this.now() + expirationBuffer * 1000;\n return effectiveNow >= expiresAt;\n }\n\n const expiresAt = new Date(token.expiresAt).getTime();\n const effectiveNow = this.now() + expirationBuffer * 1000;\n return effectiveNow >= expiresAt;\n }\n\n private detectProviderType(name: string, config: OAuth2Config): ProviderType {\n // Try to detect based on the authorization URL\n const authUrl = config.authorizationUrl.toLowerCase();\n\n // Check for known providers that have specific implementations\n if (authUrl.includes('accounts.google.com')) return 'google';\n if (authUrl.includes('github.com')) return 'github';\n if (authUrl.includes('facebook.com')) return 'facebook';\n if (authUrl.includes('microsoft.com') || authUrl.includes('microsoftonline.com')) {\n // Check if it's specifically for Outlook\n if (\n name.toLowerCase().includes('outlook') ||\n config.scopes?.some((s) => s.includes('outlook'))\n ) {\n return 'outlook';\n }\n return 'microsoft';\n }\n\n // Default to generic provider for all others\n return 'generic';\n }\n}\n","import { sealData, unsealData } from 'iron-session';\n\nexport const seal = <T>(d: T, key: string) => sealData(d, { password: key });\nexport const unseal = <T>(s: string, key: string) => unsealData<T>(s, { password: key });\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/strategies/standard-authorization-url.strategy.ts","../src/strategies/standard-token-exchange.strategy.ts","../src/providers/base.provider.ts","../src/providers/generic.provider.ts","../src/profile/base-profile-fetcher.ts","../src/profile/google-profile-fetcher.ts","../src/profile/github-profile-fetcher.ts","../src/profile/microsoft-profile-fetcher.ts","../src/profile/generic-profile-fetcher.ts","../src/profile/profile-fetcher-factory.ts","../src/providers/provider.factory.ts","../src/storage/memory.adapter.ts","../src/utils/crypto.ts","../src/facade/oauth2.facade.ts","../src/utils/seal.ts"],"names":["StandardAuthorizationUrlStrategy","params","value","key","config","state","codeChallenge","extraParams","StandardTokenExchangeStrategy","code","codeVerifier","response","errorText","data","tokenData","now","expiresIn","refreshToken","OAuth2Provider","authUrlStrategy","tokenStrategy","profileFetcher","accessToken","GenericOAuth2Provider","BaseProfileFetcher","profileEndpoint","rawData","GoogleProfileFetcher","GitHubProfileFetcher","_a","MicrosoftProfileFetcher","GenericProfileFetcher","mapping","additionalHeaders","obj","path","current","ProfileFetcherFactory","providerType","options","profileUrl","providerName","OAuth2ProviderFactory","_OAuth2ProviderFactory","type","presetConfig","mergedConfig","name","InMemoryStorageAdapter","input","existingToken","updatedToken","newToken","provider","email","t","id","userId","token","update","expiredTokens","newState","maxAge","expiredStates","createCodeVerifier","randomBytes","createCodeChallenge","verifier","createHash","generateState","OAuth2Client","authUrl","authState","_b","_c","providerInstance","tokens","profile","error","savedToken","storedToken","expirationBuffer","expiresAt","s","seal","d","sealData","unseal","unsealData"],"mappings":"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","file":"index.js","sourcesContent":["import { OAuth2Config } from '../types';\nimport { AuthorizationUrlStrategy } from './authorization-url.strategy';\n\nexport class StandardAuthorizationUrlStrategy implements AuthorizationUrlStrategy {\n protected buildUrlParams(params: Record<string, string | undefined>): string {\n const filtered = Object.entries(params)\n .filter(([, value]) => value !== undefined)\n\n .map(([key, value]) => `${key}=${encodeURIComponent(value as string)}`);\n\n return filtered.join('&');\n }\n\n generateAuthorizationUrl(config: OAuth2Config, state: string, codeChallenge?: string): string {\n const params: Record<string, string | undefined> = {\n client_id: config.clientId,\n redirect_uri: config.redirectUri,\n response_type: 'code',\n scope: config.scopes.join(' '),\n state,\n };\n\n // Add PKCE parameters\n if ((config.usePKCE || config.pkce) && codeChallenge) {\n params.code_challenge = codeChallenge;\n params.code_challenge_method = 'S256';\n }\n\n // Merge additional parameters (for both additionalParams and extraAuthParams)\n const extraParams = {\n ...config.additionalParams,\n ...config.extraAuthParams,\n };\n\n Object.assign(params, extraParams);\n\n return `${config.authorizationUrl}?${this.buildUrlParams(params)}`;\n }\n}\n","import { OAuth2Config, OAuth2Token } from '../types';\nimport { TokenExchangeStrategy } from './token-exchange.strategy';\n\nexport class StandardTokenExchangeStrategy implements TokenExchangeStrategy {\n protected buildUrlParams(params: Record<string, string | undefined>): string {\n const filtered = Object.entries(params)\n .filter(([, value]) => value !== undefined)\n .map(([key, value]) => `${key}=${encodeURIComponent(value as string)}`);\n\n return filtered.join('&');\n }\n\n async exchangeCodeForToken(\n code: string,\n config: OAuth2Config,\n codeVerifier?: string,\n ): Promise<OAuth2Token> {\n const params: Record<string, string | undefined> = {\n grant_type: 'authorization_code',\n code,\n redirect_uri: config.redirectUri,\n client_id: config.clientId,\n };\n\n // Handle PKCE\n if ((config.usePKCE || config.pkce) && codeVerifier) {\n params.code_verifier = codeVerifier;\n } else if (config.clientSecret) {\n params.client_secret = config.clientSecret;\n }\n\n const response = await fetch(config.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: this.buildUrlParams(params),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token exchange failed: ${response.statusText} - ${errorText}`);\n }\n\n const data = await response.json();\n\n // Handle nested response (e.g., Outlook might nest tokens)\n const tokenData = config.responseRootKey ? data[config.responseRootKey] : data;\n\n const now = Date.now();\n const expiresIn = tokenData.expires_in || 3600;\n\n return {\n accessToken: tokenData.access_token,\n refreshToken: tokenData.refresh_token,\n expiresAt: new Date(now + expiresIn * 1000),\n expiresIn: expiresIn,\n tokenType: tokenData.token_type || 'Bearer',\n scope: tokenData.scope,\n createdAt: now,\n raw: data,\n };\n }\n\n async refreshToken(refreshToken: string, config: OAuth2Config): Promise<OAuth2Token> {\n const params: Record<string, string | undefined> = {\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: config.clientId,\n };\n\n // Only add client_secret if not using PKCE\n if (!(config.usePKCE || config.pkce) && config.clientSecret) {\n params.client_secret = config.clientSecret;\n }\n\n const response = await fetch(config.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: this.buildUrlParams(params),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token refresh failed: ${response.statusText} - ${errorText}`);\n }\n\n const data = await response.json();\n const tokenData = config.responseRootKey ? data[config.responseRootKey] : data;\n\n const now = Date.now();\n const expiresIn = tokenData.expires_in || 3600;\n\n return {\n accessToken: tokenData.access_token,\n refreshToken: tokenData.refresh_token || refreshToken,\n expiresAt: new Date(now + expiresIn * 1000),\n expiresIn: expiresIn,\n tokenType: tokenData.token_type || 'Bearer',\n scope: tokenData.scope,\n createdAt: now,\n raw: data,\n };\n }\n}\n","import { OAuth2Config, OAuth2Token } from '../types';\n\nimport { AuthorizationUrlStrategy } from '../strategies/authorization-url.strategy';\nimport { TokenExchangeStrategy } from '../strategies/token-exchange.strategy';\nimport { UserProfile } from './interfaces/profile-fetcher.interface';\nimport { BaseProfileFetcher } from '../profile/base-profile-fetcher';\n\nexport abstract class OAuth2Provider {\n protected authUrlStrategy: AuthorizationUrlStrategy;\n protected tokenStrategy: TokenExchangeStrategy;\n protected profileFetcher?: BaseProfileFetcher;\n\n constructor(\n protected config: OAuth2Config,\n authUrlStrategy?: AuthorizationUrlStrategy,\n tokenStrategy?: TokenExchangeStrategy,\n profileFetcher?: BaseProfileFetcher,\n ) {\n this.authUrlStrategy = authUrlStrategy || this.createAuthorizationUrlStrategy();\n this.tokenStrategy = tokenStrategy || this.createTokenExchangeStrategy();\n this.profileFetcher = profileFetcher;\n }\n\n // Factory methods\n protected abstract createAuthorizationUrlStrategy(): AuthorizationUrlStrategy;\n protected abstract createTokenExchangeStrategy(): TokenExchangeStrategy;\n\n // Profile fetching methods\n async fetchProfile(accessToken: string): Promise<UserProfile> {\n if (!this.profileFetcher) {\n throw new Error('Profile fetcher not configured for this provider');\n }\n return this.profileFetcher.fetchUserInfo(accessToken);\n }\n\n getProfileEndpoint(): string {\n if (!this.profileFetcher) {\n throw new Error('Profile fetcher not configured for this provider');\n }\n return this.profileFetcher.getEndpoint();\n }\n\n setProfileFetcher(profileFetcher: BaseProfileFetcher): void {\n this.profileFetcher = profileFetcher;\n }\n\n hasProfileFetcher(): boolean {\n return !!this.profileFetcher;\n }\n\n generateAuthorizationUrl(state: string, codeChallenge?: string): string {\n return this.authUrlStrategy.generateAuthorizationUrl(this.config, state, codeChallenge);\n }\n\n async exchangeCodeForToken(code: string, codeVerifier?: string): Promise<OAuth2Token> {\n return this.tokenStrategy.exchangeCodeForToken(code, this.config, codeVerifier);\n }\n\n async refreshToken(refreshToken: string): Promise<OAuth2Token> {\n return this.tokenStrategy.refreshToken(refreshToken, this.config);\n }\n}\n","import { AuthorizationUrlStrategy } from '../strategies/authorization-url.strategy';\nimport { StandardAuthorizationUrlStrategy } from '../strategies/standard-authorization-url.strategy';\nimport { StandardTokenExchangeStrategy } from '../strategies/standard-token-exchange.strategy';\nimport { TokenExchangeStrategy } from '../strategies/token-exchange.strategy';\nimport { OAuth2Provider } from './base.provider';\nimport { BaseProfileFetcher } from '../profile/base-profile-fetcher';\n\nexport class GenericOAuth2Provider extends OAuth2Provider {\n constructor(\n config: any,\n authUrlStrategy?: AuthorizationUrlStrategy,\n tokenStrategy?: TokenExchangeStrategy,\n profileFetcher?: BaseProfileFetcher,\n ) {\n super(config, authUrlStrategy, tokenStrategy, profileFetcher);\n }\n\n protected createAuthorizationUrlStrategy(): AuthorizationUrlStrategy {\n return new StandardAuthorizationUrlStrategy();\n }\n\n protected createTokenExchangeStrategy(): TokenExchangeStrategy {\n return new StandardTokenExchangeStrategy();\n }\n}\n","import { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport abstract class BaseProfileFetcher {\n constructor(protected profileEndpoint: string) {}\n\n /**\n * Fetch user profile information from the OAuth provider\n * @param accessToken The OAuth access token\n * @returns Promise resolving to standardized user profile\n */\n async fetchUserInfo(accessToken: string): Promise<UserProfile> {\n const response = await fetch(this.profileEndpoint, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n Accept: 'application/json',\n ...this.getAdditionalHeaders(),\n },\n });\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch profile from ${this.profileEndpoint}: ${response.statusText}`,\n );\n }\n\n const rawData = await response.json();\n return this.mapToUserProfile(rawData);\n }\n\n /**\n * Map the raw API response to our standardized UserProfile structure\n * Override this method to customize mapping for different providers\n */\n protected abstract mapToUserProfile(rawData: any): UserProfile;\n\n /**\n * Get additional headers if needed for the profile request\n * Override this method to add provider-specific headers\n */\n protected getAdditionalHeaders(): Record<string, string> {\n return {};\n }\n\n /**\n * Get the profile endpoint URL\n */\n getEndpoint(): string {\n return this.profileEndpoint;\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class GoogleProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://www.googleapis.com/oauth2/v2/userinfo');\n }\n\n mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.email,\n name: rawData.name,\n id: rawData.id,\n avatar: rawData.picture,\n username: rawData.email,\n raw: rawData,\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class GitHubProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://api.github.com/user');\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.email,\n name: rawData.name || rawData.login,\n id: rawData.id?.toString(),\n avatar: rawData.avatar_url,\n username: rawData.login,\n raw: rawData,\n };\n }\n\n protected getAdditionalHeaders(): Record<string, string> {\n return {\n 'User-Agent': 'OAuth2-Token-Manager', // GitHub requires User-Agent\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class MicrosoftProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://graph.microsoft.com/v1.0/me');\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.mail || rawData.userPrincipalName,\n name: rawData.displayName,\n id: rawData.id,\n avatar: undefined, // Microsoft Graph doesn't include avatar in basic profile\n username: rawData.userPrincipalName,\n raw: rawData,\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport interface ProfileMapping {\n email: string;\n name?: string;\n id?: string;\n avatar?: string;\n username?: string;\n}\n\nexport class GenericProfileFetcher extends BaseProfileFetcher {\n constructor(\n profileEndpoint: string,\n private mapping?: ProfileMapping,\n private additionalHeaders?: Record<string, string>,\n ) {\n super(profileEndpoint);\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n if (this.mapping) {\n return {\n email: this.getNestedProperty(rawData, this.mapping.email),\n name: this.mapping.name ? this.getNestedProperty(rawData, this.mapping.name) : undefined,\n id: this.mapping.id ? this.getNestedProperty(rawData, this.mapping.id) : undefined,\n avatar: this.mapping.avatar\n ? this.getNestedProperty(rawData, this.mapping.avatar)\n : undefined,\n username: this.mapping.username\n ? this.getNestedProperty(rawData, this.mapping.username)\n : undefined,\n raw: rawData,\n };\n }\n\n // Default generic mapping\n return {\n email: rawData.email || rawData.mail || rawData.emailAddress,\n name: rawData.name || rawData.displayName || rawData.full_name,\n id: rawData.id || rawData.sub || rawData.user_id,\n avatar: rawData.avatar || rawData.picture || rawData.avatar_url,\n username: rawData.username || rawData.login || rawData.preferred_username,\n raw: rawData,\n };\n }\n\n protected getAdditionalHeaders(): Record<string, string> {\n return this.additionalHeaders || {};\n }\n\n private getNestedProperty(obj: any, path: string): any {\n return path.split('.').reduce((current, key) => current?.[key], obj);\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { GoogleProfileFetcher } from './google-profile-fetcher';\nimport { GitHubProfileFetcher } from './github-profile-fetcher';\nimport { MicrosoftProfileFetcher } from './microsoft-profile-fetcher';\nimport { GenericProfileFetcher, ProfileMapping } from './generic-profile-fetcher';\nimport { ProviderType } from '../providers/provider.factory';\nimport { OAuth2Config } from '../types';\n\nexport interface ProfileFetcherOptions {\n profileUrl?: string;\n profileMapping?: ProfileMapping;\n profileHeaders?: Record<string, string>;\n}\n\nexport class ProfileFetcherFactory {\n static createProfileFetcher(\n providerType: ProviderType,\n config: OAuth2Config,\n options?: ProfileFetcherOptions,\n ): BaseProfileFetcher {\n // If custom options are provided, use GenericProfileFetcher\n if (options?.profileUrl) {\n return new GenericProfileFetcher(\n options.profileUrl,\n options.profileMapping,\n options.profileHeaders,\n );\n }\n\n // Use provider-specific fetchers for known providers\n switch (providerType) {\n case 'google':\n return new GoogleProfileFetcher();\n case 'github':\n return new GitHubProfileFetcher();\n case 'microsoft':\n case 'outlook':\n return new MicrosoftProfileFetcher();\n case 'facebook':\n return new GenericProfileFetcher(\n 'https://graph.facebook.com/me?fields=id,name,email,picture',\n );\n case 'generic':\n default:\n // For generic providers, use the profileUrl from config\n const profileUrl = config.profileUrl || config.userInfoUrl;\n if (!profileUrl) {\n throw new Error(`Profile URL must be provided for ${providerType} provider`);\n }\n return new GenericProfileFetcher(profileUrl);\n }\n }\n\n static registerCustomProfileFetcher(\n providerName: string,\n profileFetcher: BaseProfileFetcher,\n ): void {\n // Store custom profile fetchers for later use\n this.customFetchers.set(providerName, profileFetcher);\n }\n\n private static customFetchers = new Map<string, BaseProfileFetcher>();\n\n static getCustomProfileFetcher(providerName: string): BaseProfileFetcher | undefined {\n return this.customFetchers.get(providerName);\n }\n}\n","import { OAuth2Config } from '../types';\nimport { OAuth2Provider } from './base.provider';\nimport { GenericOAuth2Provider } from './generic.provider';\nimport { ProfileFetcherFactory } from '../profile/profile-fetcher-factory';\n\nexport type ProviderType = 'google' | 'github' | 'microsoft' | 'outlook' | 'facebook' | 'generic';\n\nexport interface ProviderFactory {\n createProvider(type: ProviderType, config: OAuth2Config): OAuth2Provider;\n}\n\nexport class OAuth2ProviderFactory implements ProviderFactory {\n private static presetConfigs: Record<string, Partial<OAuth2Config>> = {\n google: {\n authorizationUrl: 'https://accounts.google.com/o/oauth2/v2/auth',\n tokenUrl: 'https://oauth2.googleapis.com/token',\n profileUrl: 'https://www.googleapis.com/oauth2/v2/userinfo',\n usePKCE: true,\n extraAuthParams: {\n access_type: 'offline',\n prompt: 'consent',\n },\n },\n github: {\n authorizationUrl: 'https://github.com/login/oauth/authorize',\n tokenUrl: 'https://github.com/login/oauth/access_token',\n profileUrl: 'https://api.github.com/user',\n },\n microsoft: {\n authorizationUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',\n tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',\n profileUrl: 'https://graph.microsoft.com/v1.0/me',\n usePKCE: true,\n },\n outlook: {\n authorizationUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',\n tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',\n profileUrl: 'https://graph.microsoft.com/v1.0/me',\n usePKCE: true,\n extraAuthParams: {\n prompt: 'select_account',\n },\n },\n facebook: {\n authorizationUrl: 'https://www.facebook.com/v12.0/dialog/oauth',\n tokenUrl: 'https://graph.facebook.com/v12.0/oauth/access_token',\n profileUrl: 'https://graph.facebook.com/me?fields=id,name,email,picture',\n },\n };\n\n createProvider(type: ProviderType, config: OAuth2Config): OAuth2Provider {\n const presetConfig = type !== 'generic' ? OAuth2ProviderFactory.presetConfigs[type] || {} : {};\n\n // Only override preset values if the user explicitly provides them (not empty strings)\n const mergedConfig: OAuth2Config = {\n ...presetConfig,\n ...config,\n // Don't override preset URLs with empty strings\n authorizationUrl: config.authorizationUrl || presetConfig.authorizationUrl || '',\n tokenUrl: config.tokenUrl || presetConfig.tokenUrl || '',\n profileUrl: config.profileUrl || presetConfig.profileUrl,\n extraAuthParams: {\n ...(presetConfig.extraAuthParams || {}),\n ...(config.extraAuthParams || {}),\n },\n };\n\n const profileFetcher = ProfileFetcherFactory.createProfileFetcher(type, mergedConfig);\n\n return new GenericOAuth2Provider(mergedConfig, undefined, undefined, profileFetcher);\n }\n\n static registerPreset(name: string, config: Partial<OAuth2Config>): void {\n OAuth2ProviderFactory.presetConfigs[name] = config;\n }\n\n static getPresetConfig(name: string): Partial<OAuth2Config> | undefined {\n return OAuth2ProviderFactory.presetConfigs[name];\n }\n}\n","import { AuthorizationState } from '../types';\nimport { StorageAdapter, StoredToken, SaveTokenInput, UpdateTokenInput } from './interfaces';\n\nexport class InMemoryStorageAdapter implements StorageAdapter {\n private tokens: Map<string, StoredToken> = new Map();\n private states: Map<string, AuthorizationState> = new Map();\n\n private generateId(): string {\n return Math.random().toString(36).substring(2) + Date.now().toString(36);\n }\n\n // Token operations\n async saveToken(input: SaveTokenInput): Promise<StoredToken> {\n // Check if token with same provider + email exists\n const existingToken = await this.getToken(input.provider, input.email);\n\n if (existingToken) {\n // Replace existing token\n const updatedToken: StoredToken = {\n ...existingToken,\n ...input,\n id: existingToken.id,\n createdAt: existingToken.createdAt,\n updatedAt: new Date(),\n };\n this.tokens.set(existingToken.id, updatedToken);\n return updatedToken;\n }\n\n // Create new token\n const newToken: StoredToken = {\n ...input,\n id: this.generateId(),\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n this.tokens.set(newToken.id, newToken);\n return newToken;\n }\n\n async getToken(provider: string, email: string): Promise<StoredToken | null> {\n const tokens = Array.from(this.tokens.values());\n return tokens.find((t) => t.provider === provider && t.email === email) || null;\n }\n\n async getTokenById(id: string): Promise<StoredToken | null> {\n return this.tokens.get(id) || null;\n }\n\n async getTokensByUserId(userId: string): Promise<StoredToken[]> {\n return Array.from(this.tokens.values()).filter((t) => t.userId === userId);\n }\n\n async getTokensByEmail(email: string): Promise<StoredToken[]> {\n return Array.from(this.tokens.values()).filter((t) => t.email === email);\n }\n\n async getTokensByProvider(provider: string): Promise<StoredToken[]> {\n return Array.from(this.tokens.values()).filter((t) => t.provider === provider);\n }\n\n async getAccounts(userId: string, provider: string): Promise<StoredToken[]> {\n return Array.from(this.tokens.values()).filter(\n (t) => t.userId === userId && t.provider === provider,\n );\n }\n\n async getTokensForEmail(\n userId: string,\n provider: string,\n email: string,\n ): Promise<StoredToken | null> {\n // Since provider + email is unique, we can use getToken directly\n const token = await this.getToken(provider, email);\n // Verify it belongs to the requested userId\n if (token && token.userId === userId) {\n return token;\n }\n return null;\n }\n\n async getTokens(userId: string, provider: string): Promise<StoredToken[]> {\n return Array.from(this.tokens.values()).filter(\n (t) => t.userId === userId && t.provider === provider,\n );\n }\n\n async updateToken(id: string, update: UpdateTokenInput): Promise<StoredToken | null> {\n const token = this.tokens.get(id);\n if (!token) return null;\n\n const updatedToken: StoredToken = {\n ...token,\n ...(update.token && { token: update.token }),\n ...(update.metadata && { metadata: { ...token.metadata, ...update.metadata } }),\n updatedAt: new Date(),\n };\n this.tokens.set(id, updatedToken);\n return updatedToken;\n }\n\n async deleteToken(id: string): Promise<boolean> {\n return this.tokens.delete(id);\n }\n\n async deleteTokenByProviderEmail(provider: string, email: string): Promise<boolean> {\n const token = await this.getToken(provider, email);\n if (!token) return false;\n return this.tokens.delete(token.id);\n }\n\n async deleteExpiredTokens(): Promise<number> {\n const now = new Date().getTime();\n const expiredTokens = Array.from(this.tokens.entries())\n .filter(([, token]) => {\n const expiresAt = new Date(token.token.expiresAt).getTime();\n return expiresAt < now;\n })\n .map(([id]) => id);\n\n expiredTokens.forEach((id) => this.tokens.delete(id));\n return expiredTokens.length;\n }\n\n // Authorization state operations\n async saveAuthorizationState(\n state: Omit<AuthorizationState, 'createdAt'>,\n ): Promise<AuthorizationState> {\n const newState: AuthorizationState = {\n ...state,\n createdAt: new Date(Date.now()),\n };\n this.states.set(state.state, newState);\n return newState;\n }\n\n async getAuthorizationState(state: string): Promise<AuthorizationState | null> {\n return this.states.get(state) || null;\n }\n\n async deleteAuthorizationState(state: string): Promise<boolean> {\n return this.states.delete(state);\n }\n\n async cleanupExpiredStates(): Promise<number> {\n const now = new Date().getTime();\n const maxAge = 10 * 60 * 1000; // 10 minutes\n\n const expiredStates = Array.from(this.states.entries())\n .filter(([, state]) => {\n const stateAge = now - state.createdAt.getTime();\n return stateAge > maxAge;\n })\n .map(([key]) => key);\n\n expiredStates.forEach((key) => this.states.delete(key));\n return expiredStates.length;\n }\n}\n","import { createHash, randomBytes } from 'crypto';\n\nexport const createCodeVerifier = () =>\n randomBytes(32)\n .toString('base64')\n .replace(/[^a-zA-Z0-9]/g, '')\n .substring(0, 128);\n\nexport const createCodeChallenge = (verifier: string): string => {\n return createHash('sha256').update(verifier).digest('base64url');\n};\n\nexport const generateState = (): string => {\n return randomBytes(16).toString('base64url');\n};\n","import { OAuth2Config, OAuth2Token, AuthorizationState } from '../types';\nimport { OAuth2ProviderFactory, ProviderType } from '../providers/provider.factory';\nimport { StorageAdapter, StoredToken } from '../storage/interfaces';\nimport { InMemoryStorageAdapter } from '../storage/memory.adapter';\nimport { ProviderFactory } from '../providers/provider.factory';\nimport { createCodeVerifier, createCodeChallenge, generateState } from '../utils/crypto';\nimport { OAuth2Provider } from '../providers/base.provider';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport interface OAuth2Options {\n storage?: StorageAdapter;\n providers?: Record<string, OAuth2Config>;\n}\n\nexport interface AuthorizationOptions {\n provider: string;\n userId: string;\n email: string;\n scopes?: string[];\n metadata?: Record<string, any>;\n usePKCE?: boolean;\n}\n\nexport interface TokenOptions {\n autoRefresh?: boolean;\n refreshBuffer?: number; // minutes before expiry to refresh\n expirationBuffer?: number; // seconds before expiry to consider expired\n defaultExpiresIn?: number; // default expiration in seconds\n}\n\nexport interface CallbackResult {\n token: StoredToken;\n profile?: UserProfile;\n}\n\nexport class OAuth2Client {\n private storage: StorageAdapter;\n private providerFactory: ProviderFactory;\n private providers: Map<string, OAuth2Provider> = new Map();\n private providerConfigs: Map<string, OAuth2Config> = new Map();\n private now: () => number;\n\n constructor(options: OAuth2Options = {}) {\n this.storage = options.storage || new InMemoryStorageAdapter();\n this.providerFactory = new OAuth2ProviderFactory();\n this.now = Date.now;\n\n // Register predefined providers\n if (options.providers) {\n Object.entries(options.providers).forEach(([name, config]) => {\n this.registerProvider(name, config);\n });\n }\n }\n\n /**\n * Register a provider configuration\n */\n registerProvider(name: string, config: OAuth2Config): void {\n this.providerConfigs.set(name, config);\n\n // Determine provider type based on configuration\n const providerType = this.detectProviderType(name, config);\n const provider = this.providerFactory.createProvider(providerType, config);\n this.providers.set(name, provider);\n }\n\n /**\n * Start OAuth2 authorization flow\n */\n async authorize(options: AuthorizationOptions): Promise<{ url: string; state: string }> {\n const provider = this.providers.get(options.provider);\n if (!provider) throw new Error(`Provider ${options.provider} not found`);\n\n const state = generateState();\n let authUrl: string;\n let authState: Omit<AuthorizationState, 'createdAt'>;\n\n const requiresPKCE = this.providerConfigs.get(options.provider)?.usePKCE || options.usePKCE;\n\n if (requiresPKCE) {\n const codeVerifier = createCodeVerifier();\n const codeChallenge = createCodeChallenge(codeVerifier);\n authUrl = provider.generateAuthorizationUrl(state, codeChallenge);\n authState = {\n state,\n codeVerifier,\n config: this.providerConfigs.get(options.provider)!,\n metadata: {\n ...options.metadata,\n userId: options.userId,\n email: options.email,\n provider: options.provider,\n },\n };\n } else {\n authUrl = provider.generateAuthorizationUrl(state);\n authState = {\n state,\n config: this.providerConfigs.get(options.provider)!,\n metadata: {\n ...options.metadata,\n userId: options.userId,\n email: options.email,\n provider: options.provider,\n },\n };\n }\n\n await this.storage.saveAuthorizationState(authState);\n return { url: authUrl, state };\n }\n\n /**\n * Handle OAuth2 callback\n */\n async handleCallback(code: string, state: string): Promise<CallbackResult> {\n const authState = await this.storage.getAuthorizationState(state);\n if (!authState) throw new Error('Invalid or expired state');\n\n const provider = authState.metadata?.provider;\n if (!provider) throw new Error('Provider not found in authorization state');\n\n const providerInstance = this.providers.get(provider);\n if (!providerInstance) throw new Error(`Provider ${provider} not found`);\n\n // Exchange code for tokens\n const tokens = await providerInstance.exchangeCodeForToken(code, authState.codeVerifier);\n\n // Extract user data from metadata\n const userId = authState.metadata?.userId;\n const email = authState.metadata?.email;\n\n if (!userId || !email) {\n throw new Error('User ID and email are required in authorization state');\n }\n\n // Fetch profile if available\n let profile: UserProfile | undefined;\n if (providerInstance.hasProfileFetcher()) {\n try {\n profile = await providerInstance.fetchProfile(tokens.accessToken);\n } catch (error) {\n console.warn('Failed to fetch user profile:', error);\n }\n }\n\n // Save token\n const savedToken = await this.storage.saveToken({\n provider,\n userId,\n email,\n token: tokens,\n metadata: {\n ...authState.metadata,\n profileFetched: !!profile,\n },\n });\n\n // Clean up authorization state\n await this.storage.deleteAuthorizationState(state);\n\n // Call onSuccess callback if defined\n const config = this.providerConfigs.get(provider);\n if (config?.onSuccess) {\n await config.onSuccess(userId, tokens);\n }\n\n return {\n token: savedToken,\n profile,\n };\n }\n\n /**\n * Get a valid access token (auto-refresh if needed)\n */\n async getAccessToken(\n provider: string,\n email: string,\n options: TokenOptions = {},\n ): Promise<string> {\n const token = await this.getValidToken(provider, email, options);\n return token.accessToken;\n }\n\n /**\n * Get a valid token (auto-refresh if needed)\n */\n async getValidToken(\n provider: string,\n email: string,\n options: TokenOptions = {},\n ): Promise<OAuth2Token> {\n const storedToken = await this.storage.getToken(provider, email);\n if (!storedToken) {\n throw new Error(`No token found for provider ${provider} and email ${email}`);\n }\n\n const needsRefresh =\n options.autoRefresh !== false && this.isTokenExpired(storedToken.token, options);\n\n if (!needsRefresh) {\n return storedToken.token;\n }\n\n // Refresh the token\n if (!storedToken.token.refreshToken) {\n throw new Error('Token expired and no refresh token available');\n }\n\n const providerInstance = this.providers.get(provider);\n if (!providerInstance) throw new Error(`Provider ${provider} not found`);\n\n const newToken = await providerInstance.refreshToken(storedToken.token.refreshToken);\n await this.storage.updateToken(storedToken.id, { token: newToken });\n\n return newToken;\n }\n\n /**\n * Get all tokens for a user\n */\n async getTokensByUserId(userId: string): Promise<StoredToken[]> {\n return this.storage.getTokensByUserId(userId);\n }\n\n /**\n * Get all tokens for an email\n */\n async getTokensByEmail(email: string): Promise<StoredToken[]> {\n return this.storage.getTokensByEmail(email);\n }\n\n /**\n * Delete a token\n */\n async deleteToken(provider: string, email: string): Promise<boolean> {\n return this.storage.deleteTokenByProviderEmail(provider, email);\n }\n\n /**\n * Delete all expired tokens\n */\n async cleanupExpiredTokens(): Promise<number> {\n return this.storage.deleteExpiredTokens();\n }\n\n /**\n * Clean up expired authorization states\n */\n async cleanupExpiredStates(): Promise<number> {\n return this.storage.cleanupExpiredStates();\n }\n\n // Helper methods\n private isTokenExpired(token: OAuth2Token, options: TokenOptions = {}): boolean {\n const { expirationBuffer = 300 } = options;\n\n if (token.createdAt && token.expiresIn !== undefined) {\n const expiresAt = token.createdAt + token.expiresIn * 1000;\n const effectiveNow = this.now() + expirationBuffer * 1000;\n return effectiveNow >= expiresAt;\n }\n\n const expiresAt = new Date(token.expiresAt).getTime();\n const effectiveNow = this.now() + expirationBuffer * 1000;\n return effectiveNow >= expiresAt;\n }\n\n private detectProviderType(name: string, config: OAuth2Config): ProviderType {\n // Try to detect based on the authorization URL\n const authUrl = config.authorizationUrl.toLowerCase();\n\n // Check for known providers that have specific implementations\n if (authUrl.includes('accounts.google.com')) return 'google';\n if (authUrl.includes('github.com')) return 'github';\n if (authUrl.includes('facebook.com')) return 'facebook';\n if (authUrl.includes('microsoft.com') || authUrl.includes('microsoftonline.com')) {\n // Check if it's specifically for Outlook\n if (\n name.toLowerCase().includes('outlook') ||\n config.scopes?.some((s) => s.includes('outlook'))\n ) {\n return 'outlook';\n }\n return 'microsoft';\n }\n\n // Default to generic provider for all others\n return 'generic';\n }\n}\n","import { sealData, unsealData } from 'iron-session';\n\nexport const seal = <T>(d: T, key: string) => sealData(d, { password: key });\nexport const unseal = <T>(s: string, key: string) => unsealData<T>(s, { password: key });\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dainprotocol/oauth2-token-manager",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "A scalable OAuth2 token management library with multi-system support",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"oauth2",
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@changesets/cli": "^2.29.4",
|
|
39
|
+
"@dainprotocol/oauth2-storage-drizzle": "link:../../../Library/pnpm/global/5/node_modules/@dainprotocol/oauth2-storage-drizzle",
|
|
39
40
|
"@dainprotocol/oauth2-token-manager": "link:../../../Library/pnpm/global/5/node_modules/@dainprotocol/oauth2-token-manager",
|
|
40
41
|
"@types/node": "^22.15.29",
|
|
41
42
|
"crypto": "^1.0.1",
|