@spidy092/auth-client 1.0.8 → 1.0.10
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 +15 -4
- package/core.js +136 -104
- package/index.js +8 -5
- package/package.json +1 -1
package/config.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
// auth-client/config.js
|
|
1
2
|
let config = {
|
|
2
3
|
clientKey: null,
|
|
3
4
|
authBaseUrl: null,
|
|
4
5
|
redirectUri: null,
|
|
5
|
-
|
|
6
|
+
accountUiUrl: null,
|
|
7
|
+
isRouter: false, // ✅ Add router flag
|
|
8
|
+
usePkce: false,
|
|
6
9
|
};
|
|
7
10
|
|
|
8
11
|
export function setConfig(customConfig = {}) {
|
|
@@ -14,13 +17,21 @@ export function setConfig(customConfig = {}) {
|
|
|
14
17
|
...config,
|
|
15
18
|
...customConfig,
|
|
16
19
|
redirectUri: customConfig.redirectUri || window.location.origin + '/callback',
|
|
20
|
+
// ✅ Auto-detect router mode
|
|
21
|
+
isRouter: customConfig.isRouter || customConfig.clientKey === 'account-ui'
|
|
17
22
|
};
|
|
23
|
+
|
|
24
|
+
console.log(`🔧 Auth Client Mode: ${config.isRouter ? 'ROUTER' : 'CLIENT'}`, {
|
|
25
|
+
clientKey: config.clientKey,
|
|
26
|
+
isRouter: config.isRouter
|
|
27
|
+
});
|
|
18
28
|
}
|
|
19
29
|
|
|
20
30
|
export function getConfig() {
|
|
21
31
|
return { ...config };
|
|
22
32
|
}
|
|
23
33
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
34
|
+
// ✅ Helper function
|
|
35
|
+
export function isRouterMode() {
|
|
36
|
+
return config.isRouter;
|
|
37
|
+
}
|
package/core.js
CHANGED
|
@@ -1,146 +1,178 @@
|
|
|
1
|
+
// auth-client/core.js
|
|
1
2
|
import { setToken, clearToken, getToken } from './token';
|
|
2
|
-
import { getConfig } from './config';
|
|
3
|
+
import { getConfig, isRouterMode } from './config';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
// ✅ Track if callback was already processed
|
|
6
|
+
let callbackProcessed = false;
|
|
7
|
+
|
|
8
|
+
export function handleCallback() {
|
|
9
|
+
const params = new URLSearchParams(window.location.search);
|
|
10
|
+
const accessToken = params.get('access_token');
|
|
11
|
+
const error = params.get('error');
|
|
12
|
+
|
|
13
|
+
console.log('🔄 Handling authentication callback:', {
|
|
14
|
+
mode: isRouterMode() ? 'ROUTER' : 'CLIENT',
|
|
15
|
+
hasAccessToken: !!accessToken,
|
|
16
|
+
error,
|
|
17
|
+
alreadyProcessed: callbackProcessed // ✅ Log if already processed
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// ✅ If already processed and we have a token, return it
|
|
21
|
+
if (callbackProcessed) {
|
|
22
|
+
const existingToken = getToken();
|
|
23
|
+
if (existingToken) {
|
|
24
|
+
console.log('🔄 Callback already processed, returning existing token');
|
|
25
|
+
return existingToken;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ✅ Mark as processed first
|
|
30
|
+
callbackProcessed = true;
|
|
31
|
+
|
|
32
|
+
// Clean up session storage (only once)
|
|
33
|
+
sessionStorage.removeItem('originalApp');
|
|
34
|
+
sessionStorage.removeItem('returnUrl');
|
|
35
|
+
|
|
36
|
+
if (error) {
|
|
37
|
+
throw new Error(`Authentication failed: ${error}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (accessToken) {
|
|
41
|
+
setToken(accessToken);
|
|
42
|
+
console.log('✅ Token set successfully');
|
|
43
|
+
return accessToken;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
throw new Error('No access token found in callback URL');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// ✅ Reset callback state when needed
|
|
50
|
+
export function resetCallbackState() {
|
|
51
|
+
callbackProcessed = false;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Your other functions remain the same...
|
|
55
|
+
export function login(clientKeyArg, redirectUriArg) {
|
|
56
|
+
// ✅ Reset callback state when starting new login
|
|
57
|
+
resetCallbackState();
|
|
58
|
+
|
|
5
59
|
const {
|
|
6
|
-
clientKey: defaultClientKey,
|
|
7
|
-
authBaseUrl,
|
|
8
|
-
redirectUri: defaultRedirectUri,
|
|
9
|
-
accountUiUrl
|
|
60
|
+
clientKey: defaultClientKey,
|
|
61
|
+
authBaseUrl,
|
|
62
|
+
redirectUri: defaultRedirectUri,
|
|
63
|
+
accountUiUrl
|
|
10
64
|
} = getConfig();
|
|
11
65
|
|
|
12
66
|
const clientKey = clientKeyArg || defaultClientKey;
|
|
13
67
|
const redirectUri = redirectUriArg || defaultRedirectUri;
|
|
14
|
-
// Removed state generation
|
|
15
68
|
|
|
16
|
-
console.log('
|
|
69
|
+
console.log('🔄 Smart Login initiated:', {
|
|
70
|
+
mode: isRouterMode() ? 'ROUTER' : 'CLIENT',
|
|
17
71
|
clientKey,
|
|
18
72
|
redirectUri
|
|
19
|
-
// Removed state from logging
|
|
20
73
|
});
|
|
21
|
-
|
|
74
|
+
|
|
22
75
|
if (!clientKey || !redirectUri) {
|
|
23
76
|
throw new Error('Missing clientKey or redirectUri');
|
|
24
77
|
}
|
|
25
78
|
|
|
26
|
-
// Store
|
|
79
|
+
// Store app info
|
|
27
80
|
sessionStorage.setItem('originalApp', clientKey);
|
|
28
81
|
sessionStorage.setItem('returnUrl', redirectUri);
|
|
29
82
|
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
console.log('Redirecting directly to auth backend:', backendLoginUrl);
|
|
36
|
-
window.location.href = backendLoginUrl;
|
|
37
|
-
return;
|
|
83
|
+
// Smart Router Logic (from my previous response)
|
|
84
|
+
if (isRouterMode()) {
|
|
85
|
+
return routerLogin(clientKey, redirectUri);
|
|
86
|
+
} else {
|
|
87
|
+
return clientLogin(clientKey, redirectUri);
|
|
38
88
|
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ✅ Router mode: Direct backend call
|
|
92
|
+
function routerLogin(clientKey, redirectUri) {
|
|
93
|
+
const { authBaseUrl } = getConfig();
|
|
94
|
+
const backendLoginUrl = `${authBaseUrl}/login/${clientKey}?redirect_uri=${encodeURIComponent(redirectUri)}`;
|
|
95
|
+
|
|
96
|
+
console.log('🏭 Router Login: Direct backend authentication', {
|
|
97
|
+
clientKey,
|
|
98
|
+
redirectUri,
|
|
99
|
+
backendUrl: backendLoginUrl
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
window.location.href = backendLoginUrl;
|
|
103
|
+
}
|
|
39
104
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
105
|
+
// ✅ Client mode: Centralized login
|
|
106
|
+
function clientLogin(clientKey, redirectUri) {
|
|
107
|
+
const { accountUiUrl } = getConfig();
|
|
108
|
+
const centralizedLoginUrl = `${accountUiUrl}/login?client=${clientKey}&redirect_uri=${encodeURIComponent(redirectUri)}`;
|
|
109
|
+
|
|
110
|
+
console.log('🔄 Client Login: Redirecting to centralized login', {
|
|
111
|
+
clientKey,
|
|
112
|
+
redirectUri,
|
|
113
|
+
centralizedUrl: centralizedLoginUrl
|
|
45
114
|
});
|
|
46
|
-
|
|
47
|
-
window.location.href =
|
|
115
|
+
|
|
116
|
+
window.location.href = centralizedLoginUrl;
|
|
48
117
|
}
|
|
49
118
|
|
|
50
119
|
export function logout() {
|
|
120
|
+
// ✅ Reset callback state on logout
|
|
121
|
+
resetCallbackState();
|
|
122
|
+
|
|
51
123
|
const { clientKey, authBaseUrl, accountUiUrl } = getConfig();
|
|
52
124
|
const token = getToken();
|
|
53
|
-
|
|
54
|
-
console.log('
|
|
125
|
+
|
|
126
|
+
console.log('🚪 Smart Logout initiated:', {
|
|
127
|
+
mode: isRouterMode() ? 'ROUTER' : 'CLIENT',
|
|
128
|
+
clientKey,
|
|
129
|
+
hasToken: !!token
|
|
130
|
+
});
|
|
55
131
|
|
|
56
132
|
// Clear local storage immediately
|
|
57
133
|
clearToken();
|
|
58
134
|
sessionStorage.clear();
|
|
59
|
-
// Don't clear localStorage completely - might break other stuff
|
|
60
|
-
// localStorage.clear(); // Remove this line
|
|
61
135
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
fetch(`${authBaseUrl}/logout/${clientKey}`, {
|
|
65
|
-
method: 'POST',
|
|
66
|
-
credentials: 'include', // ✅ CRITICAL: This sends cookies
|
|
67
|
-
headers: {
|
|
68
|
-
'Authorization': `Bearer ${token}`,
|
|
69
|
-
'Content-Type': 'application/json'
|
|
70
|
-
}
|
|
71
|
-
})
|
|
72
|
-
.then(response => response.json())
|
|
73
|
-
.then(data => {
|
|
74
|
-
console.log('Backend logout response:', data);
|
|
75
|
-
|
|
76
|
-
// If we get a Keycloak logout URL, redirect there
|
|
77
|
-
if (data.keycloakLogoutUrl) {
|
|
78
|
-
window.location.href = data.keycloakLogoutUrl;
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Otherwise redirect to login
|
|
83
|
-
window.location.href = `${accountUiUrl}/login`;
|
|
84
|
-
})
|
|
85
|
-
.catch(error => {
|
|
86
|
-
console.error('Logout error:', error);
|
|
87
|
-
// Always redirect to login even on error
|
|
88
|
-
window.location.href = `${accountUiUrl}/login`;
|
|
89
|
-
});
|
|
136
|
+
if (isRouterMode()) {
|
|
137
|
+
return routerLogout(clientKey, authBaseUrl, accountUiUrl, token);
|
|
90
138
|
} else {
|
|
91
|
-
|
|
92
|
-
window.location.href = `${accountUiUrl}/login`;
|
|
139
|
+
return clientLogout(clientKey, accountUiUrl);
|
|
93
140
|
}
|
|
94
141
|
}
|
|
95
142
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const accessToken = params.get('access_token');
|
|
100
|
-
const error = params.get('error');
|
|
101
|
-
// Removed state handling completely
|
|
102
|
-
|
|
103
|
-
console.log('Handling authentication callback:', {
|
|
104
|
-
accessToken,
|
|
105
|
-
error
|
|
106
|
-
// Removed state from logging
|
|
107
|
-
});
|
|
143
|
+
// Router logout (same as before)
|
|
144
|
+
async function routerLogout(clientKey, authBaseUrl, accountUiUrl, token) {
|
|
145
|
+
console.log('🏭 Router Logout: Backend logout for all sessions');
|
|
108
146
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
147
|
+
if (token) {
|
|
148
|
+
try {
|
|
149
|
+
const response = await fetch(`${authBaseUrl}/logout/${clientKey}`, {
|
|
150
|
+
method: 'POST',
|
|
151
|
+
credentials: 'include',
|
|
152
|
+
headers: {
|
|
153
|
+
'Authorization': `Bearer ${token}`,
|
|
154
|
+
'Content-Type': 'application/json'
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const data = await response.json();
|
|
159
|
+
console.log('Backend logout response:', data);
|
|
117
160
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
161
|
+
if (data.keycloakLogoutUrl) {
|
|
162
|
+
window.location.href = data.keycloakLogoutUrl;
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
} catch (error) {
|
|
166
|
+
console.warn('Backend logout failed:', error);
|
|
167
|
+
}
|
|
121
168
|
}
|
|
122
169
|
|
|
123
|
-
|
|
170
|
+
window.location.href = '/login';
|
|
124
171
|
}
|
|
125
172
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
method: 'POST',
|
|
132
|
-
credentials: 'include',
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
if (!response.ok) {
|
|
136
|
-
throw new Error('Refresh failed');
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const { access_token } = await response.json();
|
|
140
|
-
setToken(access_token);
|
|
141
|
-
return access_token;
|
|
142
|
-
} catch (err) {
|
|
143
|
-
clearToken();
|
|
144
|
-
throw err;
|
|
145
|
-
}
|
|
173
|
+
// Client logout (same as before)
|
|
174
|
+
function clientLogout(clientKey, accountUiUrl) {
|
|
175
|
+
console.log('🔄 Client Logout: Redirecting to centralized login');
|
|
176
|
+
const logoutUrl = `${accountUiUrl}/login?client=${clientKey}&logout=true`;
|
|
177
|
+
window.location.href = logoutUrl;
|
|
146
178
|
}
|
package/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
// auth-client/index.js
|
|
2
|
+
import { setConfig, getConfig, isRouterMode } from './config';
|
|
2
3
|
import { login, logout, handleCallback, refreshToken } from './core';
|
|
3
4
|
import { getToken, setToken, clearToken } from './token';
|
|
4
5
|
import api from './api';
|
|
@@ -8,6 +9,7 @@ export const auth = {
|
|
|
8
9
|
// 🔧 Config
|
|
9
10
|
setConfig,
|
|
10
11
|
getConfig,
|
|
12
|
+
isRouterMode, // ✅ Expose router mode check
|
|
11
13
|
|
|
12
14
|
// 🔐 Core flows
|
|
13
15
|
login,
|
|
@@ -26,23 +28,24 @@ export const auth = {
|
|
|
26
28
|
// 🧪 Utilities
|
|
27
29
|
decodeToken,
|
|
28
30
|
isTokenExpired,
|
|
29
|
-
|
|
31
|
+
|
|
30
32
|
// 🔄 Auto-refresh setup
|
|
31
33
|
startTokenRefresh: () => {
|
|
32
34
|
const interval = setInterval(async () => {
|
|
33
35
|
const token = getToken();
|
|
34
|
-
if (token && isTokenExpired(token, 300)) {
|
|
36
|
+
if (token && isTokenExpired(token, 300)) {
|
|
35
37
|
try {
|
|
36
38
|
await refreshToken();
|
|
39
|
+
console.log('🔄 Auto-refresh successful');
|
|
37
40
|
} catch (err) {
|
|
38
41
|
console.error('Auto-refresh failed:', err);
|
|
39
42
|
clearInterval(interval);
|
|
40
43
|
}
|
|
41
44
|
}
|
|
42
|
-
}, 60000);
|
|
45
|
+
}, 60000);
|
|
43
46
|
return interval;
|
|
44
47
|
}
|
|
45
48
|
};
|
|
46
49
|
|
|
47
50
|
export { AuthProvider } from './react/AuthProvider';
|
|
48
|
-
export { useAuth } from './react/useAuth';
|
|
51
|
+
export { useAuth } from './react/useAuth';
|