@blureffect/oauth2-token-manager
Version:
A scalable OAuth2 token management library with multi-system support
848 lines (826 loc) • 39.1 kB
text/typescript
interface OAuth2Config {
clientId: string;
clientSecret?: string;
authorizationUrl: string;
tokenUrl: string;
redirectUri: string;
scopes: string[];
usePKCE?: boolean;
pkce?: boolean;
includeClientSecretOnRefresh?: boolean;
additionalParams?: Record<string, string>;
extraAuthParams?: Record<string, string>;
responseRootKey?: string;
profileUrl?: string;
userInfoUrl?: string;
onSuccess?: (userId: string, tokens: OAuth2Token) => Promise<void>;
}
interface OAuth2Token {
accessToken: string;
refreshToken?: string;
expiresAt: Date;
expiresIn?: number;
tokenType: string;
scope?: string;
createdAt?: number;
raw?: Record<string, any>;
}
interface User {
id: string;
systemId: string;
metadata?: Record<string, any>;
createdAt: Date;
updatedAt: Date;
}
interface UserToken {
id: string;
userId: string;
systemId: string;
scopeId: string;
provider: string;
email?: string;
token: OAuth2Token;
createdAt: Date;
updatedAt: Date;
}
interface System {
id: string;
name: string;
description?: string;
scopes: Scope[];
metadata?: Record<string, any>;
createdAt: Date;
updatedAt: Date;
}
interface Scope {
id: string;
systemId: string;
name: string;
type: 'authentication' | 'access' | 'custom';
permissions: string[];
isolated: boolean;
metadata?: Record<string, any>;
}
interface AuthorizationState {
state: string;
codeVerifier?: string;
config: OAuth2Config;
timestamp: Date;
metadata?: Record<string, any>;
}
interface CreateUserInput {
systemId: string;
metadata?: Record<string, any>;
email?: string;
externalId?: string;
}
interface UserTokenWithProfile {
id: string;
userId: string;
systemId: string;
scopeId: string;
provider: string;
token: {
accessToken: string;
refreshToken?: string;
expiresAt: Date;
expiresIn?: number;
tokenType: string;
scope?: string;
createdAt?: number;
raw?: Record<string, any>;
};
createdAt: Date;
updatedAt: Date;
user: {
email?: string;
name?: string;
externalId?: string;
metadata?: Record<string, any>;
};
}
interface ProfileBasedTokenOptions {
checkProfileEmail?: boolean;
replaceConflictingTokens?: boolean;
mergeUserData?: boolean;
}
interface StorageAdapter {
createSystem(system: Omit<System, 'id' | 'createdAt' | 'updatedAt'>): Promise<System>;
getSystem(id: string): Promise<System | null>;
updateSystem(id: string, system: Partial<System>): Promise<System>;
deleteSystem(id: string): Promise<void>;
listSystems(): Promise<System[]>;
createScope(scope: Omit<Scope, 'id'>): Promise<Scope>;
getScope(id: string): Promise<Scope | null>;
getScopesBySystem(systemId: string): Promise<Scope[]>;
updateScope(id: string, scope: Partial<Scope>): Promise<Scope>;
deleteScope(id: string): Promise<void>;
createUser(user: Omit<User, 'id' | 'createdAt' | 'updatedAt'>): Promise<User>;
getOrCreateUser(input: CreateUserInput): Promise<User>;
findUserByEmail(systemId: string, email: string): Promise<User | null>;
findUserByExternalId(systemId: string, externalId: string): Promise<User | null>;
getUser(id: string): Promise<User | null>;
getUsersBySystem(systemId: string): Promise<User[]>;
updateUser(id: string, user: Partial<User>): Promise<User>;
deleteUser(id: string): Promise<void>;
saveToken(token: Omit<UserToken, 'id' | 'createdAt' | 'updatedAt'>): Promise<UserToken>;
saveTokenWithEmailValidation(userId: string, systemId: string, scopeId: string, provider: string, email: string, token: Omit<UserToken, 'id' | 'createdAt' | 'updatedAt'>): Promise<UserToken>;
getTokensByUser(userId: string): Promise<UserToken[]>;
getTokensByUserAndScope(userId: string, scopeId: string): Promise<UserToken[]>;
getTokensByUserAndProvider(userId: string, provider: string): Promise<UserToken[]>;
getTokensByUserScopeProvider(userId: string, scopeId: string, provider: string): Promise<UserToken[]>;
getTokensByScope(systemId: string, scopeId: string): Promise<UserToken[]>;
getTokensByProvider(systemId: string, provider: string): Promise<UserToken[]>;
getTokensBySystem(systemId: string): Promise<UserToken[]>;
findTokensByEmail(email: string, systemId: string): Promise<UserToken[]>;
findTokensByEmailAndScope(email: string, systemId: string, scopeId: string): Promise<UserToken[]>;
findTokensByEmailAndProvider(email: string, systemId: string, provider: string): Promise<UserToken[]>;
findTokenByEmailScopeProvider(email: string, systemId: string, scopeId: string, provider: string): Promise<UserToken | null>;
getTokensByUserWithProfile(userId: string): Promise<UserTokenWithProfile[]>;
getTokensByUserAndScopeWithProfile(userId: string, scopeId: string): Promise<UserTokenWithProfile[]>;
getTokensByUserAndProviderWithProfile(userId: string, provider: string): Promise<UserTokenWithProfile[]>;
getTokensByUserScopeProviderWithProfile(userId: string, scopeId: string, provider: string): Promise<UserTokenWithProfile[]>;
getTokensByScopeWithProfile(systemId: string, scopeId: string): Promise<UserTokenWithProfile[]>;
getTokensBySystemWithProfile(systemId: string): Promise<UserTokenWithProfile[]>;
findTokensByEmailInUserScopeProvider(userId: string, scopeId: string, provider: string, email: string): Promise<UserToken[]>;
hasTokenWithEmailInUserScopeProvider(userId: string, scopeId: string, provider: string, email: string): Promise<boolean>;
replaceTokensByEmailInUserScopeProvider(userId: string, scopeId: string, provider: string, email: string, newToken: Omit<UserToken, 'id' | 'createdAt' | 'updatedAt'>): Promise<UserToken>;
getTokenById(id: string): Promise<UserToken | null>;
updateToken(id: string, token: Partial<UserToken>): Promise<UserToken>;
deleteToken(id: string): Promise<void>;
deleteTokensByUser(userId: string): Promise<void>;
deleteTokensByUserAndScope(userId: string, scopeId: string): Promise<void>;
deleteTokensByUserAndProvider(userId: string, provider: string): Promise<void>;
saveAuthorizationState(state: AuthorizationState): Promise<void>;
getAuthorizationState(state: string): Promise<AuthorizationState | null>;
deleteAuthorizationState(state: string): Promise<void>;
cleanupExpiredStates(expiryMs: number): Promise<void>;
}
interface UserProfile {
email: string;
name?: string;
id?: string;
avatar?: string;
username?: string;
raw?: Record<string, any>;
}
interface ProfileFetcher {
/**
* Fetch user profile using an access token
* @param accessToken The OAuth access token
* @returns Promise resolving to user profile information
*/
fetchProfile(accessToken: string): Promise<UserProfile>;
/**
* Get the profile endpoint URL for this provider
* @returns The URL used to fetch user profiles
*/
getProfileEndpoint(): string;
}
interface AuthorizationUrlStrategy {
generateAuthorizationUrl(config: OAuth2Config, state: string, codeChallenge?: string): string;
}
interface TokenExchangeStrategy {
exchangeCodeForToken(code: string, config: OAuth2Config, codeVerifier?: string): Promise<OAuth2Token>;
refreshToken(refreshToken: string, config: OAuth2Config): Promise<OAuth2Token>;
}
declare abstract class BaseProfileFetcher {
protected profileEndpoint: string;
constructor(profileEndpoint: string);
/**
* Fetch user profile information from the OAuth provider
* @param accessToken The OAuth access token
* @returns Promise resolving to standardized user profile
*/
fetchUserInfo(accessToken: string): Promise<UserProfile>;
/**
* Map the raw API response to our standardized UserProfile structure
* Override this method to customize mapping for different providers
*/
protected abstract mapToUserProfile(rawData: any): UserProfile;
/**
* Get additional headers if needed for the profile request
* Override this method to add provider-specific headers
*/
protected getAdditionalHeaders(): Record<string, string>;
/**
* Get the profile endpoint URL
*/
getEndpoint(): string;
}
declare abstract class OAuth2Provider {
protected config: OAuth2Config;
protected authUrlStrategy: AuthorizationUrlStrategy;
protected tokenStrategy: TokenExchangeStrategy;
protected profileFetcher?: BaseProfileFetcher;
constructor(config: OAuth2Config, authUrlStrategy?: AuthorizationUrlStrategy, tokenStrategy?: TokenExchangeStrategy, profileFetcher?: BaseProfileFetcher);
protected abstract createAuthorizationUrlStrategy(): AuthorizationUrlStrategy;
protected abstract createTokenExchangeStrategy(): TokenExchangeStrategy;
fetchProfile(accessToken: string): Promise<UserProfile>;
getProfileEndpoint(): string;
setProfileFetcher(profileFetcher: BaseProfileFetcher): void;
hasProfileFetcher(): boolean;
generateAuthorizationUrl(state: string, codeChallenge?: string): string;
exchangeCodeForToken(code: string, codeVerifier?: string): Promise<OAuth2Token>;
refreshToken(refreshToken: string): Promise<OAuth2Token>;
}
interface OAuth2GranularOperations {
createUserInSystem(systemId: string, options: UserCreationOptions): Promise<User>;
getOrCreateUserInSystem(systemId: string, options: UserCreationOptions): Promise<User>;
getUserById(userId: string): Promise<User | null>;
findUserByEmailInSystem(systemId: string, email: string): Promise<User | null>;
findUserByExternalIdInSystem(systemId: string, externalId: string): Promise<User | null>;
getUsersBySystem(systemId: string): Promise<User[]>;
saveTokenForUser(userId: string, systemId: string, scopeId: string, provider: string, email: string, token: OAuth2Token): Promise<UserToken>;
getTokensByUser(userId: string): Promise<UserToken[]>;
getTokensByUserAndScope(userId: string, scopeId: string): Promise<UserToken[]>;
getTokensByUserAndProvider(userId: string, provider: string): Promise<UserToken[]>;
getTokensByUserScopeProvider(userId: string, scopeId: string, provider: string): Promise<UserToken[]>;
getTokensByScope(systemId: string, scopeId: string): Promise<UserToken[]>;
getTokensByProvider(systemId: string, provider: string): Promise<UserToken[]>;
getTokensBySystem(systemId: string): Promise<UserToken[]>;
findTokensByEmail(email: string, systemId: string): Promise<UserToken[]>;
findTokensByEmailAndScope(email: string, systemId: string, scopeId: string): Promise<UserToken[]>;
findTokensByEmailAndProvider(email: string, systemId: string, provider: string): Promise<UserToken[]>;
findTokenByEmailScopeProvider(email: string, systemId: string, scopeId: string, provider: string): Promise<UserToken | null>;
getValidTokenByEmail(email: string, systemId: string, scopeId: string, provider: string, options?: TokenOptions): Promise<OAuth2Token>;
getAccessTokenByEmail(email: string, systemId: string, scopeId: string, provider: string, options?: TokenOptions): Promise<string>;
withValidTokenByEmail<T>(email: string, systemId: string, scopeId: string, provider: string, callback: (accessToken: string) => Promise<T>, options?: TokenOptions): Promise<T>;
getAllValidTokensForUser(userId: string, options?: TokenOptions): Promise<{
provider: string;
scopeId: string;
token: OAuth2Token;
userToken: UserToken;
}[]>;
getAllValidTokensForUserScopeProvider(userId: string, scopeId: string, provider: string, options?: TokenOptions): Promise<{
email: string;
token: OAuth2Token;
userToken: UserToken;
}[]>;
getAllValidTokensForEmail(email: string, systemId: string, options?: TokenOptions): Promise<{
provider: string;
scopeId: string;
token: OAuth2Token;
userToken: UserToken;
}[]>;
hasTokensForUserScopeProvider(userId: string, scopeId: string, provider: string): Promise<boolean>;
hasTokenByEmail(email: string, systemId: string, scopeId: string, provider: string): Promise<boolean>;
hasTokenWithEmailInUserScopeProvider(userId: string, scopeId: string, provider: string, email: string): Promise<boolean>;
replaceTokensByEmailInUserScopeProvider(userId: string, scopeId: string, provider: string, email: string, token: OAuth2Token): Promise<UserToken>;
deleteTokensByUser(userId: string): Promise<void>;
deleteTokensByUserAndScope(userId: string, scopeId: string): Promise<void>;
deleteTokensByUserAndProvider(userId: string, provider: string): Promise<void>;
deleteTokensByUserScopeProvider(userId: string, scopeId: string, provider: string): Promise<void>;
deleteTokenByEmail(email: string, systemId: string, scopeId: string, provider: string): Promise<void>;
createSystem(name: string, description?: string): Promise<System>;
getSystem(systemId: string): Promise<System | null>;
createScopeInSystem(systemId: string, name: string, options?: {
type?: 'authentication' | 'access' | 'custom';
permissions?: string[];
isolated?: boolean;
}): Promise<Scope>;
getScope(scopeId: string): Promise<Scope | null>;
getScopesBySystem(systemId: string): Promise<Scope[]>;
}
declare class OAuth2GranularClient implements OAuth2GranularOperations {
private storage;
private providers;
private now;
constructor(storage: StorageAdapter, providers: Map<string, OAuth2Provider>, now?: () => number);
createUserInSystem(systemId: string, options?: UserCreationOptions): Promise<User>;
getOrCreateUserInSystem(systemId: string, options?: UserCreationOptions): Promise<User>;
getUserById(userId: string): Promise<User | null>;
findUserByEmailInSystem(systemId: string, email: string): Promise<User | null>;
findUserByExternalIdInSystem(systemId: string, externalId: string): Promise<User | null>;
getUsersBySystem(systemId: string): Promise<User[]>;
saveTokenForUser(userId: string, systemId: string, scopeId: string, provider: string, email: string, token: OAuth2Token): Promise<UserToken>;
getTokensByUser(userId: string): Promise<UserToken[]>;
getTokensByUserAndScope(userId: string, scopeId: string): Promise<UserToken[]>;
getTokensByUserAndProvider(userId: string, provider: string): Promise<UserToken[]>;
getTokensByUserScopeProvider(userId: string, scopeId: string, provider: string): Promise<UserToken[]>;
getTokensByScope(systemId: string, scopeId: string): Promise<UserToken[]>;
getTokensByProvider(systemId: string, provider: string): Promise<UserToken[]>;
getTokensBySystem(systemId: string): Promise<UserToken[]>;
findTokensByEmail(email: string, systemId: string): Promise<UserToken[]>;
findTokensByEmailAndScope(email: string, systemId: string, scopeId: string): Promise<UserToken[]>;
findTokensByEmailAndProvider(email: string, systemId: string, provider: string): Promise<UserToken[]>;
findTokenByEmailScopeProvider(email: string, systemId: string, scopeId: string, provider: string): Promise<UserToken | null>;
getValidTokenByEmail(email: string, systemId: string, scopeId: string, provider: string, options?: TokenOptions): Promise<OAuth2Token>;
getAccessTokenByEmail(email: string, systemId: string, scopeId: string, provider: string, options?: TokenOptions): Promise<string>;
getAllValidTokensForUser(userId: string, options?: TokenOptions): Promise<{
provider: string;
scopeId: string;
token: OAuth2Token;
userToken: UserToken;
}[]>;
getAllValidTokensForUserScopeProvider(userId: string, scopeId: string, provider: string, options?: TokenOptions): Promise<{
email: string;
token: OAuth2Token;
userToken: UserToken;
}[]>;
getAllValidTokensForEmail(email: string, systemId: string, options?: TokenOptions): Promise<{
provider: string;
scopeId: string;
token: OAuth2Token;
userToken: UserToken;
}[]>;
withValidTokenByEmail<T>(email: string, systemId: string, scopeId: string, provider: string, callback: (accessToken: string) => Promise<T>, options?: TokenOptions): Promise<T>;
hasTokensForUserScopeProvider(userId: string, scopeId: string, provider: string): Promise<boolean>;
hasTokenByEmail(email: string, systemId: string, scopeId: string, provider: string): Promise<boolean>;
hasTokenWithEmailInUserScopeProvider(userId: string, scopeId: string, provider: string, email: string): Promise<boolean>;
replaceTokensByEmailInUserScopeProvider(userId: string, scopeId: string, provider: string, email: string, token: OAuth2Token): Promise<UserToken>;
deleteTokensByUser(userId: string): Promise<void>;
deleteTokensByUserAndScope(userId: string, scopeId: string): Promise<void>;
deleteTokensByUserAndProvider(userId: string, provider: string): Promise<void>;
deleteTokensByUserScopeProvider(userId: string, scopeId: string, provider: string): Promise<void>;
deleteTokenByEmail(email: string, systemId: string, scopeId: string, provider: string): Promise<void>;
createSystem(name: string, description?: string): Promise<System>;
getSystem(systemId: string): Promise<System | null>;
createScopeInSystem(systemId: string, name: string, options?: {
type?: 'authentication' | 'access' | 'custom';
permissions?: string[];
isolated?: boolean;
}): Promise<Scope>;
getScope(scopeId: string): Promise<Scope | null>;
getScopesBySystem(systemId: string): Promise<Scope[]>;
private isTokenExpired;
}
interface OAuth2Options {
storage?: StorageAdapter;
sealKey?: string;
providers?: Record<string, OAuth2Config>;
}
interface AuthorizationOptions {
provider: string;
scopes?: string[];
metadata?: Record<string, any>;
usePKCE?: boolean;
userId?: string;
}
interface TokenOptions {
autoRefresh?: boolean;
refreshBuffer?: number;
expirationBuffer?: number;
defaultExpiresIn?: number;
}
interface UserCreationOptions {
email?: string;
externalId?: string;
metadata?: Record<string, any>;
}
interface CallbackOptions {
userId?: string;
scopeId?: string;
profileOptions?: ProfileBasedTokenOptions;
}
interface CallbackResult {
userToken: UserToken;
userId: string;
systemId: string;
scopeId: string;
provider: string;
profile?: UserProfile;
}
declare class OAuth2Client {
private storage;
private providerFactory;
private providers;
private providerConfigs;
private now;
private currentSystem?;
private currentUser?;
private defaultScope?;
readonly granular: OAuth2GranularOperations;
constructor(options?: OAuth2Options);
/**
* Quick setup for common use cases
*/
static quickSetup(appName: string, providers: Record<string, OAuth2Config>): Promise<OAuth2Client>;
/**
* Register a provider configuration
*/
registerProvider(name: string, config: OAuth2Config): void;
/**
* Create or select a system to work with
*/
createSystem(name: string, description?: string): Promise<System>;
useSystem(systemId: string): Promise<void>;
/**
* Create a scope within the current system
*/
createScope(name: string, options?: {
type?: 'authentication' | 'access' | 'custom';
permissions?: string[];
isolated?: boolean;
}): Promise<Scope>;
setDefaultScope(scopeId: string): void;
/**
* Create a user (legacy method - always creates new user)
* @deprecated Use getOrCreateUser for better user management
*/
createUser(metadata?: Record<string, any>): Promise<User>;
/**
* Get or create a user (recommended method)
*/
getOrCreateUser(options?: UserCreationOptions): Promise<User>;
/**
* Get or create a user (stateless version for backend APIs)
*/
getOrCreateUserStateless(systemId: string, options?: UserCreationOptions): Promise<User>;
/**
* Start authorization flow for a specific user (stateless backend API method)
*/
authorizeForUser(userId: string, provider: string, options?: {
systemId?: string;
scopeId?: string;
scopes?: string[];
metadata?: Record<string, any>;
usePKCE?: boolean;
}): Promise<{
url: string;
state: string;
}>;
/**
* Complete workflow: get/create user and start authorization (for backend APIs)
*/
createUserAndAuthorize(systemId: string, provider: string, userOptions: UserCreationOptions, authOptions?: {
scopeId?: string;
scopes?: string[];
metadata?: Record<string, any>;
usePKCE?: boolean;
}): Promise<{
user: User;
authUrl: string;
state: string;
}>;
/**
* Find user by email
*/
findUserByEmail(email: string): Promise<User | null>;
/**
* Find user by email (stateless version)
*/
findUserByEmailStateless(systemId: string, email: string): Promise<User | null>;
/**
* Find user by external ID
*/
findUserByExternalId(externalId: string): Promise<User | null>;
/**
* Find user by external ID (stateless version)
*/
findUserByExternalIdStateless(systemId: string, externalId: string): Promise<User | null>;
useUser(userId: string): Promise<void>;
/**
* Start the OAuth authorization flow
*/
authorize(options: AuthorizationOptions): Promise<{
url: string;
state: string;
}>;
/**
* Handle the OAuth callback
*/
handleCallback(code: string, state: string, options?: CallbackOptions): Promise<CallbackResult>;
/**
* Merge user data from OAuth profile
*/
private mergeUserDataFromProfile;
/**
* Fetch user profile for a given provider and user
* Note: If user has multiple tokens for the provider, this will fail.
* Use fetchUserProfileByEmail() for unambiguous profile fetching.
*/
fetchUserProfile(provider: string, userId?: string): Promise<UserProfile>;
/**
* Fetch user profile by email (unambiguous)
*/
fetchUserProfileByEmail(provider: string, email: string, systemId?: string, scopeId?: string): Promise<UserProfile>;
/**
* Replace tokens for users with conflicting email addresses
*/
replaceConflictingTokensByEmail(email: string, provider: string, newUserId: string, newToken: OAuth2Token): Promise<UserToken>;
/**
* Check if a token is expired
*/
isTokenExpired(token: OAuth2Token, options?: TokenOptions): boolean;
/**
* Get a valid access token (auto-refresh if needed)
* Uses current context (user + default scope)
*/
getAccessToken(provider: string, options?: TokenOptions): Promise<string>;
/**
* Get access token by email (unambiguous)
*/
getAccessTokenByEmail(email: string, systemId: string, scopeId: string, provider: string, options?: TokenOptions): Promise<string>;
/**
* Ensure we have a valid token, refreshing if needed
* Uses current context (user + default scope)
*/
ensureValidToken(provider: string, options?: TokenOptions): Promise<OAuth2Token>;
/**
* Execute a callback with a valid access token
* Uses current context (user + default scope)
*/
withValidToken<T>(provider: string, callback: (accessToken: string) => Promise<T>, options?: TokenOptions): Promise<T>;
/**
* Get user token entity (includes all metadata) for specific user
*/
getUserTokenForUser(userId: string, _systemId: string, scopeId: string, provider: string): Promise<UserToken | null>;
/**
* Check if token exists for specific user/provider combination
*/
hasTokenForUser(userId: string, _systemId: string, scopeId: string, provider: string): Promise<boolean>;
/**
* Revoke tokens for a specific user and provider (stateless method)
* This removes ALL tokens for the user/scope/provider combination
*/
revokeTokensForUser(userId: string, _systemId: string, scopeId: string, provider: string): Promise<void>;
/**
* Revoke tokens for a provider
*/
revokeTokens(provider: string): Promise<void>;
/**
* Get all tokens for the current user
*/
getUserTokens(): Promise<UserToken[]>;
/**
* Get user information by internal user ID
* Returns user data including external ID (in systemId field)
*/
getUserById(userId: string): Promise<User | null>;
/**
* Get user by internal ID with explicit external ID field
* Returns user with both internal ID and external ID clearly labeled
*/
getUserByInternalId(userId: string): Promise<{
id: string;
externalId: string;
user: User;
} | null>;
/**
* Get user information by external ID
* Returns the full user entity including both internal ID and external ID
*/
getUserByExternalId(systemId: string, externalId: string): Promise<User | null>;
/**
* Get tokens for a user by internal user ID with user profile
* Includes external ID in the response
*/
getTokensByInternalUserId(userId: string, options?: {
includeProfile?: boolean;
}): Promise<Array<UserToken & {
user?: User;
}>>;
/**
* Get tokens for a user by internal user ID for a specific provider
* Includes external ID in the response
*/
getTokensByInternalUserIdAndProvider(userId: string, provider: string): Promise<Array<UserToken & {
externalId?: string;
}>>;
/**
* Get tokens for a user by internal user ID for a specific scope
* Includes external ID in the response
*/
getTokensByInternalUserIdAndScope(userId: string, scopeId: string): Promise<Array<UserToken & {
externalId?: string;
}>>;
/**
* Get a specific token by internal user ID, scope, and provider
* Includes full user information including external ID
*/
getTokenByInternalUserId(userId: string, scopeId: string, provider: string): Promise<(UserToken & {
user: User;
}) | null>;
/**
* Get all valid tokens for a user by internal ID with auto-refresh
* Includes external ID in the response
*/
getAllValidTokensByInternalUserId(userId: string, options?: TokenOptions): Promise<Array<{
provider: string;
scopeId: string;
token: OAuth2Token;
userToken: UserToken;
externalId?: string;
}>>;
/**
* Get all tokens for a user by ID with validation and auto-refresh
* @deprecated Use getAllValidTokensByInternalUserId instead
*/
getAllValidTokensForUser(userId: string, options?: TokenOptions): Promise<{
provider: string;
scopeId: string;
token: OAuth2Token;
userToken: UserToken;
}[]>;
/**
* Get all valid tokens for a user by email with validation and auto-refresh
*/
getAllValidTokensForEmail(email: string, systemId?: string, options?: TokenOptions): Promise<{
provider: string;
scopeId: string;
token: OAuth2Token;
userToken: UserToken;
}[]>;
/**
* Get specific token for an email
*/
getTokenForEmail(email: string, provider: string, systemId?: string, scopeId?: string): Promise<UserToken | null>;
/**
* Get valid token for an email (with auto-refresh)
*/
getValidTokenForEmail(email: string, provider: string, systemId?: string, scopeId?: string, options?: TokenOptions): Promise<OAuth2Token>;
/**
* Get valid access token for an email (with auto-refresh)
*/
getAccessTokenForEmail(email: string, provider: string, systemId?: string, scopeId?: string, options?: TokenOptions): Promise<string>;
/**
* Execute a callback with a valid access token for an email
*/
withValidTokenForEmail<T>(email: string, provider: string, callback: (accessToken: string) => Promise<T>, systemId?: string, scopeId?: string, options?: TokenOptions): Promise<T>;
/**
* Check if token exists for specific email/provider combination
*/
hasTokenForEmail(email: string, provider: string, systemId?: string, scopeId?: string): Promise<boolean>;
/**
* Revoke tokens for a specific email and provider
*/
revokeTokensForEmail(email: string, provider: string, systemId?: string, scopeId?: string): Promise<void>;
/**
* Get tokens by scope (stateless method)
*/
getTokensByScope(systemId?: string, scopeId?: string): Promise<UserToken[]>;
/**
* Find token by email and scope
*/
findTokenByEmailAndScope(email: string, provider: string, systemId?: string, scopeId?: string): Promise<UserToken | null>;
/**
* Find all tokens by email and scope
*/
findAllTokensByEmailAndScope(email: string, provider: string, systemId?: string, scopeId?: string): Promise<UserToken[]>;
private detectProviderType;
/**
* Clean up expired authorization states
*/
cleanup(expiryMs?: number): Promise<void>;
/**
* Get all valid tokens for a user with OAuth provider profile information (RECOMMENDED FOR UI)
* This fetches the actual email/profile from each OAuth provider using the access token
*/
getAllValidTokensWithProviderProfiles(userId: string, options?: TokenOptions): Promise<{
provider: string;
scopeId: string;
token: OAuth2Token;
userToken: UserToken;
profile?: UserProfile;
}[]>;
/**
* Get all valid tokens for a user and scope with OAuth provider profile information
*/
getAllValidTokensForUserAndScopeWithProviderProfiles(userId: string, scopeId: string, options?: TokenOptions): Promise<{
provider: string;
token: OAuth2Token;
userToken: UserToken;
profile?: UserProfile;
}[]>;
/**
* Get all valid tokens for a user and provider with OAuth provider profile information
*/
getAllValidTokensForUserAndProviderWithProviderProfiles(userId: string, provider: string, options?: TokenOptions): Promise<{
scopeId: string;
token: OAuth2Token;
userToken: UserToken;
profile?: UserProfile;
}[]>;
/**
* Get OAuth provider profile for a specific token
* This fetches the actual email/profile from the OAuth provider using the access token
*/
getTokenProfile(token: OAuth2Token, provider: string): Promise<UserProfile | null>;
/**
* Get OAuth provider profile for a specific user token
* This fetches the actual email/profile from the OAuth provider using the access token
*/
getUserTokenProfile(userToken: UserToken): Promise<UserProfile | null>;
}
declare class InMemoryStorageAdapter implements StorageAdapter {
private systems;
private scopes;
private users;
private tokens;
private states;
private generateId;
createSystem(system: Omit<System, 'id' | 'createdAt' | 'updatedAt'>): Promise<System>;
getSystem(id: string): Promise<System | null>;
updateSystem(id: string, updates: Partial<System>): Promise<System>;
deleteSystem(id: string): Promise<void>;
listSystems(): Promise<System[]>;
createScope(scope: Omit<Scope, 'id'>): Promise<Scope>;
getScope(id: string): Promise<Scope | null>;
getScopesBySystem(systemId: string): Promise<Scope[]>;
updateScope(id: string, updates: Partial<Scope>): Promise<Scope>;
deleteScope(id: string): Promise<void>;
createUser(user: Omit<User, 'id' | 'createdAt' | 'updatedAt'>): Promise<User>;
getOrCreateUser(input: CreateUserInput): Promise<User>;
findUserByEmail(systemId: string, email: string): Promise<User | null>;
findUserByExternalId(systemId: string, externalId: string): Promise<User | null>;
getUser(id: string): Promise<User | null>;
getUsersBySystem(systemId: string): Promise<User[]>;
updateUser(id: string, updates: Partial<User>): Promise<User>;
deleteUser(id: string): Promise<void>;
saveToken(token: Omit<UserToken, 'id' | 'createdAt' | 'updatedAt'>): Promise<UserToken>;
saveTokenWithEmailValidation(userId: string, systemId: string, scopeId: string, provider: string, email: string, token: Omit<UserToken, 'id' | 'createdAt' | 'updatedAt'>): Promise<UserToken>;
getTokensByUser(userId: string): Promise<UserToken[]>;
getTokensByUserAndScope(userId: string, scopeId: string): Promise<UserToken[]>;
getTokensByUserAndProvider(userId: string, provider: string): Promise<UserToken[]>;
getTokensByUserScopeProvider(userId: string, scopeId: string, provider: string): Promise<UserToken[]>;
getTokensByScope(systemId: string, scopeId: string): Promise<UserToken[]>;
getTokensByProvider(systemId: string, provider: string): Promise<UserToken[]>;
getTokensBySystem(systemId: string): Promise<UserToken[]>;
findTokensByEmail(email: string, systemId: string): Promise<UserToken[]>;
findTokensByEmailAndScope(email: string, systemId: string, scopeId: string): Promise<UserToken[]>;
findTokensByEmailAndProvider(email: string, systemId: string, provider: string): Promise<UserToken[]>;
findTokenByEmailScopeProvider(email: string, systemId: string, scopeId: string, provider: string): Promise<UserToken | null>;
findTokensByEmailInUserScopeProvider(userId: string, scopeId: string, provider: string, email: string): Promise<UserToken[]>;
hasTokenWithEmailInUserScopeProvider(userId: string, scopeId: string, provider: string, email: string): Promise<boolean>;
replaceTokensByEmailInUserScopeProvider(userId: string, scopeId: string, provider: string, email: string, newToken: Omit<UserToken, 'id' | 'createdAt' | 'updatedAt'>): Promise<UserToken>;
getTokenById(id: string): Promise<UserToken | null>;
updateToken(id: string, updates: Partial<UserToken>): Promise<UserToken>;
deleteToken(id: string): Promise<void>;
deleteTokensByUser(userId: string): Promise<void>;
deleteTokensByUserAndScope(userId: string, scopeId: string): Promise<void>;
deleteTokensByUserAndProvider(userId: string, provider: string): Promise<void>;
saveAuthorizationState(state: AuthorizationState): Promise<void>;
getAuthorizationState(state: string): Promise<AuthorizationState | null>;
deleteAuthorizationState(state: string): Promise<void>;
cleanupExpiredStates(expiryMs: number): Promise<void>;
getTokensByUserWithProfile(userId: string): Promise<UserTokenWithProfile[]>;
getTokensByUserAndScopeWithProfile(userId: string, scopeId: string): Promise<UserTokenWithProfile[]>;
getTokensByUserAndProviderWithProfile(userId: string, provider: string): Promise<UserTokenWithProfile[]>;
getTokensByUserScopeProviderWithProfile(userId: string, scopeId: string, provider: string): Promise<UserTokenWithProfile[]>;
getTokensByScopeWithProfile(systemId: string, scopeId: string): Promise<UserTokenWithProfile[]>;
getTokensBySystemWithProfile(systemId: string): Promise<UserTokenWithProfile[]>;
}
type ProviderType = 'google' | 'github' | 'microsoft' | 'outlook' | 'facebook' | 'generic';
interface ProviderFactory {
createProvider(type: ProviderType, config: OAuth2Config): OAuth2Provider;
}
declare class StandardTokenExchangeStrategy implements TokenExchangeStrategy {
protected buildUrlParams(params: Record<string, string | undefined>): string;
exchangeCodeForToken(code: string, config: OAuth2Config, codeVerifier?: string): Promise<OAuth2Token>;
refreshToken(refreshToken: string, config: OAuth2Config): Promise<OAuth2Token>;
}
declare class StandardAuthorizationUrlStrategy implements AuthorizationUrlStrategy {
protected buildUrlParams(params: Record<string, string | undefined>): string;
generateAuthorizationUrl(config: OAuth2Config, state: string, codeChallenge?: string): string;
}
declare class GenericOAuth2Provider extends OAuth2Provider {
constructor(config: any, authUrlStrategy?: AuthorizationUrlStrategy, tokenStrategy?: TokenExchangeStrategy, profileFetcher?: BaseProfileFetcher);
protected createAuthorizationUrlStrategy(): AuthorizationUrlStrategy;
protected createTokenExchangeStrategy(): TokenExchangeStrategy;
}
declare class GoogleProfileFetcher extends BaseProfileFetcher {
constructor();
mapToUserProfile(rawData: any): UserProfile;
}
declare class GitHubProfileFetcher extends BaseProfileFetcher {
constructor();
protected mapToUserProfile(rawData: any): UserProfile;
protected getAdditionalHeaders(): Record<string, string>;
}
declare class MicrosoftProfileFetcher extends BaseProfileFetcher {
constructor();
protected mapToUserProfile(rawData: any): UserProfile;
}
interface ProfileMapping {
email: string;
name?: string;
id?: string;
avatar?: string;
username?: string;
}
declare class GenericProfileFetcher extends BaseProfileFetcher {
private mapping?;
private additionalHeaders?;
constructor(profileEndpoint: string, mapping?: ProfileMapping | undefined, additionalHeaders?: Record<string, string> | undefined);
protected mapToUserProfile(rawData: any): UserProfile;
protected getAdditionalHeaders(): Record<string, string>;
private getNestedProperty;
}
interface ProfileFetcherOptions {
profileUrl?: string;
profileMapping?: ProfileMapping;
profileHeaders?: Record<string, string>;
}
declare class ProfileFetcherFactory {
static createProfileFetcher(providerType: ProviderType, config: OAuth2Config, options?: ProfileFetcherOptions): BaseProfileFetcher;
static registerCustomProfileFetcher(providerName: string, profileFetcher: BaseProfileFetcher): void;
private static customFetchers;
static getCustomProfileFetcher(providerName: string): BaseProfileFetcher | undefined;
}
declare const createCodeVerifier: () => string;
declare const createCodeChallenge: (verifier: string) => string;
declare const generateState: () => string;
declare const seal: <T>(d: T, key: string) => Promise<string>;
declare const unseal: <T>(s: string, key: string) => Promise<T>;
export { type AuthorizationState, type AuthorizationUrlStrategy, BaseProfileFetcher, type CreateUserInput, GenericOAuth2Provider, GenericProfileFetcher, GitHubProfileFetcher, GoogleProfileFetcher, InMemoryStorageAdapter, MicrosoftProfileFetcher, OAuth2Client, type OAuth2Config, OAuth2GranularClient, OAuth2Provider, type OAuth2Token, type ProfileFetcher, ProfileFetcherFactory, type ProfileFetcherOptions, type ProfileMapping, type ProviderFactory, type ProviderType, type Scope, StandardAuthorizationUrlStrategy, StandardTokenExchangeStrategy, type StorageAdapter, type System, type TokenExchangeStrategy, type User, type UserProfile, type UserToken, type UserTokenWithProfile, createCodeChallenge, createCodeVerifier, generateState, seal, unseal };