@spidy092/auth-client 2.0.7 → 2.1.0
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/config.js +0 -1
- package/core.js +15 -54
- package/package.json +1 -1
- package/token.js +53 -31
package/config.js
CHANGED
package/core.js
CHANGED
|
@@ -12,7 +12,7 @@ import { getConfig, isRouterMode } from './config';
|
|
|
12
12
|
|
|
13
13
|
let callbackProcessed = false;
|
|
14
14
|
|
|
15
|
-
export function login(clientKeyArg, redirectUriArg
|
|
15
|
+
export function login(clientKeyArg, redirectUriArg) {
|
|
16
16
|
// ✅ Reset callback state when starting new login
|
|
17
17
|
resetCallbackState();
|
|
18
18
|
|
|
@@ -25,14 +25,11 @@ export function login(clientKeyArg, redirectUriArg, options = {}) {
|
|
|
25
25
|
|
|
26
26
|
const clientKey = clientKeyArg || defaultClientKey;
|
|
27
27
|
const redirectUri = redirectUriArg || defaultRedirectUri;
|
|
28
|
-
const { codeChallenge, codeChallengeMethod, state } = options;
|
|
29
28
|
|
|
30
29
|
console.log('🔄 Smart Login initiated:', {
|
|
31
30
|
mode: isRouterMode() ? 'ROUTER' : 'CLIENT',
|
|
32
31
|
clientKey,
|
|
33
|
-
redirectUri
|
|
34
|
-
hasPKCE: !!codeChallenge,
|
|
35
|
-
hasState: !!state
|
|
32
|
+
redirectUri
|
|
36
33
|
});
|
|
37
34
|
|
|
38
35
|
if (!clientKey || !redirectUri) {
|
|
@@ -44,39 +41,27 @@ export function login(clientKeyArg, redirectUriArg, options = {}) {
|
|
|
44
41
|
|
|
45
42
|
if (isRouterMode()) {
|
|
46
43
|
// Router mode: Direct backend authentication
|
|
47
|
-
return routerLogin(clientKey, redirectUri
|
|
44
|
+
return routerLogin(clientKey, redirectUri);
|
|
48
45
|
} else {
|
|
49
46
|
// Client mode: Redirect to centralized login
|
|
50
|
-
return clientLogin(clientKey, redirectUri
|
|
47
|
+
return clientLogin(clientKey, redirectUri);
|
|
51
48
|
}
|
|
52
49
|
}
|
|
53
50
|
|
|
54
51
|
// ✅ Router mode: Direct backend call
|
|
55
|
-
function routerLogin(clientKey, redirectUri
|
|
52
|
+
function routerLogin(clientKey, redirectUri) {
|
|
56
53
|
const { authBaseUrl } = getConfig();
|
|
57
|
-
const { codeChallenge, codeChallengeMethod, state } = options;
|
|
58
|
-
|
|
59
|
-
// Build URL with PKCE and state parameters
|
|
60
|
-
const params = new URLSearchParams({
|
|
61
|
-
redirect_uri: redirectUri
|
|
62
|
-
});
|
|
63
54
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
params.append('
|
|
55
|
+
const params = new URLSearchParams();
|
|
56
|
+
if (redirectUri) {
|
|
57
|
+
params.append('redirect_uri', redirectUri);
|
|
67
58
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
params.append('state', state);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const backendLoginUrl = `${authBaseUrl}/login/${clientKey}?${params.toString()}`;
|
|
59
|
+
const query = params.toString();
|
|
60
|
+
const backendLoginUrl = `${authBaseUrl}/login/${clientKey}${query ? `?${query}` : ''}`;
|
|
74
61
|
|
|
75
62
|
console.log('🏭 Router Login: Direct backend authentication', {
|
|
76
63
|
clientKey,
|
|
77
64
|
redirectUri,
|
|
78
|
-
hasPKCE: !!codeChallenge,
|
|
79
|
-
hasState: !!state,
|
|
80
65
|
backendUrl: backendLoginUrl
|
|
81
66
|
});
|
|
82
67
|
|
|
@@ -84,32 +69,20 @@ function routerLogin(clientKey, redirectUri, options = {}) {
|
|
|
84
69
|
}
|
|
85
70
|
|
|
86
71
|
// ✅ Client mode: Centralized login
|
|
87
|
-
function clientLogin(clientKey, redirectUri
|
|
72
|
+
function clientLogin(clientKey, redirectUri) {
|
|
88
73
|
const { accountUiUrl } = getConfig();
|
|
89
|
-
const { codeChallenge, codeChallengeMethod, state } = options;
|
|
90
74
|
|
|
91
|
-
// Build URL with PKCE and state parameters
|
|
92
75
|
const params = new URLSearchParams({
|
|
93
|
-
client: clientKey
|
|
94
|
-
redirect_uri: redirectUri
|
|
76
|
+
client: clientKey
|
|
95
77
|
});
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
params.append('code_challenge', codeChallenge);
|
|
99
|
-
params.append('code_challenge_method', codeChallengeMethod || 'S256');
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (state) {
|
|
103
|
-
params.append('state', state);
|
|
78
|
+
if (redirectUri) {
|
|
79
|
+
params.append('redirect_uri', redirectUri);
|
|
104
80
|
}
|
|
105
|
-
|
|
106
81
|
const centralizedLoginUrl = `${accountUiUrl}/login?${params.toString()}`;
|
|
107
82
|
|
|
108
83
|
console.log('🔄 Client Login: Redirecting to centralized login', {
|
|
109
84
|
clientKey,
|
|
110
85
|
redirectUri,
|
|
111
|
-
hasPKCE: !!codeChallenge,
|
|
112
|
-
hasState: !!state,
|
|
113
86
|
centralizedUrl: centralizedLoginUrl
|
|
114
87
|
});
|
|
115
88
|
|
|
@@ -187,23 +160,12 @@ export function handleCallback() {
|
|
|
187
160
|
const params = new URLSearchParams(window.location.search);
|
|
188
161
|
const accessToken = params.get('access_token');
|
|
189
162
|
const error = params.get('error');
|
|
190
|
-
const state = params.get('state');
|
|
191
163
|
|
|
192
164
|
console.log('🔄 Callback handling:', {
|
|
193
165
|
hasAccessToken: !!accessToken,
|
|
194
|
-
error
|
|
195
|
-
hasState: !!state
|
|
166
|
+
error
|
|
196
167
|
});
|
|
197
168
|
|
|
198
|
-
// ✅ Validate state parameter
|
|
199
|
-
if (state) {
|
|
200
|
-
console.warn("⚠️ State returned but validation disabled (demo mode)");
|
|
201
|
-
|
|
202
|
-
// Clean up any existing stored state
|
|
203
|
-
sessionStorage.removeItem('oauth_state');
|
|
204
|
-
sessionStorage.removeItem('pkce_timestamp');
|
|
205
|
-
}
|
|
206
|
-
|
|
207
169
|
// ✅ Prevent duplicate callback processing
|
|
208
170
|
if (callbackProcessed) {
|
|
209
171
|
const existingToken = getToken();
|
|
@@ -218,7 +180,6 @@ export function handleCallback() {
|
|
|
218
180
|
callbackProcessed = true;
|
|
219
181
|
sessionStorage.removeItem('originalApp');
|
|
220
182
|
sessionStorage.removeItem('returnUrl');
|
|
221
|
-
sessionStorage.removeItem('pkce_code_verifier'); // Clear PKCE verifier after use
|
|
222
183
|
|
|
223
184
|
if (error) {
|
|
224
185
|
const errorDescription = params.get('error_description') || error;
|
package/package.json
CHANGED
package/token.js
CHANGED
|
@@ -53,7 +53,7 @@ function readAccessToken() {
|
|
|
53
53
|
// }
|
|
54
54
|
|
|
55
55
|
// const expires = new Date(Date.now() + COOKIE_MAX_AGE * 1000);
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
// try {
|
|
58
58
|
// document.cookie = `${REFRESH_COOKIE}=${encodeURIComponent(token)}; Path=/; SameSite=Lax${secureAttribute()}; Expires=${expires.toUTCString()}`;
|
|
59
59
|
// } catch (err) {
|
|
@@ -66,14 +66,14 @@ function readAccessToken() {
|
|
|
66
66
|
// const match = document.cookie
|
|
67
67
|
// ?.split('; ')
|
|
68
68
|
// ?.find((row) => row.startsWith(`${REFRESH_COOKIE}=`));
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
// if (match) {
|
|
71
71
|
// return decodeURIComponent(match.split('=')[1]);
|
|
72
72
|
// }
|
|
73
73
|
// } catch (err) {
|
|
74
74
|
// console.warn('Could not read refresh token:', err);
|
|
75
75
|
// }
|
|
76
|
-
|
|
76
|
+
|
|
77
77
|
// return null;
|
|
78
78
|
// }
|
|
79
79
|
|
|
@@ -145,55 +145,77 @@ export function clearToken() {
|
|
|
145
145
|
});
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
+
// ========== REFRESH TOKEN STORAGE FOR HTTP DEVELOPMENT ==========
|
|
149
|
+
// In production, refresh tokens should ONLY be in httpOnly cookies set by server
|
|
150
|
+
// For HTTP development (cross-origin cookies don't work), we store in localStorage
|
|
151
|
+
const REFRESH_TOKEN_KEY = 'auth_refresh_token';
|
|
152
|
+
|
|
153
|
+
function isHttpDevelopment() {
|
|
154
|
+
try {
|
|
155
|
+
return typeof window !== 'undefined' &&
|
|
156
|
+
window.location?.protocol === 'http:';
|
|
157
|
+
} catch (err) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
148
162
|
export function setRefreshToken(token) {
|
|
149
|
-
// ✅ SECURITY: Refresh tokens should ONLY be in httpOnly cookies set by server
|
|
150
|
-
// This function should NOT be used - refresh tokens must come from server cookies
|
|
151
|
-
// Keeping for backwards compatibility but logging warning
|
|
152
|
-
|
|
153
163
|
if (!token) {
|
|
154
164
|
clearRefreshToken();
|
|
155
165
|
return;
|
|
156
166
|
}
|
|
157
167
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
168
|
+
// For HTTP development, store in localStorage (since httpOnly cookies don't work cross-origin)
|
|
169
|
+
if (isHttpDevelopment()) {
|
|
170
|
+
try {
|
|
171
|
+
localStorage.setItem(REFRESH_TOKEN_KEY, token);
|
|
172
|
+
console.log('📦 Refresh token stored in localStorage (HTTP dev mode)');
|
|
173
|
+
} catch (err) {
|
|
174
|
+
console.warn('Could not store refresh token:', err);
|
|
175
|
+
}
|
|
176
|
+
} else {
|
|
177
|
+
// In production (HTTPS), refresh token should be in httpOnly cookie only
|
|
178
|
+
console.log('🔒 Refresh token managed by server httpOnly cookie (production mode)');
|
|
169
179
|
}
|
|
170
180
|
}
|
|
171
181
|
|
|
172
182
|
export function getRefreshToken() {
|
|
173
|
-
//
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
183
|
+
// For HTTP development, read from localStorage
|
|
184
|
+
if (isHttpDevelopment()) {
|
|
185
|
+
try {
|
|
186
|
+
const token = localStorage.getItem(REFRESH_TOKEN_KEY);
|
|
187
|
+
return token;
|
|
188
|
+
} catch (err) {
|
|
189
|
+
console.warn('Could not read refresh token:', err);
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// In production, refresh token is in httpOnly cookie (not accessible via JS)
|
|
195
|
+
// The refresh endpoint uses credentials: 'include' to send the cookie
|
|
196
|
+
return null;
|
|
185
197
|
}
|
|
186
198
|
|
|
187
199
|
export function clearRefreshToken() {
|
|
200
|
+
// Clear localStorage (for HTTP dev)
|
|
201
|
+
try {
|
|
202
|
+
localStorage.removeItem(REFRESH_TOKEN_KEY);
|
|
203
|
+
} catch (err) {
|
|
204
|
+
// Ignore
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Clear cookie (for production)
|
|
188
208
|
try {
|
|
189
209
|
document.cookie = `${REFRESH_COOKIE}=; Path=/; SameSite=Strict${secureAttribute()}; Expires=Thu, 01 Jan 1970 00:00:00 GMT`;
|
|
190
210
|
} catch (err) {
|
|
191
211
|
console.warn('Could not clear refresh token cookie:', err);
|
|
192
212
|
}
|
|
213
|
+
|
|
214
|
+
// Clear sessionStorage
|
|
193
215
|
try {
|
|
194
216
|
sessionStorage.removeItem(REFRESH_COOKIE);
|
|
195
217
|
} catch (err) {
|
|
196
|
-
|
|
218
|
+
// Ignore
|
|
197
219
|
}
|
|
198
220
|
}
|
|
199
221
|
|