mulguard 1.1.6 → 1.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +210 -706
- package/dist/actions-CMtg7FGv.js +1 -0
- package/dist/{actions-DeCfLtHA.mjs → actions-CjQUKaXF.mjs} +54 -38
- package/dist/client/index.js +1 -1
- package/dist/client/index.mjs +84 -78
- package/dist/core/auth/email-password.d.ts +145 -0
- package/dist/core/auth/oauth/index.d.ts +14 -0
- package/dist/core/auth/oauth/oauth-handler.d.ts +172 -0
- package/dist/core/auth/oauth/pkce.d.ts +168 -0
- package/dist/core/auth/{oauth-providers.d.ts → oauth/providers.d.ts} +8 -7
- package/dist/core/auth/{oauth-state-store-cookie.d.ts → oauth/state-store-cookie.d.ts} +4 -4
- package/dist/core/auth/{oauth-state-store-redis.d.ts → oauth/state-store-redis.d.ts} +1 -1
- package/dist/core/auth/{oauth-state-store.d.ts → oauth/state-store.d.ts} +4 -1
- package/dist/core/auth/otp.d.ts +184 -0
- package/dist/core/errors/index.d.ts +269 -0
- package/dist/core/index.d.ts +1 -3
- package/dist/core/logger/index.d.ts +147 -0
- package/dist/core/mulguard/integration.d.ts +104 -0
- package/dist/core/mulguard/oauth-handler.d.ts +1 -1
- package/dist/core/security/security-manager.d.ts +236 -0
- package/dist/core/session/session-manager.d.ts +235 -0
- package/dist/core/types/index.d.ts +27 -5
- package/dist/index/index.js +1 -1
- package/dist/index/index.mjs +1388 -881
- package/dist/index.d.ts +3 -6
- package/dist/{client → nextjs/client}/hooks.d.ts +2 -2
- package/dist/nextjs/client/index.d.ts +13 -0
- package/dist/{client → nextjs/client}/provider.d.ts +1 -1
- package/dist/{client → nextjs/client}/server-actions-helper.d.ts +2 -2
- package/dist/{handlers → nextjs/handlers}/api.d.ts +1 -1
- package/dist/nextjs/handlers/index.d.ts +9 -0
- package/dist/{handlers → nextjs/handlers}/route.d.ts +1 -1
- package/dist/nextjs/index.d.ts +15 -0
- package/dist/nextjs/proxy/index.d.ts +149 -0
- package/dist/nextjs/server/actions.d.ts +30 -0
- package/dist/{server → nextjs/server}/auth.d.ts +6 -6
- package/dist/{server → nextjs/server}/cookies.d.ts +5 -6
- package/dist/nextjs/server/index.d.ts +18 -0
- package/dist/{server → nextjs/server}/oauth-state.d.ts +5 -3
- package/dist/{server → nextjs/server}/session-helpers.d.ts +1 -3
- package/dist/nextjs/server/session.d.ts +144 -0
- package/dist/oauth-state-Drwz6fES.js +1 -0
- package/dist/oauth-state-pdypStuS.mjs +210 -0
- package/dist/server/index.js +1 -1
- package/dist/server/index.mjs +27 -29
- package/package.json +64 -11
- package/dist/actions-CExpv_dD.js +0 -1
- package/dist/client/index.d.ts +0 -5
- package/dist/core/auth/index.d.ts +0 -40
- package/dist/core/auth/oauth.d.ts +0 -20
- package/dist/middleware/index.d.ts +0 -28
- package/dist/middleware/proxy.d.ts +0 -53
- package/dist/oauth-state-DKle8eCr.mjs +0 -289
- package/dist/oauth-state-DlvrCV11.js +0 -1
- package/dist/server/actions.d.ts +0 -86
- package/dist/server/helpers.d.ts +0 -10
- package/dist/server/index.d.ts +0 -14
- package/dist/server/middleware.d.ts +0 -39
- package/dist/server/session.d.ts +0 -28
- package/dist/server/utils.d.ts +0 -10
- /package/dist/{middleware → nextjs/proxy}/security.d.ts +0 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { EmailCredentials, AuthResult, User, Session } from '../types';
|
|
2
|
+
import { SecurityManager } from '../security/security-manager';
|
|
3
|
+
import { Logger } from '../logger';
|
|
4
|
+
/**
|
|
5
|
+
* Email/password authentication configuration.
|
|
6
|
+
*/
|
|
7
|
+
export interface EmailPasswordConfig {
|
|
8
|
+
readonly security?: SecurityManager;
|
|
9
|
+
readonly logger?: Logger;
|
|
10
|
+
readonly requireEmailVerification?: boolean;
|
|
11
|
+
readonly maxLoginAttempts?: number;
|
|
12
|
+
readonly lockoutDuration?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Email/password authentication handler.
|
|
16
|
+
*
|
|
17
|
+
* Provides secure email/password authentication with validation,
|
|
18
|
+
* rate limiting, and account lockout protection.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const handler = new EmailPasswordAuth({
|
|
23
|
+
* security: securityManager,
|
|
24
|
+
* logger: logger,
|
|
25
|
+
* })
|
|
26
|
+
*
|
|
27
|
+
* const result = await handler.authenticate({
|
|
28
|
+
* email: 'user@example.com',
|
|
29
|
+
* password: 'password123',
|
|
30
|
+
* }, async (email) => {
|
|
31
|
+
* // Your custom user lookup logic
|
|
32
|
+
* return await db.user.findUnique({ where: { email } })
|
|
33
|
+
* })
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare class EmailPasswordAuth {
|
|
37
|
+
private readonly config;
|
|
38
|
+
private readonly security;
|
|
39
|
+
private readonly loginAttempts;
|
|
40
|
+
constructor(config?: EmailPasswordConfig);
|
|
41
|
+
/**
|
|
42
|
+
* Authenticates a user with email and password.
|
|
43
|
+
*
|
|
44
|
+
* @template TUser - User type
|
|
45
|
+
* @template TSession - Session type
|
|
46
|
+
* @param credentials - Email and password credentials
|
|
47
|
+
* @param userLookup - Function to lookup user by email
|
|
48
|
+
* @param passwordVerify - Function to verify password (optional, uses comparePassword if not provided)
|
|
49
|
+
* @param createSession - Function to create session (optional)
|
|
50
|
+
* @returns Authentication result
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* const result = await handler.authenticate(
|
|
55
|
+
* { email: 'user@example.com', password: 'password123' },
|
|
56
|
+
* async (email) => await db.user.findUnique({ where: { email } }),
|
|
57
|
+
* async (password, hash) => await bcrypt.compare(password, hash)
|
|
58
|
+
* )
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
authenticate<TUser extends User = User, TSession extends Session<TUser> = Session<TUser>>(credentials: EmailCredentials, userLookup: (email: string) => Promise<TUser | null>, passwordVerify?: (password: string, hash: string) => Promise<boolean>, createSession?: (user: TUser) => Promise<TSession>): Promise<AuthResult<TUser, TSession>>;
|
|
62
|
+
/**
|
|
63
|
+
* Checks if account is locked.
|
|
64
|
+
*
|
|
65
|
+
* @param email - User email
|
|
66
|
+
* @returns Lockout status
|
|
67
|
+
*/
|
|
68
|
+
private checkAccountLockout;
|
|
69
|
+
/**
|
|
70
|
+
* Records a failed login attempt.
|
|
71
|
+
*
|
|
72
|
+
* @param email - User email
|
|
73
|
+
*/
|
|
74
|
+
private recordFailedAttempt;
|
|
75
|
+
/**
|
|
76
|
+
* Clears failed login attempts for an email.
|
|
77
|
+
*
|
|
78
|
+
* @param email - User email
|
|
79
|
+
*/
|
|
80
|
+
private clearFailedAttempts;
|
|
81
|
+
/**
|
|
82
|
+
* Resets login attempts for an email (for admin use).
|
|
83
|
+
*
|
|
84
|
+
* @param email - User email
|
|
85
|
+
*/
|
|
86
|
+
resetLoginAttempts(email: string): void;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Creates an email/password authentication handler.
|
|
90
|
+
*
|
|
91
|
+
* @param config - Email/password authentication configuration
|
|
92
|
+
* @returns Email/password authentication handler
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* const handler = createEmailPasswordAuth({
|
|
97
|
+
* security: securityManager,
|
|
98
|
+
* logger: logger,
|
|
99
|
+
* })
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export declare function createEmailPasswordAuth(config?: EmailPasswordConfig): EmailPasswordAuth;
|
|
103
|
+
/**
|
|
104
|
+
* TODO: Performance
|
|
105
|
+
* - [ ] Add password hashing caching
|
|
106
|
+
* - [ ] Optimize user lookup with caching
|
|
107
|
+
* - [ ] Implement async password verification
|
|
108
|
+
* - [ ] Add batch authentication support
|
|
109
|
+
*
|
|
110
|
+
* TODO: Features
|
|
111
|
+
* - [ ] Add password reset functionality
|
|
112
|
+
* - [ ] Implement password change with old password verification
|
|
113
|
+
* - [ ] Add password history tracking
|
|
114
|
+
* - [ ] Create password expiration support
|
|
115
|
+
* - [ ] Add account recovery options
|
|
116
|
+
* - [ ] Implement remember me functionality
|
|
117
|
+
*
|
|
118
|
+
* TODO: Security
|
|
119
|
+
* - [ ] Add password breach checking (Have I Been Pwned)
|
|
120
|
+
* - [ ] Implement password strength requirements
|
|
121
|
+
* - [ ] Add two-factor authentication integration
|
|
122
|
+
* - [ ] Create security event logging
|
|
123
|
+
* - [ ] Add IP-based lockout
|
|
124
|
+
*
|
|
125
|
+
* TODO: Type Safety
|
|
126
|
+
* - [ ] Add branded types for email addresses
|
|
127
|
+
* - [ ] Create type-safe password handling
|
|
128
|
+
* - [ ] Implement compile-time validation rules
|
|
129
|
+
*
|
|
130
|
+
* TODO: Testing
|
|
131
|
+
* - [ ] Add comprehensive unit tests
|
|
132
|
+
* - [ ] Test account lockout mechanism
|
|
133
|
+
* - [ ] Test rate limiting integration
|
|
134
|
+
* - [ ] Add password verification tests
|
|
135
|
+
*
|
|
136
|
+
* TODO: Documentation
|
|
137
|
+
* - [ ] Document authentication flow
|
|
138
|
+
* - [ ] Add password policy guide
|
|
139
|
+
* - [ ] Create security best practices guide
|
|
140
|
+
*
|
|
141
|
+
* TODO: Limitations
|
|
142
|
+
* - [ ] Password verification must be implemented by user
|
|
143
|
+
* - [ ] Account lockout is in-memory (consider persistent storage)
|
|
144
|
+
* - [ ] No password hashing included (use bcrypt, argon2, etc.)
|
|
145
|
+
*/
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth 2.0 Module for Mulguard Authentication Library.
|
|
3
|
+
*
|
|
4
|
+
* Provides comprehensive OAuth authentication with PKCE support,
|
|
5
|
+
* state management, and provider integrations.
|
|
6
|
+
*
|
|
7
|
+
* @module @mulguard/core/auth/oauth
|
|
8
|
+
*/
|
|
9
|
+
export * from './providers';
|
|
10
|
+
export * from './pkce';
|
|
11
|
+
export * from './state-store';
|
|
12
|
+
export * from './state-store-cookie';
|
|
13
|
+
export * from './state-store-redis';
|
|
14
|
+
export * from './oauth-handler';
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { OAuthProvidersConfig, OAuthUserInfo, AuthResult, User, Session } from '../../types';
|
|
2
|
+
import { PKCEStorageAdapter } from './pkce';
|
|
3
|
+
import { OAuthStateStore } from './state-store';
|
|
4
|
+
import { Logger } from '../../logger';
|
|
5
|
+
/**
|
|
6
|
+
* OAuth handler configuration.
|
|
7
|
+
*/
|
|
8
|
+
export interface OAuthHandlerConfig {
|
|
9
|
+
readonly providers: OAuthProvidersConfig;
|
|
10
|
+
readonly baseUrl: string;
|
|
11
|
+
readonly pkce?: {
|
|
12
|
+
readonly enabled: boolean;
|
|
13
|
+
readonly storage?: PKCEStorageAdapter;
|
|
14
|
+
};
|
|
15
|
+
readonly stateStore?: OAuthStateStore;
|
|
16
|
+
readonly logger?: Logger;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* OAuth initiation result with authorization URL and state.
|
|
20
|
+
*/
|
|
21
|
+
export interface OAuthInitiationResult {
|
|
22
|
+
readonly url: string;
|
|
23
|
+
readonly state: string;
|
|
24
|
+
readonly codeVerifier?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Comprehensive OAuth 2.0 handler with PKCE support.
|
|
28
|
+
*
|
|
29
|
+
* Provides secure OAuth authentication flow with PKCE protection,
|
|
30
|
+
* state management, and comprehensive error handling.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* const handler = new OAuthHandler({
|
|
35
|
+
* providers: {
|
|
36
|
+
* google: { clientId: '...', clientSecret: '...' },
|
|
37
|
+
* },
|
|
38
|
+
* baseUrl: 'https://example.com',
|
|
39
|
+
* pkce: { enabled: true },
|
|
40
|
+
* })
|
|
41
|
+
*
|
|
42
|
+
* // Initiate OAuth flow
|
|
43
|
+
* const { url, state, codeVerifier } = await handler.initiate('google')
|
|
44
|
+
*
|
|
45
|
+
* // Handle callback
|
|
46
|
+
* const result = await handler.handleCallback('google', code, state, codeVerifier)
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare class OAuthHandler {
|
|
50
|
+
private readonly config;
|
|
51
|
+
private readonly pkceStorage;
|
|
52
|
+
constructor(config: OAuthHandlerConfig);
|
|
53
|
+
/**
|
|
54
|
+
* Initiates OAuth authentication flow.
|
|
55
|
+
*
|
|
56
|
+
* Generates authorization URL with PKCE (if enabled) and CSRF state token.
|
|
57
|
+
*
|
|
58
|
+
* @param providerId - OAuth provider identifier
|
|
59
|
+
* @returns OAuth initiation result with authorization URL and state
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* const { url, state, codeVerifier } = await handler.initiate('google')
|
|
64
|
+
* // Store state and codeVerifier securely
|
|
65
|
+
* // Redirect user to url
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
initiate(providerId: string): Promise<OAuthInitiationResult>;
|
|
69
|
+
/**
|
|
70
|
+
* Handles OAuth callback and completes authentication.
|
|
71
|
+
*
|
|
72
|
+
* Validates state token, verifies PKCE (if enabled), exchanges code for tokens,
|
|
73
|
+
* retrieves user profile, and creates session.
|
|
74
|
+
*
|
|
75
|
+
* @template TUser - User type
|
|
76
|
+
* @template TSession - Session type
|
|
77
|
+
* @param providerId - OAuth provider identifier
|
|
78
|
+
* @param code - Authorization code from OAuth callback
|
|
79
|
+
* @param state - CSRF state token
|
|
80
|
+
* @param codeVerifier - PKCE code verifier (required if PKCE is enabled)
|
|
81
|
+
* @param userLookup - Function to lookup/create user from OAuth profile
|
|
82
|
+
* @param createSession - Function to create session (optional)
|
|
83
|
+
* @returns Authentication result
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* const result = await handler.handleCallback(
|
|
88
|
+
* 'google',
|
|
89
|
+
* code,
|
|
90
|
+
* state,
|
|
91
|
+
* storedCodeVerifier,
|
|
92
|
+
* async (userInfo) => {
|
|
93
|
+
* // Lookup or create user
|
|
94
|
+
* return await db.user.findOrCreate({ email: userInfo.email })
|
|
95
|
+
* }
|
|
96
|
+
* )
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
handleCallback<TUser extends User = User, TSession extends Session<TUser> = Session<TUser>>(providerId: string, code: string, state: string, codeVerifier?: string, userLookup?: (userInfo: OAuthUserInfo) => Promise<TUser>, createSession?: (user: TUser, userInfo: OAuthUserInfo) => Promise<TSession>): Promise<AuthResult<TUser, TSession>>;
|
|
100
|
+
/**
|
|
101
|
+
* Validates OAuth state token.
|
|
102
|
+
*
|
|
103
|
+
* @param state - State token
|
|
104
|
+
* @param providerId - Provider identifier
|
|
105
|
+
* @returns True if state is valid
|
|
106
|
+
*/
|
|
107
|
+
private validateState;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Creates an OAuth handler instance.
|
|
111
|
+
*
|
|
112
|
+
* @param config - OAuth handler configuration
|
|
113
|
+
* @returns OAuth handler instance
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* const handler = createOAuthHandler({
|
|
118
|
+
* providers: {
|
|
119
|
+
* google: { clientId: '...', clientSecret: '...' },
|
|
120
|
+
* },
|
|
121
|
+
* baseUrl: 'https://example.com',
|
|
122
|
+
* pkce: { enabled: true },
|
|
123
|
+
* })
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
export declare function createOAuthHandler(config: OAuthHandlerConfig): OAuthHandler;
|
|
127
|
+
export * from './pkce';
|
|
128
|
+
export * from './providers';
|
|
129
|
+
/**
|
|
130
|
+
* TODO: Performance
|
|
131
|
+
* - [ ] Add OAuth token caching
|
|
132
|
+
* - [ ] Optimize user profile retrieval
|
|
133
|
+
* - [ ] Implement token refresh caching
|
|
134
|
+
* - [ ] Add batch OAuth operations support
|
|
135
|
+
*
|
|
136
|
+
* TODO: Features
|
|
137
|
+
* - [ ] Add OAuth token refresh support
|
|
138
|
+
* - [ ] Implement OAuth token revocation
|
|
139
|
+
* - [ ] Add OAuth provider discovery
|
|
140
|
+
* - [ ] Create OAuth provider plugin system
|
|
141
|
+
* - [ ] Add OAuth consent screen customization
|
|
142
|
+
*
|
|
143
|
+
* TODO: Security
|
|
144
|
+
* - [ ] Add OAuth flow rate limiting
|
|
145
|
+
* - [ ] Implement OAuth state encryption
|
|
146
|
+
* - [ ] Add OAuth token validation
|
|
147
|
+
* - [ ] Create security event logging
|
|
148
|
+
* - [ ] Add OAuth flow monitoring
|
|
149
|
+
*
|
|
150
|
+
* TODO: Type Safety
|
|
151
|
+
* - [ ] Add branded types for OAuth tokens
|
|
152
|
+
* - [ ] Create type-safe provider configuration
|
|
153
|
+
* - [ ] Implement compile-time validation
|
|
154
|
+
*
|
|
155
|
+
* TODO: Testing
|
|
156
|
+
* - [ ] Add comprehensive unit tests
|
|
157
|
+
* - [ ] Test PKCE flow end-to-end
|
|
158
|
+
* - [ ] Test state validation
|
|
159
|
+
* - [ ] Add provider-specific tests
|
|
160
|
+
*
|
|
161
|
+
* TODO: Documentation
|
|
162
|
+
* - [ ] Document OAuth flow
|
|
163
|
+
* - [ ] Add PKCE setup guide
|
|
164
|
+
* - [ ] Create provider configuration guide
|
|
165
|
+
* - [ ] Document security best practices
|
|
166
|
+
*
|
|
167
|
+
* TODO: Limitations
|
|
168
|
+
* - [ ] PKCE storage is in-memory (consider Redis for production)
|
|
169
|
+
* - [ ] State storage is in-memory (consider Redis for production)
|
|
170
|
+
* - [ ] Token refresh not implemented yet
|
|
171
|
+
* - [ ] No support for custom OAuth providers yet
|
|
172
|
+
*/
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PKCE (Proof Key for Code Exchange) Implementation for OAuth 2.0.
|
|
3
|
+
*
|
|
4
|
+
* Provides secure PKCE code generation and verification for OAuth flows
|
|
5
|
+
* to prevent authorization code interception attacks.
|
|
6
|
+
*
|
|
7
|
+
* @module @mulguard/core/auth/oauth/pkce
|
|
8
|
+
*
|
|
9
|
+
* @see {@link https://tools.ietf.org/html/rfc7636} RFC 7636 - PKCE
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* PKCE code challenge method.
|
|
13
|
+
*/
|
|
14
|
+
export type PKCECodeChallengeMethod = 'S256' | 'plain';
|
|
15
|
+
/**
|
|
16
|
+
* PKCE code pair (verifier and challenge).
|
|
17
|
+
*/
|
|
18
|
+
export interface PKCECodePair {
|
|
19
|
+
readonly codeVerifier: string;
|
|
20
|
+
readonly codeChallenge: string;
|
|
21
|
+
readonly codeChallengeMethod: PKCECodeChallengeMethod;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* PKCE verification result.
|
|
25
|
+
*/
|
|
26
|
+
export interface PKCEVerificationResult {
|
|
27
|
+
readonly valid: boolean;
|
|
28
|
+
readonly error?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Generates a cryptographically secure random string for PKCE code verifier.
|
|
32
|
+
*
|
|
33
|
+
* Uses URL-safe base64 encoding (base64url) as per RFC 7636.
|
|
34
|
+
*
|
|
35
|
+
* @param length - Code verifier length (43-128, default: 43)
|
|
36
|
+
* @returns Base64url-encoded code verifier
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const verifier = generateCodeVerifier()
|
|
41
|
+
* // Returns: 'abc123xyz...' (43 characters, base64url encoded)
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare function generateCodeVerifier(length?: number): string;
|
|
45
|
+
/**
|
|
46
|
+
* Generates PKCE code challenge from verifier using S256 method.
|
|
47
|
+
*
|
|
48
|
+
* Uses SHA256 hash and base64url encoding as per RFC 7636.
|
|
49
|
+
*
|
|
50
|
+
* @param codeVerifier - Code verifier
|
|
51
|
+
* @returns Base64url-encoded code challenge
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const verifier = generateCodeVerifier()
|
|
56
|
+
* const challenge = generateCodeChallenge(verifier)
|
|
57
|
+
* // Returns: 'E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM' (base64url encoded SHA256 hash)
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare function generateCodeChallenge(codeVerifier: string): string;
|
|
61
|
+
/**
|
|
62
|
+
* Generates a complete PKCE code pair (verifier + challenge).
|
|
63
|
+
*
|
|
64
|
+
* @param length - Code verifier length (default: 43)
|
|
65
|
+
* @param method - Code challenge method (default: 'S256')
|
|
66
|
+
* @returns PKCE code pair
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* const { codeVerifier, codeChallenge } = generatePKCECodePair()
|
|
71
|
+
* // Store codeVerifier securely (e.g., in session)
|
|
72
|
+
* // Use codeChallenge in authorization URL
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export declare function generatePKCECodePair(length?: number, method?: PKCECodeChallengeMethod): PKCECodePair;
|
|
76
|
+
/**
|
|
77
|
+
* Verifies PKCE code challenge against code verifier.
|
|
78
|
+
*
|
|
79
|
+
* Uses constant-time comparison to prevent timing attacks.
|
|
80
|
+
*
|
|
81
|
+
* @param codeVerifier - Code verifier (from stored session)
|
|
82
|
+
* @param codeChallenge - Code challenge (from authorization request)
|
|
83
|
+
* @param method - Code challenge method (default: 'S256')
|
|
84
|
+
* @returns Verification result
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const result = verifyPKCECode(storedVerifier, receivedChallenge)
|
|
89
|
+
* if (!result.valid) {
|
|
90
|
+
* throw new Error(result.error)
|
|
91
|
+
* }
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export declare function verifyPKCECode(codeVerifier: string, codeChallenge: string, method?: PKCECodeChallengeMethod): PKCEVerificationResult;
|
|
95
|
+
/**
|
|
96
|
+
* PKCE code storage adapter interface.
|
|
97
|
+
*/
|
|
98
|
+
export interface PKCEStorageAdapter {
|
|
99
|
+
/**
|
|
100
|
+
* Stores PKCE code verifier.
|
|
101
|
+
*
|
|
102
|
+
* @param key - Storage key (e.g., state token)
|
|
103
|
+
* @param codeVerifier - Code verifier to store
|
|
104
|
+
* @param expiresIn - Expiration time in milliseconds
|
|
105
|
+
*/
|
|
106
|
+
set(key: string, codeVerifier: string, expiresIn: number): Promise<void>;
|
|
107
|
+
/**
|
|
108
|
+
* Gets PKCE code verifier.
|
|
109
|
+
*
|
|
110
|
+
* @param key - Storage key
|
|
111
|
+
* @returns Code verifier or null if not found/expired
|
|
112
|
+
*/
|
|
113
|
+
get(key: string): Promise<string | null>;
|
|
114
|
+
/**
|
|
115
|
+
* Deletes PKCE code verifier.
|
|
116
|
+
*
|
|
117
|
+
* @param key - Storage key
|
|
118
|
+
*/
|
|
119
|
+
delete(key: string): Promise<void>;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* In-memory PKCE storage adapter.
|
|
123
|
+
*/
|
|
124
|
+
export declare class MemoryPKCEStorage implements PKCEStorageAdapter {
|
|
125
|
+
private readonly storage;
|
|
126
|
+
set(key: string, codeVerifier: string, expiresIn: number): Promise<void>;
|
|
127
|
+
get(key: string): Promise<string | null>;
|
|
128
|
+
delete(key: string): Promise<void>;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* TODO: Performance
|
|
132
|
+
* - [ ] Add PKCE code pair caching
|
|
133
|
+
* - [ ] Optimize SHA256 hashing for high-frequency operations
|
|
134
|
+
* - [ ] Consider Web Crypto API for browser environments
|
|
135
|
+
*
|
|
136
|
+
* TODO: Features
|
|
137
|
+
* - [ ] Add Redis-based PKCE storage adapter
|
|
138
|
+
* - [ ] Implement PKCE code rotation
|
|
139
|
+
* - [ ] Add PKCE code expiration tracking
|
|
140
|
+
* - [ ] Create PKCE code cleanup job
|
|
141
|
+
*
|
|
142
|
+
* TODO: Security
|
|
143
|
+
* - [ ] Add PKCE code generation rate limiting
|
|
144
|
+
* - [ ] Implement PKCE code audit logging
|
|
145
|
+
* - [ ] Add PKCE code strength validation
|
|
146
|
+
* - [ ] Create security event monitoring
|
|
147
|
+
*
|
|
148
|
+
* TODO: Type Safety
|
|
149
|
+
* - [ ] Add branded types for code verifier/challenge
|
|
150
|
+
* - [ ] Create type-safe PKCE storage
|
|
151
|
+
* - [ ] Implement compile-time validation
|
|
152
|
+
*
|
|
153
|
+
* TODO: Testing
|
|
154
|
+
* - [ ] Add comprehensive unit tests
|
|
155
|
+
* - [ ] Test constant-time comparison
|
|
156
|
+
* - [ ] Test code generation randomness
|
|
157
|
+
* - [ ] Add storage adapter tests
|
|
158
|
+
*
|
|
159
|
+
* TODO: Documentation
|
|
160
|
+
* - [ ] Document PKCE flow
|
|
161
|
+
* - [ ] Add security considerations guide
|
|
162
|
+
* - [ ] Create PKCE best practices guide
|
|
163
|
+
*
|
|
164
|
+
* TODO: Limitations
|
|
165
|
+
* - [ ] PKCE storage is in-memory (consider Redis for production)
|
|
166
|
+
* - [ ] Code generation uses Node.js Buffer (consider Web Crypto API for browsers)
|
|
167
|
+
* - [ ] Plain method is supported but not recommended
|
|
168
|
+
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { OAuthProviderConfig } from '
|
|
1
|
+
import { OAuthProviderConfig } from '../../types';
|
|
2
2
|
/**
|
|
3
3
|
* OAuth provider identifier.
|
|
4
4
|
*/
|
|
@@ -106,6 +106,7 @@ export declare function buildOAuthAuthorizationUrl(providerId: string, config: O
|
|
|
106
106
|
* @param config - Provider configuration
|
|
107
107
|
* @param code - Authorization code from OAuth callback
|
|
108
108
|
* @param redirectUri - Redirect URI used in authorization request
|
|
109
|
+
* @param codeVerifier - PKCE code verifier (optional)
|
|
109
110
|
* @returns Token exchange result
|
|
110
111
|
* @throws {Error} If exchange fails or provider is not supported
|
|
111
112
|
*
|
|
@@ -115,12 +116,13 @@ export declare function buildOAuthAuthorizationUrl(providerId: string, config: O
|
|
|
115
116
|
* 'google',
|
|
116
117
|
* { clientId: '...', clientSecret: '...' },
|
|
117
118
|
* 'code123',
|
|
118
|
-
* 'https://example.com/callback'
|
|
119
|
+
* 'https://example.com/callback',
|
|
120
|
+
* 'code_verifier'
|
|
119
121
|
* )
|
|
120
122
|
* console.log(tokens.access_token)
|
|
121
123
|
* ```
|
|
122
124
|
*/
|
|
123
|
-
export declare function exchangeOAuthCode(providerId: string, config: OAuthProviderConfig, code: string, redirectUri: string): Promise<TokenExchangeResult>;
|
|
125
|
+
export declare function exchangeOAuthCode(providerId: string, config: OAuthProviderConfig, code: string, redirectUri: string, codeVerifier?: string): Promise<TokenExchangeResult>;
|
|
124
126
|
/**
|
|
125
127
|
* Retrieves user information from OAuth provider.
|
|
126
128
|
*
|
|
@@ -131,11 +133,11 @@ export declare function exchangeOAuthCode(providerId: string, config: OAuthProvi
|
|
|
131
133
|
*
|
|
132
134
|
* @example
|
|
133
135
|
* ```typescript
|
|
134
|
-
* const profile = await
|
|
136
|
+
* const profile = await getUserProfile('google', 'access_token_123')
|
|
135
137
|
* console.log(profile.email, profile.name)
|
|
136
138
|
* ```
|
|
137
139
|
*/
|
|
138
|
-
export declare function
|
|
140
|
+
export declare function getUserProfile(providerId: string, accessToken: string): Promise<OAuthUserProfile>;
|
|
139
141
|
/**
|
|
140
142
|
* Type predicate to check if a value is a valid OAuth provider config.
|
|
141
143
|
*
|
|
@@ -143,7 +145,7 @@ export declare function getOAuthUserInfo(providerId: string, accessToken: string
|
|
|
143
145
|
* @returns True if value is a valid OAuth provider config
|
|
144
146
|
*/
|
|
145
147
|
export declare function isOAuthProviderConfig(value: unknown): value is OAuthProviderConfig;
|
|
146
|
-
export {};
|
|
148
|
+
export { getUserProfile as getOAuthUserInfo };
|
|
147
149
|
/**
|
|
148
150
|
* TODO: Performance
|
|
149
151
|
* - [ ] Add token exchange result caching (with TTL)
|
|
@@ -152,7 +154,6 @@ export {};
|
|
|
152
154
|
* - [ ] Cache provider metadata lookups
|
|
153
155
|
*
|
|
154
156
|
* TODO: Features
|
|
155
|
-
* - [ ] Add support for PKCE (Proof Key for Code Exchange)
|
|
156
157
|
* - [ ] Implement token refresh flow
|
|
157
158
|
* - [ ] Add support for custom OAuth providers
|
|
158
159
|
* - [ ] Create provider plugin system
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { OAuthStateStore } from './
|
|
1
|
+
import { OAuthStateStore } from './state-store';
|
|
2
2
|
/**
|
|
3
3
|
* Cookie options interface
|
|
4
4
|
*/
|
|
5
|
-
export interface
|
|
5
|
+
export interface OAuthCookieOptions {
|
|
6
6
|
httpOnly?: boolean;
|
|
7
7
|
secure?: boolean;
|
|
8
8
|
sameSite?: 'strict' | 'lax' | 'none';
|
|
@@ -21,7 +21,7 @@ export interface CookieHandler {
|
|
|
21
21
|
/**
|
|
22
22
|
* Set cookie with options
|
|
23
23
|
*/
|
|
24
|
-
setCookie(name: string, value: string, options:
|
|
24
|
+
setCookie(name: string, value: string, options: OAuthCookieOptions): Promise<void> | void;
|
|
25
25
|
/**
|
|
26
26
|
* Delete cookie
|
|
27
27
|
*/
|
|
@@ -72,7 +72,7 @@ export declare function createCookieOAuthStateStore(config: CookieOAuthStateStor
|
|
|
72
72
|
*
|
|
73
73
|
* @example
|
|
74
74
|
* ```typescript
|
|
75
|
-
* import { createNextJsCookieOAuthStateStore } from 'mulguard/core/auth/oauth
|
|
75
|
+
* import { createNextJsCookieOAuthStateStore } from 'mulguard/core/auth/oauth/state-store-cookie'
|
|
76
76
|
*
|
|
77
77
|
* export const auth = mulguard({
|
|
78
78
|
* oauthStateStore: createNextJsCookieOAuthStateStore(),
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Default implementation uses in-memory Map (for development)
|
|
6
6
|
* Production should use Redis, database, or other persistent store
|
|
7
|
+
*
|
|
8
|
+
* @module @mulguard/core/auth/oauth/state-store
|
|
7
9
|
*/
|
|
8
10
|
export interface OAuthState {
|
|
9
11
|
provider: string;
|
|
@@ -42,4 +44,5 @@ export declare class MemoryOAuthStateStore implements OAuthStateStore {
|
|
|
42
44
|
* Create default in-memory OAuth state store
|
|
43
45
|
*/
|
|
44
46
|
export declare function createMemoryOAuthStateStore(): OAuthStateStore;
|
|
45
|
-
export { createCookieOAuthStateStore, createNextJsCookieOAuthStateStore, type CookieHandler, type CookieOAuthStateStoreConfig, } from './
|
|
47
|
+
export { createCookieOAuthStateStore, createNextJsCookieOAuthStateStore, type CookieHandler, type CookieOAuthStateStoreConfig, } from './state-store-cookie';
|
|
48
|
+
export { createRedisOAuthStateStore, type RedisClient, } from './state-store-redis';
|