react-keycloak-wrapper 0.0.1-beta.7 → 0.0.1-beta.9
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.d.mts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +156 -70
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +158 -71
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -42,10 +42,12 @@ type KeycloakUser = {
|
|
|
42
42
|
groups?: string[];
|
|
43
43
|
};
|
|
44
44
|
interface KeycloakContextValue {
|
|
45
|
+
configurationName?: string;
|
|
45
46
|
isLoading: boolean;
|
|
46
47
|
isAuthenticated: boolean;
|
|
47
48
|
userInfo: KeycloakUser | null;
|
|
48
49
|
accessToken?: string;
|
|
50
|
+
refreshToken?: string;
|
|
49
51
|
idToken?: string;
|
|
50
52
|
error: Error | null;
|
|
51
53
|
sessionLost: boolean;
|
|
@@ -54,7 +56,8 @@ interface KeycloakContextValue {
|
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
interface Props {
|
|
57
|
-
|
|
59
|
+
configurationName?: string;
|
|
60
|
+
logging?: "wrapper" | "keycloak" | "both";
|
|
58
61
|
children: ReactNode;
|
|
59
62
|
config: KeycloakConfig;
|
|
60
63
|
LoadingComponent?: FC<{
|
|
@@ -74,11 +77,12 @@ declare function useKeycloak(): {
|
|
|
74
77
|
logout: (redirectUri: string) => Promise<void>;
|
|
75
78
|
isLoading: boolean;
|
|
76
79
|
isAuthenticated: boolean;
|
|
80
|
+
configurationName: string | undefined;
|
|
77
81
|
};
|
|
78
82
|
|
|
79
83
|
declare function useKeycloakUser<UserInfo = KeycloakUser>(): {
|
|
80
84
|
user: UserInfo | null;
|
|
81
|
-
|
|
85
|
+
isLoading: boolean;
|
|
82
86
|
};
|
|
83
87
|
|
|
84
88
|
declare function useKeycloakToken(): {
|
package/dist/index.d.ts
CHANGED
|
@@ -42,10 +42,12 @@ type KeycloakUser = {
|
|
|
42
42
|
groups?: string[];
|
|
43
43
|
};
|
|
44
44
|
interface KeycloakContextValue {
|
|
45
|
+
configurationName?: string;
|
|
45
46
|
isLoading: boolean;
|
|
46
47
|
isAuthenticated: boolean;
|
|
47
48
|
userInfo: KeycloakUser | null;
|
|
48
49
|
accessToken?: string;
|
|
50
|
+
refreshToken?: string;
|
|
49
51
|
idToken?: string;
|
|
50
52
|
error: Error | null;
|
|
51
53
|
sessionLost: boolean;
|
|
@@ -54,7 +56,8 @@ interface KeycloakContextValue {
|
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
interface Props {
|
|
57
|
-
|
|
59
|
+
configurationName?: string;
|
|
60
|
+
logging?: "wrapper" | "keycloak" | "both";
|
|
58
61
|
children: ReactNode;
|
|
59
62
|
config: KeycloakConfig;
|
|
60
63
|
LoadingComponent?: FC<{
|
|
@@ -74,11 +77,12 @@ declare function useKeycloak(): {
|
|
|
74
77
|
logout: (redirectUri: string) => Promise<void>;
|
|
75
78
|
isLoading: boolean;
|
|
76
79
|
isAuthenticated: boolean;
|
|
80
|
+
configurationName: string | undefined;
|
|
77
81
|
};
|
|
78
82
|
|
|
79
83
|
declare function useKeycloakUser<UserInfo = KeycloakUser>(): {
|
|
80
84
|
user: UserInfo | null;
|
|
81
|
-
|
|
85
|
+
isLoading: boolean;
|
|
82
86
|
};
|
|
83
87
|
|
|
84
88
|
declare function useKeycloakToken(): {
|
package/dist/index.js
CHANGED
|
@@ -59,6 +59,31 @@ var Logger = class {
|
|
|
59
59
|
}
|
|
60
60
|
};
|
|
61
61
|
|
|
62
|
+
// src/store/ConfigurationStore.ts
|
|
63
|
+
function getConfigurationKey(name, realm) {
|
|
64
|
+
return ["keycloak", realm, name].join(".");
|
|
65
|
+
}
|
|
66
|
+
var ConfigurationStore = class {
|
|
67
|
+
static setConfiguration(name, realm, config) {
|
|
68
|
+
sessionStorage.setItem(
|
|
69
|
+
getConfigurationKey(name, realm),
|
|
70
|
+
JSON.stringify(config)
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
static getConfiguration(name, realm) {
|
|
74
|
+
const config = sessionStorage.getItem(getConfigurationKey(name, realm));
|
|
75
|
+
return config ? JSON.parse(config) : {};
|
|
76
|
+
}
|
|
77
|
+
static clearConfiguration(name, realm) {
|
|
78
|
+
sessionStorage.removeItem(getConfigurationKey(name, realm));
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// src/utils/constants.ts
|
|
83
|
+
function getSessionStoragePrefixCN(configurationName, suffix = "") {
|
|
84
|
+
return ["keycloak", configurationName ?? "default", suffix].filter(Boolean).join("_");
|
|
85
|
+
}
|
|
86
|
+
|
|
62
87
|
// src/provider/keycloak-context.ts
|
|
63
88
|
var import_react = require("react");
|
|
64
89
|
|
|
@@ -70,14 +95,21 @@ var initialKeycloakContextValue = {
|
|
|
70
95
|
sessionLost: false,
|
|
71
96
|
login: () => Promise.reject(new Error("Not implemented")),
|
|
72
97
|
logout: () => Promise.reject(new Error("Not implemented")),
|
|
73
|
-
userInfo: null
|
|
98
|
+
userInfo: null,
|
|
99
|
+
configurationName: void 0
|
|
74
100
|
};
|
|
75
101
|
function keycloakReducer(state, action) {
|
|
76
102
|
switch (action.type) {
|
|
103
|
+
case "SET_CONFIGURATION_NAME":
|
|
104
|
+
return {
|
|
105
|
+
...state,
|
|
106
|
+
configurationName: action.payload
|
|
107
|
+
};
|
|
77
108
|
case "SET_TOKEN":
|
|
78
109
|
return {
|
|
79
110
|
...state,
|
|
80
111
|
accessToken: action.payload.accessToken,
|
|
112
|
+
refreshToken: action.payload.refreshToken,
|
|
81
113
|
idToken: action.payload.idToken,
|
|
82
114
|
isAuthenticated: action.payload.isAuthenticated ?? state.isAuthenticated
|
|
83
115
|
};
|
|
@@ -117,9 +149,9 @@ var KeycloakContext = (0, import_react.createContext)(
|
|
|
117
149
|
|
|
118
150
|
// src/provider/KeycloakProvider.tsx
|
|
119
151
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
120
|
-
var keycloak;
|
|
121
152
|
var logger = new Logger(false);
|
|
122
153
|
var KeycloakProvider = ({
|
|
154
|
+
configurationName = "default",
|
|
123
155
|
logging,
|
|
124
156
|
children,
|
|
125
157
|
config,
|
|
@@ -127,34 +159,16 @@ var KeycloakProvider = ({
|
|
|
127
159
|
AuthenticatingErrorComponent,
|
|
128
160
|
SessionLostComponent
|
|
129
161
|
}) => {
|
|
130
|
-
logger.setEnabled(logging ??
|
|
162
|
+
logger.setEnabled(["wrapper", "both"].includes(logging ?? ""));
|
|
163
|
+
const keycloakRef = (0, import_react2.useRef)();
|
|
164
|
+
const timeoutRef = (0, import_react2.useRef)();
|
|
131
165
|
const [state, dispatch] = (0, import_react2.useReducer)(
|
|
132
166
|
keycloakReducer,
|
|
133
167
|
initialKeycloakContextValue
|
|
134
168
|
);
|
|
135
|
-
const
|
|
136
|
-
if (!
|
|
137
|
-
|
|
138
|
-
url: config.url,
|
|
139
|
-
realm: config.realm,
|
|
140
|
-
clientId: config.clientId,
|
|
141
|
-
oidcProvider: config.wellKnownUrlPrefix
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
if (keycloak && !keycloak.didInitialize) {
|
|
145
|
-
keycloak.init({
|
|
146
|
-
onLoad: "check-sso",
|
|
147
|
-
checkLoginIframe: false,
|
|
148
|
-
scope: config.scope
|
|
149
|
-
}).catch((error) => {
|
|
150
|
-
logger.log("Failed to initialize Keycloak", { error });
|
|
151
|
-
dispatch({
|
|
152
|
-
type: "SET_ERROR",
|
|
153
|
-
payload: error || null
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
keycloak.onReady = (authenticated) => {
|
|
169
|
+
const watchKeycloakEvents = (0, import_react2.useCallback)(() => {
|
|
170
|
+
if (!keycloakRef.current) return;
|
|
171
|
+
keycloakRef.current.onReady = (authenticated) => {
|
|
158
172
|
logger.log("Keycloak is ready", { authenticated });
|
|
159
173
|
if (!authenticated) {
|
|
160
174
|
dispatch({
|
|
@@ -163,18 +177,24 @@ var KeycloakProvider = ({
|
|
|
163
177
|
});
|
|
164
178
|
}
|
|
165
179
|
};
|
|
166
|
-
|
|
180
|
+
keycloakRef.current.onAuthSuccess = () => {
|
|
167
181
|
logger.log("Authentication successful");
|
|
182
|
+
ConfigurationStore.setConfiguration(configurationName, config.realm, {
|
|
183
|
+
token: keycloakRef.current?.token,
|
|
184
|
+
refreshToken: keycloakRef.current?.refreshToken,
|
|
185
|
+
idToken: keycloakRef.current?.idToken
|
|
186
|
+
});
|
|
168
187
|
dispatch({
|
|
169
188
|
type: "SET_TOKEN",
|
|
170
189
|
payload: {
|
|
171
190
|
isAuthenticated: true,
|
|
172
|
-
accessToken:
|
|
173
|
-
|
|
191
|
+
accessToken: keycloakRef.current?.token,
|
|
192
|
+
refreshToken: keycloakRef.current?.refreshToken,
|
|
193
|
+
idToken: keycloakRef.current?.idToken
|
|
174
194
|
}
|
|
175
195
|
});
|
|
176
196
|
logger.log("Loading user info");
|
|
177
|
-
|
|
197
|
+
keycloakRef.current?.loadUserInfo().then((userInfo) => {
|
|
178
198
|
logger.log("User info loaded", { userInfo });
|
|
179
199
|
dispatch({
|
|
180
200
|
type: "SET_USER_INFO",
|
|
@@ -186,14 +206,14 @@ var KeycloakProvider = ({
|
|
|
186
206
|
payload: false
|
|
187
207
|
});
|
|
188
208
|
});
|
|
189
|
-
setInterval(
|
|
209
|
+
timeoutRef.current = setInterval(
|
|
190
210
|
() => {
|
|
191
|
-
|
|
211
|
+
keycloakRef.current?.updateToken(config.refreshSecondsBeforeTokenExpires ?? 120).then((refreshed) => {
|
|
192
212
|
if (!refreshed) {
|
|
193
213
|
logger.log(
|
|
194
214
|
"Token is still valid, no need to refresh",
|
|
195
215
|
new Date(
|
|
196
|
-
(
|
|
216
|
+
(keycloakRef.current?.tokenParsed?.exp ?? 0) * 1e3
|
|
197
217
|
).toLocaleTimeString()
|
|
198
218
|
);
|
|
199
219
|
}
|
|
@@ -202,58 +222,111 @@ var KeycloakProvider = ({
|
|
|
202
222
|
(config.tokenRefreshIntervalInSeconds ?? 10) * 1e3
|
|
203
223
|
);
|
|
204
224
|
};
|
|
205
|
-
|
|
225
|
+
keycloakRef.current.onAuthLogout = () => {
|
|
206
226
|
logger.log("Session lost");
|
|
207
227
|
dispatch({
|
|
208
228
|
type: "SET_SESSION_LOST",
|
|
209
229
|
payload: true
|
|
210
230
|
});
|
|
211
231
|
};
|
|
212
|
-
|
|
232
|
+
keycloakRef.current.onAuthError = (error) => {
|
|
213
233
|
logger.log("Authentication error", { error });
|
|
214
234
|
dispatch({
|
|
215
235
|
type: "SET_ERROR",
|
|
216
236
|
payload: error || null
|
|
217
237
|
});
|
|
218
238
|
};
|
|
219
|
-
|
|
239
|
+
keycloakRef.current.onAuthRefreshError = () => {
|
|
220
240
|
logger.log("Token refresh error");
|
|
221
241
|
dispatch({
|
|
222
242
|
type: "SET_ERROR",
|
|
223
243
|
payload: new Error("Token refresh error") || null
|
|
224
244
|
});
|
|
225
245
|
};
|
|
226
|
-
|
|
227
|
-
logger.log("Token refresh successful",
|
|
246
|
+
keycloakRef.current.onAuthRefreshSuccess = () => {
|
|
247
|
+
logger.log("Token refresh successful", keycloakRef.current?.token);
|
|
248
|
+
ConfigurationStore.setConfiguration(configurationName, config.realm, {
|
|
249
|
+
token: keycloakRef.current?.token,
|
|
250
|
+
refreshToken: keycloakRef.current?.refreshToken,
|
|
251
|
+
idToken: keycloakRef.current?.idToken
|
|
252
|
+
});
|
|
228
253
|
dispatch({
|
|
229
254
|
type: "SET_TOKEN",
|
|
230
255
|
payload: {
|
|
231
256
|
isAuthenticated: true,
|
|
232
|
-
accessToken:
|
|
233
|
-
|
|
257
|
+
accessToken: keycloakRef.current?.token,
|
|
258
|
+
refreshToken: keycloakRef.current?.refreshToken,
|
|
259
|
+
idToken: keycloakRef.current?.idToken
|
|
234
260
|
}
|
|
235
261
|
});
|
|
236
262
|
};
|
|
237
263
|
}, [
|
|
238
|
-
config.clientId,
|
|
239
264
|
config.realm,
|
|
240
265
|
config.refreshSecondsBeforeTokenExpires,
|
|
241
|
-
config.scope,
|
|
242
266
|
config.tokenRefreshIntervalInSeconds,
|
|
267
|
+
configurationName
|
|
268
|
+
]);
|
|
269
|
+
const initiateKeycloak = (0, import_react2.useCallback)(() => {
|
|
270
|
+
if (keycloakRef.current && !keycloakRef.current.didInitialize) {
|
|
271
|
+
keycloakRef.current.init({
|
|
272
|
+
onLoad: "check-sso",
|
|
273
|
+
checkLoginIframe: false,
|
|
274
|
+
scope: config.scope,
|
|
275
|
+
enableLogging: ["keycloak", "both"].includes(logging ?? ""),
|
|
276
|
+
...ConfigurationStore.getConfiguration(
|
|
277
|
+
configurationName,
|
|
278
|
+
config.realm
|
|
279
|
+
)
|
|
280
|
+
}).catch((error) => {
|
|
281
|
+
logger.log("Failed to initialize Keycloak", { error });
|
|
282
|
+
dispatch({
|
|
283
|
+
type: "SET_ERROR",
|
|
284
|
+
payload: error || null
|
|
285
|
+
});
|
|
286
|
+
dispatch({
|
|
287
|
+
type: "SET_LOADING",
|
|
288
|
+
payload: false
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
} else if (!keycloakRef.current) {
|
|
292
|
+
keycloakRef.current = new import_keycloak_js.default({
|
|
293
|
+
url: config.url,
|
|
294
|
+
realm: config.realm,
|
|
295
|
+
clientId: config.clientId,
|
|
296
|
+
oidcProvider: config.wellKnownUrlPrefix
|
|
297
|
+
});
|
|
298
|
+
watchKeycloakEvents();
|
|
299
|
+
dispatch({
|
|
300
|
+
type: "SET_CONFIGURATION_NAME",
|
|
301
|
+
payload: configurationName
|
|
302
|
+
});
|
|
303
|
+
return true;
|
|
304
|
+
}
|
|
305
|
+
}, [
|
|
306
|
+
config.clientId,
|
|
307
|
+
config.realm,
|
|
308
|
+
config.scope,
|
|
243
309
|
config.url,
|
|
244
|
-
config.wellKnownUrlPrefix
|
|
310
|
+
config.wellKnownUrlPrefix,
|
|
311
|
+
configurationName,
|
|
312
|
+
logging,
|
|
313
|
+
watchKeycloakEvents
|
|
245
314
|
]);
|
|
246
315
|
(0, import_react2.useLayoutEffect)(() => {
|
|
247
316
|
initiateKeycloak();
|
|
317
|
+
return () => {
|
|
318
|
+
if (keycloakRef.current?.didInitialize && keycloakRef.current.authenticated && timeoutRef.current !== void 0) {
|
|
319
|
+
logger.log("Cleaning up Keycloak refresh token");
|
|
320
|
+
clearInterval(timeoutRef.current);
|
|
321
|
+
timeoutRef.current = void 0;
|
|
322
|
+
}
|
|
323
|
+
};
|
|
248
324
|
}, [initiateKeycloak]);
|
|
249
325
|
(0, import_react2.useLayoutEffect)(() => {
|
|
250
|
-
logger.log("Checando redirecionamento ap\xF3s autentica\xE7\xE3o", {
|
|
251
|
-
isAuthenticated: state.isAuthenticated,
|
|
252
|
-
isLoading: state.isLoading,
|
|
253
|
-
redirectUri: config.redirectUri
|
|
254
|
-
});
|
|
255
326
|
if (!state.isLoading && state.isAuthenticated && config.redirectUri && window.location.href.startsWith(config.redirectUri)) {
|
|
256
|
-
const returnUrl = sessionStorage.getItem(
|
|
327
|
+
const returnUrl = sessionStorage.getItem(
|
|
328
|
+
getSessionStoragePrefixCN(configurationName, "return_url")
|
|
329
|
+
) || "/";
|
|
257
330
|
if (!window.location.href.endsWith(returnUrl)) {
|
|
258
331
|
logger.log("Redirecionando para a URL original ap\xF3s autentica\xE7\xE3o", {
|
|
259
332
|
returnUrl,
|
|
@@ -265,31 +338,44 @@ var KeycloakProvider = ({
|
|
|
265
338
|
window.location.origin + returnUrl
|
|
266
339
|
);
|
|
267
340
|
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
268
|
-
sessionStorage.removeItem(
|
|
341
|
+
sessionStorage.removeItem(
|
|
342
|
+
getSessionStoragePrefixCN(configurationName, "return_url")
|
|
343
|
+
);
|
|
269
344
|
}
|
|
270
345
|
}
|
|
271
|
-
}, [
|
|
346
|
+
}, [
|
|
347
|
+
config.redirectUri,
|
|
348
|
+
configurationName,
|
|
349
|
+
state.isAuthenticated,
|
|
350
|
+
state.isLoading
|
|
351
|
+
]);
|
|
272
352
|
const handleLogin = (0, import_react2.useCallback)(
|
|
273
353
|
(redirectUri) => {
|
|
274
354
|
dispatch({
|
|
275
355
|
type: "SET_LOADING",
|
|
276
356
|
payload: true
|
|
277
357
|
});
|
|
278
|
-
return
|
|
358
|
+
return keycloakRef.current?.login({
|
|
279
359
|
redirectUri: redirectUri ?? config.redirectUri
|
|
280
360
|
}) ?? Promise.reject();
|
|
281
361
|
},
|
|
282
362
|
[config.redirectUri]
|
|
283
363
|
);
|
|
284
|
-
const handleLogout = (0, import_react2.useCallback)(
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
364
|
+
const handleLogout = (0, import_react2.useCallback)(
|
|
365
|
+
(redirectUriAfterLogout) => {
|
|
366
|
+
dispatch({
|
|
367
|
+
type: "SET_LOADING",
|
|
368
|
+
payload: true
|
|
369
|
+
});
|
|
370
|
+
ConfigurationStore.clearConfiguration(configurationName, config.realm);
|
|
371
|
+
return keycloakRef.current?.logout({
|
|
372
|
+
redirectUri: redirectUriAfterLogout
|
|
373
|
+
}) ?? Promise.reject();
|
|
374
|
+
},
|
|
375
|
+
[config.realm, configurationName]
|
|
376
|
+
);
|
|
377
|
+
const shouldRenderError = state?.error && !state.isLoading && AuthenticatingErrorComponent;
|
|
378
|
+
const shouldRenderSessionLost = state.sessionLost && !state.isLoading && !state?.error && SessionLostComponent;
|
|
293
379
|
const shouldRenderChildren = !state.isLoading && !state.error && !state.sessionLost;
|
|
294
380
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
295
381
|
KeycloakContext.Provider,
|
|
@@ -301,9 +387,9 @@ var KeycloakProvider = ({
|
|
|
301
387
|
},
|
|
302
388
|
children: [
|
|
303
389
|
shouldRenderChildren && children,
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
390
|
+
shouldRenderSessionLost && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SessionLostComponent, {}),
|
|
391
|
+
shouldRenderError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AuthenticatingErrorComponent, { error: state?.error }),
|
|
392
|
+
LoadingComponent && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoadingComponent, { opened: state?.isLoading })
|
|
307
393
|
]
|
|
308
394
|
}
|
|
309
395
|
);
|
|
@@ -317,26 +403,26 @@ function useKeycloak() {
|
|
|
317
403
|
login: ctx.login,
|
|
318
404
|
logout: ctx.logout,
|
|
319
405
|
isLoading: ctx.isLoading,
|
|
320
|
-
isAuthenticated: ctx.isAuthenticated
|
|
406
|
+
isAuthenticated: ctx.isAuthenticated,
|
|
407
|
+
configurationName: ctx.configurationName
|
|
321
408
|
};
|
|
322
409
|
}
|
|
323
410
|
|
|
324
411
|
// src/components/KeycloakSecure.tsx
|
|
325
|
-
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
326
412
|
var KeycloakSecure = ({
|
|
327
413
|
children
|
|
328
414
|
}) => {
|
|
329
|
-
const { isAuthenticated, login, isLoading } = useKeycloak();
|
|
415
|
+
const { isAuthenticated, login, isLoading, configurationName } = useKeycloak();
|
|
330
416
|
if (isLoading) return null;
|
|
331
417
|
if (!isAuthenticated) {
|
|
332
418
|
sessionStorage.setItem(
|
|
333
|
-
"
|
|
419
|
+
getSessionStoragePrefixCN(configurationName, "return_url"),
|
|
334
420
|
window.location.pathname + window.location.search
|
|
335
421
|
);
|
|
336
422
|
login();
|
|
337
423
|
return null;
|
|
338
424
|
}
|
|
339
|
-
return
|
|
425
|
+
return children;
|
|
340
426
|
};
|
|
341
427
|
|
|
342
428
|
// src/hooks/useKeycloakUser.ts
|
|
@@ -345,7 +431,7 @@ function useKeycloakUser() {
|
|
|
345
431
|
const ctx = (0, import_react4.useContext)(KeycloakContext);
|
|
346
432
|
return {
|
|
347
433
|
user: ctx?.userInfo,
|
|
348
|
-
|
|
434
|
+
isLoading: ctx?.isLoading
|
|
349
435
|
};
|
|
350
436
|
}
|
|
351
437
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/provider/KeycloakProvider.tsx","../src/components/Logger.ts","../src/provider/keycloak-context.ts","../src/provider/keycloak-reducer.ts","../src/hooks/useKeycloak.ts","../src/components/KeycloakSecure.tsx","../src/hooks/useKeycloakUser.ts","../src/hooks/useKeycloakToken.ts"],"sourcesContent":["export * from \"./provider/KeycloakProvider\";\nexport * from \"./components/KeycloakSecure\";\n\nexport * from \"./hooks/useKeycloak\";\nexport * from \"./hooks/useKeycloakUser\";\nexport * from \"./hooks/useKeycloakToken\";\n\nexport * from \"./types\";\n","import Keycloak from \"keycloak-js\";\nimport React, {\n FC,\n ReactNode,\n useCallback,\n useLayoutEffect,\n useReducer,\n} from \"react\";\nimport Logger from \"../components/Logger\";\nimport { KeycloakConfig, KeycloakUser } from \"../types\";\nimport { KeycloakContext } from \"./keycloak-context\";\nimport {\n initialKeycloakContextValue,\n keycloakReducer,\n} from \"./keycloak-reducer\";\n\ninterface Props {\n logging?: boolean;\n children: ReactNode;\n config: KeycloakConfig;\n LoadingComponent?: FC<{ opened: boolean }>;\n AuthenticatingErrorComponent?: FC<{\n error: Error | null;\n }>;\n SessionLostComponent?: FC;\n}\n\nlet keycloak: Keycloak | undefined;\nconst logger = new Logger(false);\nexport const KeycloakProvider: React.FC<Props> = ({\n logging,\n children,\n config,\n LoadingComponent,\n AuthenticatingErrorComponent,\n SessionLostComponent,\n}) => {\n logger.setEnabled(logging ?? false);\n\n const [state, dispatch] = useReducer(\n keycloakReducer,\n initialKeycloakContextValue,\n );\n\n const initiateKeycloak = useCallback(() => {\n if (!keycloak) {\n keycloak = new Keycloak({\n url: config.url,\n realm: config.realm,\n clientId: config.clientId,\n oidcProvider: config.wellKnownUrlPrefix,\n });\n }\n\n if (keycloak && !keycloak.didInitialize) {\n keycloak\n .init({\n onLoad: \"check-sso\",\n checkLoginIframe: false,\n scope: config.scope,\n })\n .catch((error) => {\n logger.log(\"Failed to initialize Keycloak\", { error });\n dispatch({\n type: \"SET_ERROR\",\n payload: error || null,\n });\n });\n }\n\n keycloak.onReady = (authenticated) => {\n logger.log(\"Keycloak is ready\", { authenticated });\n\n if (!authenticated) {\n dispatch({\n type: \"SET_LOADING\",\n payload: false,\n });\n }\n };\n\n keycloak.onAuthSuccess = () => {\n logger.log(\"Authentication successful\");\n\n dispatch({\n type: \"SET_TOKEN\",\n payload: {\n isAuthenticated: true,\n accessToken: keycloak?.token,\n idToken: keycloak?.idToken,\n },\n });\n\n logger.log(\"Loading user info\");\n keycloak\n ?.loadUserInfo()\n .then((userInfo) => {\n logger.log(\"User info loaded\", { userInfo });\n dispatch({\n type: \"SET_USER_INFO\",\n payload: userInfo as unknown as KeycloakUser,\n });\n })\n .finally(() => {\n dispatch({\n type: \"SET_LOADING\",\n payload: false,\n });\n });\n\n setInterval(\n () => {\n keycloak\n ?.updateToken(config.refreshSecondsBeforeTokenExpires ?? 120)\n .then((refreshed) => {\n if (!refreshed) {\n logger.log(\n \"Token is still valid, no need to refresh\",\n new Date(\n (keycloak?.tokenParsed?.exp ?? 0) * 1000,\n ).toLocaleTimeString(),\n );\n }\n });\n },\n (config.tokenRefreshIntervalInSeconds ?? 10) * 1000,\n );\n };\n\n keycloak.onAuthLogout = () => {\n logger.log(\"Session lost\");\n dispatch({\n type: \"SET_SESSION_LOST\",\n payload: true,\n });\n };\n\n keycloak.onAuthError = (error) => {\n logger.log(\"Authentication error\", { error });\n\n dispatch({\n type: \"SET_ERROR\",\n payload: error || null,\n });\n };\n\n keycloak.onAuthRefreshError = () => {\n logger.log(\"Token refresh error\");\n\n dispatch({\n type: \"SET_ERROR\",\n payload: new Error(\"Token refresh error\") || null,\n });\n };\n\n keycloak.onAuthRefreshSuccess = () => {\n logger.log(\"Token refresh successful\", keycloak?.token);\n\n dispatch({\n type: \"SET_TOKEN\",\n payload: {\n isAuthenticated: true,\n accessToken: keycloak?.token,\n idToken: keycloak?.idToken,\n },\n });\n };\n }, [\n config.clientId,\n config.realm,\n config.refreshSecondsBeforeTokenExpires,\n config.scope,\n config.tokenRefreshIntervalInSeconds,\n config.url,\n config.wellKnownUrlPrefix,\n ]);\n\n useLayoutEffect(() => {\n initiateKeycloak();\n }, [initiateKeycloak]);\n\n useLayoutEffect(() => {\n logger.log(\"Checando redirecionamento após autenticação\", {\n isAuthenticated: state.isAuthenticated,\n isLoading: state.isLoading,\n redirectUri: config.redirectUri,\n });\n\n if (\n !state.isLoading &&\n state.isAuthenticated &&\n config.redirectUri &&\n window.location.href.startsWith(config.redirectUri)\n ) {\n const returnUrl = sessionStorage.getItem(\"keycloak_return_url\") || \"/\";\n if (!window.location.href.endsWith(returnUrl)) {\n logger.log(\"Redirecionando para a URL original após autenticação\", {\n returnUrl,\n origin: window.location.origin,\n });\n\n // Redireciona para a URL original\n window.history.replaceState(\n { keycloak_redirected: true },\n \"\",\n window.location.origin + returnUrl,\n );\n window.dispatchEvent(new PopStateEvent(\"popstate\"));\n sessionStorage.removeItem(\"keycloak_return_url\");\n }\n }\n }, [config.redirectUri, state.isAuthenticated, state.isLoading]);\n\n const handleLogin = useCallback(\n (redirectUri?: string) => {\n dispatch({\n type: \"SET_LOADING\",\n payload: true,\n });\n\n return (\n keycloak?.login({\n redirectUri: redirectUri ?? config.redirectUri,\n }) ?? Promise.reject()\n );\n },\n [config.redirectUri],\n );\n\n const handleLogout = useCallback((redirectUriAfterLogout: string) => {\n dispatch({\n type: \"SET_LOADING\",\n payload: true,\n });\n\n return (\n keycloak?.logout({\n redirectUri: redirectUriAfterLogout,\n }) ?? Promise.reject()\n );\n }, []);\n\n const shouldRenderChildren =\n !state.isLoading && !state.error && !state.sessionLost;\n\n return (\n <KeycloakContext.Provider\n value={{\n ...state,\n login: handleLogin,\n logout: handleLogout,\n }}\n >\n {shouldRenderChildren && children}\n\n {LoadingComponent && <LoadingComponent opened={state?.isLoading} />}\n {AuthenticatingErrorComponent && state?.error && (\n <AuthenticatingErrorComponent error={state?.error} />\n )}\n {SessionLostComponent && state?.sessionLost && <SessionLostComponent />}\n </KeycloakContext.Provider>\n );\n};\n","export default class Logger {\n enabled: boolean = false;\n\n constructor(enabled: boolean = false) {\n this.enabled = enabled;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n log(...data: any[]) {\n if (this.enabled) {\n console.log(\"[react-keycloak-wrapper]\", ...data);\n }\n }\n\n setEnabled(enabled: boolean) {\n this.enabled = enabled;\n }\n}\n","import { createContext } from \"react\";\nimport { KeycloakContextValue } from \"../types\";\nimport { initialKeycloakContextValue } from \"./keycloak-reducer\";\n\nexport const KeycloakContext = createContext<KeycloakContextValue>(\n initialKeycloakContextValue,\n);\n","import { KeycloakError } from \"keycloak-js\";\nimport { KeycloakContextValue, KeycloakUser } from \"../types\";\n\ntype GenericAction<T extends string, P = undefined> = { type: T; payload: P };\n\nexport type KeycloakAction =\n | GenericAction<\n \"SET_TOKEN\",\n { accessToken?: string; idToken?: string; isAuthenticated?: boolean }\n >\n | GenericAction<\"SET_LOADING\", boolean>\n | GenericAction<\"SET_ERROR\", Error | KeycloakError | null>\n | GenericAction<\"SET_SESSION_LOST\", boolean>\n | GenericAction<\"SET_USER_INFO\", KeycloakUser | null>;\n\nexport const initialKeycloakContextValue: KeycloakContextValue = {\n error: null,\n isAuthenticated: false,\n isLoading: true,\n sessionLost: false,\n login: () => Promise.reject(new Error(\"Not implemented\")),\n logout: () => Promise.reject(new Error(\"Not implemented\")),\n userInfo: null,\n};\n\nexport function keycloakReducer(\n state: KeycloakContextValue,\n action: KeycloakAction,\n): KeycloakContextValue {\n switch (action.type) {\n case \"SET_TOKEN\":\n return {\n ...state,\n accessToken: action.payload.accessToken,\n idToken: action.payload.idToken,\n isAuthenticated:\n action.payload.isAuthenticated ?? state.isAuthenticated,\n };\n case \"SET_LOADING\":\n return {\n ...state,\n isLoading: action.payload,\n };\n case \"SET_ERROR\":\n return {\n ...state,\n error:\n !action.payload || action.payload instanceof Error\n ? action.payload\n : new Error(\n String(\n action.payload.error || action.payload.error_description,\n ),\n ),\n };\n case \"SET_SESSION_LOST\":\n return {\n ...state,\n sessionLost: action.payload,\n };\n case \"SET_USER_INFO\":\n return {\n ...state,\n userInfo: action.payload,\n };\n\n default:\n return state;\n }\n}\n","import { useContext } from \"react\";\nimport { KeycloakContext } from \"../provider/keycloak-context\";\n\nexport function useKeycloak() {\n const ctx = useContext(KeycloakContext);\n\n return {\n login: ctx.login,\n logout: ctx.logout,\n isLoading: ctx.isLoading,\n isAuthenticated: ctx.isAuthenticated,\n };\n}\n","import React from \"react\";\nimport { useKeycloak } from \"../hooks/useKeycloak\";\n\nexport const KeycloakSecure: React.FC<React.PropsWithChildren> = ({\n children,\n}) => {\n const { isAuthenticated, login, isLoading } = useKeycloak();\n\n if (isLoading) return null;\n\n if (!isAuthenticated) {\n // Salva a URL atual antes de redirecionar\n sessionStorage.setItem(\n \"keycloak_return_url\",\n window.location.pathname + window.location.search,\n );\n\n // Redireciona para o Keycloak com callback fixo\n login(); // Usa o redirectUri configurado (ex: /authorization)\n return null;\n }\n\n return <>{children}</>;\n};\n","import { useContext } from \"react\";\nimport { KeycloakContext } from \"../provider/keycloak-context\";\nimport { KeycloakUser } from \"../types\";\n\nexport function useKeycloakUser<UserInfo = KeycloakUser>() {\n const ctx = useContext(KeycloakContext);\n\n return {\n user: ctx?.userInfo as UserInfo | null,\n loading: ctx?.isLoading,\n };\n}\n","import { useContext } from \"react\";\nimport { KeycloakContext } from \"../provider/keycloak-context\";\n\nexport function useKeycloakToken() {\n const ctx = useContext(KeycloakContext);\n\n return {\n accessToken: ctx.accessToken,\n idToken: ctx.idToken,\n };\n}\n"],"mappings":"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","names":["import_react","Keycloak","import_react","import_jsx_runtime","import_react","import_react"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/provider/KeycloakProvider.tsx","../src/components/Logger.ts","../src/store/ConfigurationStore.ts","../src/utils/constants.ts","../src/provider/keycloak-context.ts","../src/provider/keycloak-reducer.ts","../src/hooks/useKeycloak.ts","../src/components/KeycloakSecure.tsx","../src/hooks/useKeycloakUser.ts","../src/hooks/useKeycloakToken.ts"],"sourcesContent":["export * from \"./provider/KeycloakProvider\";\nexport * from \"./components/KeycloakSecure\";\n\nexport * from \"./hooks/useKeycloak\";\nexport * from \"./hooks/useKeycloakUser\";\nexport * from \"./hooks/useKeycloakToken\";\n\nexport * from \"./types\";\n","import Keycloak from \"keycloak-js\";\nimport React, {\n FC,\n ReactNode,\n useCallback,\n useLayoutEffect,\n useReducer,\n useRef,\n} from \"react\";\nimport Logger from \"../components/Logger\";\nimport ConfigurationStore from \"../store/ConfigurationStore\";\nimport { KeycloakConfig, KeycloakUser } from \"../types\";\nimport { getSessionStoragePrefixCN } from \"../utils/constants\";\nimport { KeycloakContext } from \"./keycloak-context\";\nimport {\n initialKeycloakContextValue,\n keycloakReducer,\n} from \"./keycloak-reducer\";\n\ninterface Props {\n configurationName?: string;\n logging?: \"wrapper\" | \"keycloak\" | \"both\";\n children: ReactNode;\n config: KeycloakConfig;\n LoadingComponent?: FC<{ opened: boolean }>;\n AuthenticatingErrorComponent?: FC<{\n error: Error | null;\n }>;\n SessionLostComponent?: FC;\n}\n\nconst logger = new Logger(false);\nexport const KeycloakProvider: React.FC<Props> = ({\n configurationName = \"default\",\n logging,\n children,\n config,\n LoadingComponent,\n AuthenticatingErrorComponent,\n SessionLostComponent,\n}) => {\n logger.setEnabled([\"wrapper\", \"both\"].includes(logging ?? \"\"));\n\n const keycloakRef = useRef<Keycloak>();\n const timeoutRef = useRef<NodeJS.Timeout>();\n\n const [state, dispatch] = useReducer(\n keycloakReducer,\n initialKeycloakContextValue,\n );\n\n const watchKeycloakEvents = useCallback(() => {\n if (!keycloakRef.current) return;\n\n keycloakRef.current.onReady = (authenticated) => {\n logger.log(\"Keycloak is ready\", { authenticated });\n\n if (!authenticated) {\n dispatch({\n type: \"SET_LOADING\",\n payload: false,\n });\n }\n };\n\n keycloakRef.current.onAuthSuccess = () => {\n logger.log(\"Authentication successful\");\n\n ConfigurationStore.setConfiguration(configurationName, config.realm, {\n token: keycloakRef.current?.token,\n refreshToken: keycloakRef.current?.refreshToken,\n idToken: keycloakRef.current?.idToken,\n });\n\n dispatch({\n type: \"SET_TOKEN\",\n payload: {\n isAuthenticated: true,\n accessToken: keycloakRef.current?.token,\n refreshToken: keycloakRef.current?.refreshToken,\n idToken: keycloakRef.current?.idToken,\n },\n });\n\n logger.log(\"Loading user info\");\n keycloakRef.current\n ?.loadUserInfo()\n .then((userInfo) => {\n logger.log(\"User info loaded\", { userInfo });\n dispatch({\n type: \"SET_USER_INFO\",\n payload: userInfo as unknown as KeycloakUser,\n });\n })\n .finally(() => {\n dispatch({\n type: \"SET_LOADING\",\n payload: false,\n });\n });\n\n timeoutRef.current = setInterval(\n () => {\n keycloakRef.current\n ?.updateToken(config.refreshSecondsBeforeTokenExpires ?? 120)\n .then((refreshed) => {\n if (!refreshed) {\n logger.log(\n \"Token is still valid, no need to refresh\",\n new Date(\n (keycloakRef.current?.tokenParsed?.exp ?? 0) * 1000,\n ).toLocaleTimeString(),\n );\n }\n });\n },\n (config.tokenRefreshIntervalInSeconds ?? 10) * 1000,\n );\n };\n\n keycloakRef.current.onAuthLogout = () => {\n logger.log(\"Session lost\");\n dispatch({\n type: \"SET_SESSION_LOST\",\n payload: true,\n });\n };\n\n keycloakRef.current.onAuthError = (error) => {\n logger.log(\"Authentication error\", { error });\n\n dispatch({\n type: \"SET_ERROR\",\n payload: error || null,\n });\n };\n\n keycloakRef.current.onAuthRefreshError = () => {\n logger.log(\"Token refresh error\");\n\n dispatch({\n type: \"SET_ERROR\",\n payload: new Error(\"Token refresh error\") || null,\n });\n };\n\n keycloakRef.current.onAuthRefreshSuccess = () => {\n logger.log(\"Token refresh successful\", keycloakRef.current?.token);\n\n ConfigurationStore.setConfiguration(configurationName, config.realm, {\n token: keycloakRef.current?.token,\n refreshToken: keycloakRef.current?.refreshToken,\n idToken: keycloakRef.current?.idToken,\n });\n\n dispatch({\n type: \"SET_TOKEN\",\n payload: {\n isAuthenticated: true,\n accessToken: keycloakRef.current?.token,\n refreshToken: keycloakRef.current?.refreshToken,\n idToken: keycloakRef.current?.idToken,\n },\n });\n };\n }, [\n config.realm,\n config.refreshSecondsBeforeTokenExpires,\n config.tokenRefreshIntervalInSeconds,\n configurationName,\n ]);\n\n const initiateKeycloak = useCallback(() => {\n if (keycloakRef.current && !keycloakRef.current.didInitialize) {\n keycloakRef.current\n .init({\n onLoad: \"check-sso\",\n checkLoginIframe: false,\n scope: config.scope,\n enableLogging: [\"keycloak\", \"both\"].includes(logging ?? \"\"),\n ...ConfigurationStore.getConfiguration(\n configurationName,\n config.realm,\n ),\n })\n .catch((error) => {\n logger.log(\"Failed to initialize Keycloak\", { error });\n dispatch({\n type: \"SET_ERROR\",\n payload: error || null,\n });\n dispatch({\n type: \"SET_LOADING\",\n payload: false,\n });\n });\n } else if (!keycloakRef.current) {\n keycloakRef.current = new Keycloak({\n url: config.url,\n realm: config.realm,\n clientId: config.clientId,\n oidcProvider: config.wellKnownUrlPrefix,\n });\n\n watchKeycloakEvents();\n\n dispatch({\n type: \"SET_CONFIGURATION_NAME\",\n payload: configurationName,\n });\n\n return true;\n }\n }, [\n config.clientId,\n config.realm,\n config.scope,\n config.url,\n config.wellKnownUrlPrefix,\n configurationName,\n logging,\n watchKeycloakEvents,\n ]);\n\n useLayoutEffect(() => {\n initiateKeycloak();\n\n return () => {\n if (\n keycloakRef.current?.didInitialize &&\n keycloakRef.current.authenticated &&\n timeoutRef.current !== undefined\n ) {\n logger.log(\"Cleaning up Keycloak refresh token\");\n clearInterval(timeoutRef.current);\n timeoutRef.current = undefined;\n }\n };\n }, [initiateKeycloak]);\n\n useLayoutEffect(() => {\n if (\n !state.isLoading &&\n state.isAuthenticated &&\n config.redirectUri &&\n window.location.href.startsWith(config.redirectUri)\n ) {\n const returnUrl =\n sessionStorage.getItem(\n getSessionStoragePrefixCN(configurationName, \"return_url\"),\n ) || \"/\";\n if (!window.location.href.endsWith(returnUrl)) {\n logger.log(\"Redirecionando para a URL original após autenticação\", {\n returnUrl,\n origin: window.location.origin,\n });\n\n // Redireciona para a URL original\n window.history.replaceState(\n { keycloak_redirected: true },\n \"\",\n window.location.origin + returnUrl,\n );\n \n // Dispara um evento para que o ReactRouter detecte\n window.dispatchEvent(new PopStateEvent(\"popstate\"));\n sessionStorage.removeItem(\n getSessionStoragePrefixCN(configurationName, \"return_url\"),\n );\n }\n }\n }, [\n config.redirectUri,\n configurationName,\n state.isAuthenticated,\n state.isLoading,\n ]);\n\n const handleLogin = useCallback(\n (redirectUri?: string) => {\n dispatch({\n type: \"SET_LOADING\",\n payload: true,\n });\n\n return (\n keycloakRef.current?.login({\n redirectUri: redirectUri ?? config.redirectUri,\n }) ?? Promise.reject()\n );\n },\n [config.redirectUri],\n );\n\n const handleLogout = useCallback(\n (redirectUriAfterLogout: string) => {\n dispatch({\n type: \"SET_LOADING\",\n payload: true,\n });\n\n ConfigurationStore.clearConfiguration(configurationName, config.realm);\n\n return (\n keycloakRef.current?.logout({\n redirectUri: redirectUriAfterLogout,\n }) ?? Promise.reject()\n );\n },\n [config.realm, configurationName],\n );\n\n // carregando > erro > sessão perdida > children\n\n const shouldRenderError =\n state?.error && !state.isLoading && AuthenticatingErrorComponent;\n\n const shouldRenderSessionLost =\n state.sessionLost &&\n !state.isLoading &&\n !state?.error &&\n SessionLostComponent;\n\n const shouldRenderChildren =\n !state.isLoading && !state.error && !state.sessionLost;\n\n return (\n <KeycloakContext.Provider\n value={{\n ...state,\n login: handleLogin,\n logout: handleLogout,\n }}\n >\n {shouldRenderChildren && children}\n\n {shouldRenderSessionLost && <SessionLostComponent />}\n\n {shouldRenderError && (\n <AuthenticatingErrorComponent error={state?.error} />\n )}\n\n {LoadingComponent && <LoadingComponent opened={state?.isLoading} />}\n </KeycloakContext.Provider>\n );\n};\n","export default class Logger {\n enabled: boolean = false;\n\n constructor(enabled: boolean = false) {\n this.enabled = enabled;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n log(...data: any[]) {\n if (this.enabled) {\n console.log(\"[react-keycloak-wrapper]\", ...data);\n }\n }\n\n setEnabled(enabled: boolean) {\n this.enabled = enabled;\n }\n}\n","type ConfigurationTokens = {\n idToken?: string;\n token?: string;\n refreshToken?: string;\n};\n\nfunction getConfigurationKey(name: string, realm: string) {\n return [\"keycloak\", realm, name].join(\".\");\n}\n\nexport default class ConfigurationStore {\n public static setConfiguration(\n name: string,\n realm: string,\n config: ConfigurationTokens,\n ): void {\n sessionStorage.setItem(\n getConfigurationKey(name, realm),\n JSON.stringify(config),\n );\n }\n\n public static getConfiguration(\n name: string,\n realm: string,\n ): ConfigurationTokens | object {\n const config = sessionStorage.getItem(getConfigurationKey(name, realm));\n return config ? (JSON.parse(config) as ConfigurationTokens) : {};\n }\n\n public static clearConfiguration(name: string, realm: string): void {\n sessionStorage.removeItem(getConfigurationKey(name, realm));\n }\n}\n","export function getSessionStoragePrefixCN(\n configurationName?: string,\n suffix = \"\",\n) {\n return [\"keycloak\", configurationName ?? \"default\", suffix]\n .filter(Boolean)\n .join(\"_\");\n}\n","import { createContext } from \"react\";\nimport { KeycloakContextValue } from \"../types\";\nimport { initialKeycloakContextValue } from \"./keycloak-reducer\";\n\nexport const KeycloakContext = createContext<KeycloakContextValue>(\n initialKeycloakContextValue,\n);\n","import { KeycloakError } from \"keycloak-js\";\nimport { KeycloakContextValue, KeycloakUser } from \"../types\";\n\ntype GenericAction<T extends string, P = undefined> = { type: T; payload: P };\n\nexport type KeycloakAction =\n | GenericAction<\"SET_CONFIGURATION_NAME\", string>\n | GenericAction<\n \"SET_TOKEN\",\n {\n accessToken?: string;\n idToken?: string;\n refreshToken?: string;\n isAuthenticated?: boolean;\n }\n >\n | GenericAction<\"SET_LOADING\", boolean>\n | GenericAction<\"SET_ERROR\", Error | KeycloakError | null>\n | GenericAction<\"SET_SESSION_LOST\", boolean>\n | GenericAction<\"SET_USER_INFO\", KeycloakUser | null>;\n\nexport const initialKeycloakContextValue: KeycloakContextValue = {\n error: null,\n isAuthenticated: false,\n isLoading: true,\n sessionLost: false,\n login: () => Promise.reject(new Error(\"Not implemented\")),\n logout: () => Promise.reject(new Error(\"Not implemented\")),\n userInfo: null,\n configurationName: undefined,\n};\n\nexport function keycloakReducer(\n state: KeycloakContextValue,\n action: KeycloakAction,\n): KeycloakContextValue {\n switch (action.type) {\n case \"SET_CONFIGURATION_NAME\":\n return {\n ...state,\n configurationName: action.payload,\n };\n case \"SET_TOKEN\":\n return {\n ...state,\n accessToken: action.payload.accessToken,\n refreshToken: action.payload.refreshToken,\n idToken: action.payload.idToken,\n isAuthenticated:\n action.payload.isAuthenticated ?? state.isAuthenticated,\n };\n case \"SET_LOADING\":\n return {\n ...state,\n isLoading: action.payload,\n };\n case \"SET_ERROR\":\n return {\n ...state,\n error:\n !action.payload || action.payload instanceof Error\n ? action.payload\n : new Error(\n String(\n action.payload.error || action.payload.error_description,\n ),\n ),\n };\n case \"SET_SESSION_LOST\":\n return {\n ...state,\n sessionLost: action.payload,\n };\n case \"SET_USER_INFO\":\n return {\n ...state,\n userInfo: action.payload,\n };\n\n default:\n return state;\n }\n}\n","import { useContext } from \"react\";\nimport { KeycloakContext } from \"../provider/keycloak-context\";\n\nexport function useKeycloak() {\n const ctx = useContext(KeycloakContext);\n\n return {\n login: ctx.login,\n logout: ctx.logout,\n isLoading: ctx.isLoading,\n isAuthenticated: ctx.isAuthenticated,\n configurationName: ctx.configurationName,\n };\n}\n","import React from \"react\";\nimport { useKeycloak } from \"../hooks/useKeycloak\";\nimport { getSessionStoragePrefixCN } from \"../utils/constants\";\n\nexport const KeycloakSecure: React.FC<React.PropsWithChildren> = ({\n children,\n}) => {\n const { isAuthenticated, login, isLoading, configurationName } =\n useKeycloak();\n\n if (isLoading) return null;\n\n if (!isAuthenticated) {\n // Salva a URL atual antes de redirecionar\n sessionStorage.setItem(\n getSessionStoragePrefixCN(configurationName, \"return_url\"),\n window.location.pathname + window.location.search,\n );\n\n // Redireciona para o Keycloak com callback fixo\n login(); // Usa o redirectUri configurado (ex: /authorization)\n return null;\n }\n\n return children;\n};\n","import { useContext } from \"react\";\nimport { KeycloakContext } from \"../provider/keycloak-context\";\nimport { KeycloakUser } from \"../types\";\n\nexport function useKeycloakUser<UserInfo = KeycloakUser>() {\n const ctx = useContext(KeycloakContext);\n\n return {\n user: ctx?.userInfo as UserInfo | null,\n isLoading: ctx?.isLoading,\n };\n}\n","import { useContext } from \"react\";\nimport { KeycloakContext } from \"../provider/keycloak-context\";\n\nexport function useKeycloakToken() {\n const ctx = useContext(KeycloakContext);\n\n return {\n accessToken: ctx.accessToken,\n idToken: ctx.idToken,\n };\n}\n"],"mappings":"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","names":["import_react","Keycloak","import_react","import_react","import_react"]}
|
package/dist/index.mjs
CHANGED
|
@@ -3,7 +3,8 @@ import Keycloak from "keycloak-js";
|
|
|
3
3
|
import {
|
|
4
4
|
useCallback,
|
|
5
5
|
useLayoutEffect,
|
|
6
|
-
useReducer
|
|
6
|
+
useReducer,
|
|
7
|
+
useRef
|
|
7
8
|
} from "react";
|
|
8
9
|
|
|
9
10
|
// src/components/Logger.ts
|
|
@@ -23,6 +24,31 @@ var Logger = class {
|
|
|
23
24
|
}
|
|
24
25
|
};
|
|
25
26
|
|
|
27
|
+
// src/store/ConfigurationStore.ts
|
|
28
|
+
function getConfigurationKey(name, realm) {
|
|
29
|
+
return ["keycloak", realm, name].join(".");
|
|
30
|
+
}
|
|
31
|
+
var ConfigurationStore = class {
|
|
32
|
+
static setConfiguration(name, realm, config) {
|
|
33
|
+
sessionStorage.setItem(
|
|
34
|
+
getConfigurationKey(name, realm),
|
|
35
|
+
JSON.stringify(config)
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
static getConfiguration(name, realm) {
|
|
39
|
+
const config = sessionStorage.getItem(getConfigurationKey(name, realm));
|
|
40
|
+
return config ? JSON.parse(config) : {};
|
|
41
|
+
}
|
|
42
|
+
static clearConfiguration(name, realm) {
|
|
43
|
+
sessionStorage.removeItem(getConfigurationKey(name, realm));
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// src/utils/constants.ts
|
|
48
|
+
function getSessionStoragePrefixCN(configurationName, suffix = "") {
|
|
49
|
+
return ["keycloak", configurationName ?? "default", suffix].filter(Boolean).join("_");
|
|
50
|
+
}
|
|
51
|
+
|
|
26
52
|
// src/provider/keycloak-context.ts
|
|
27
53
|
import { createContext } from "react";
|
|
28
54
|
|
|
@@ -34,14 +60,21 @@ var initialKeycloakContextValue = {
|
|
|
34
60
|
sessionLost: false,
|
|
35
61
|
login: () => Promise.reject(new Error("Not implemented")),
|
|
36
62
|
logout: () => Promise.reject(new Error("Not implemented")),
|
|
37
|
-
userInfo: null
|
|
63
|
+
userInfo: null,
|
|
64
|
+
configurationName: void 0
|
|
38
65
|
};
|
|
39
66
|
function keycloakReducer(state, action) {
|
|
40
67
|
switch (action.type) {
|
|
68
|
+
case "SET_CONFIGURATION_NAME":
|
|
69
|
+
return {
|
|
70
|
+
...state,
|
|
71
|
+
configurationName: action.payload
|
|
72
|
+
};
|
|
41
73
|
case "SET_TOKEN":
|
|
42
74
|
return {
|
|
43
75
|
...state,
|
|
44
76
|
accessToken: action.payload.accessToken,
|
|
77
|
+
refreshToken: action.payload.refreshToken,
|
|
45
78
|
idToken: action.payload.idToken,
|
|
46
79
|
isAuthenticated: action.payload.isAuthenticated ?? state.isAuthenticated
|
|
47
80
|
};
|
|
@@ -81,9 +114,9 @@ var KeycloakContext = createContext(
|
|
|
81
114
|
|
|
82
115
|
// src/provider/KeycloakProvider.tsx
|
|
83
116
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
84
|
-
var keycloak;
|
|
85
117
|
var logger = new Logger(false);
|
|
86
118
|
var KeycloakProvider = ({
|
|
119
|
+
configurationName = "default",
|
|
87
120
|
logging,
|
|
88
121
|
children,
|
|
89
122
|
config,
|
|
@@ -91,34 +124,16 @@ var KeycloakProvider = ({
|
|
|
91
124
|
AuthenticatingErrorComponent,
|
|
92
125
|
SessionLostComponent
|
|
93
126
|
}) => {
|
|
94
|
-
logger.setEnabled(logging ??
|
|
127
|
+
logger.setEnabled(["wrapper", "both"].includes(logging ?? ""));
|
|
128
|
+
const keycloakRef = useRef();
|
|
129
|
+
const timeoutRef = useRef();
|
|
95
130
|
const [state, dispatch] = useReducer(
|
|
96
131
|
keycloakReducer,
|
|
97
132
|
initialKeycloakContextValue
|
|
98
133
|
);
|
|
99
|
-
const
|
|
100
|
-
if (!
|
|
101
|
-
|
|
102
|
-
url: config.url,
|
|
103
|
-
realm: config.realm,
|
|
104
|
-
clientId: config.clientId,
|
|
105
|
-
oidcProvider: config.wellKnownUrlPrefix
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
if (keycloak && !keycloak.didInitialize) {
|
|
109
|
-
keycloak.init({
|
|
110
|
-
onLoad: "check-sso",
|
|
111
|
-
checkLoginIframe: false,
|
|
112
|
-
scope: config.scope
|
|
113
|
-
}).catch((error) => {
|
|
114
|
-
logger.log("Failed to initialize Keycloak", { error });
|
|
115
|
-
dispatch({
|
|
116
|
-
type: "SET_ERROR",
|
|
117
|
-
payload: error || null
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
keycloak.onReady = (authenticated) => {
|
|
134
|
+
const watchKeycloakEvents = useCallback(() => {
|
|
135
|
+
if (!keycloakRef.current) return;
|
|
136
|
+
keycloakRef.current.onReady = (authenticated) => {
|
|
122
137
|
logger.log("Keycloak is ready", { authenticated });
|
|
123
138
|
if (!authenticated) {
|
|
124
139
|
dispatch({
|
|
@@ -127,18 +142,24 @@ var KeycloakProvider = ({
|
|
|
127
142
|
});
|
|
128
143
|
}
|
|
129
144
|
};
|
|
130
|
-
|
|
145
|
+
keycloakRef.current.onAuthSuccess = () => {
|
|
131
146
|
logger.log("Authentication successful");
|
|
147
|
+
ConfigurationStore.setConfiguration(configurationName, config.realm, {
|
|
148
|
+
token: keycloakRef.current?.token,
|
|
149
|
+
refreshToken: keycloakRef.current?.refreshToken,
|
|
150
|
+
idToken: keycloakRef.current?.idToken
|
|
151
|
+
});
|
|
132
152
|
dispatch({
|
|
133
153
|
type: "SET_TOKEN",
|
|
134
154
|
payload: {
|
|
135
155
|
isAuthenticated: true,
|
|
136
|
-
accessToken:
|
|
137
|
-
|
|
156
|
+
accessToken: keycloakRef.current?.token,
|
|
157
|
+
refreshToken: keycloakRef.current?.refreshToken,
|
|
158
|
+
idToken: keycloakRef.current?.idToken
|
|
138
159
|
}
|
|
139
160
|
});
|
|
140
161
|
logger.log("Loading user info");
|
|
141
|
-
|
|
162
|
+
keycloakRef.current?.loadUserInfo().then((userInfo) => {
|
|
142
163
|
logger.log("User info loaded", { userInfo });
|
|
143
164
|
dispatch({
|
|
144
165
|
type: "SET_USER_INFO",
|
|
@@ -150,14 +171,14 @@ var KeycloakProvider = ({
|
|
|
150
171
|
payload: false
|
|
151
172
|
});
|
|
152
173
|
});
|
|
153
|
-
setInterval(
|
|
174
|
+
timeoutRef.current = setInterval(
|
|
154
175
|
() => {
|
|
155
|
-
|
|
176
|
+
keycloakRef.current?.updateToken(config.refreshSecondsBeforeTokenExpires ?? 120).then((refreshed) => {
|
|
156
177
|
if (!refreshed) {
|
|
157
178
|
logger.log(
|
|
158
179
|
"Token is still valid, no need to refresh",
|
|
159
180
|
new Date(
|
|
160
|
-
(
|
|
181
|
+
(keycloakRef.current?.tokenParsed?.exp ?? 0) * 1e3
|
|
161
182
|
).toLocaleTimeString()
|
|
162
183
|
);
|
|
163
184
|
}
|
|
@@ -166,58 +187,111 @@ var KeycloakProvider = ({
|
|
|
166
187
|
(config.tokenRefreshIntervalInSeconds ?? 10) * 1e3
|
|
167
188
|
);
|
|
168
189
|
};
|
|
169
|
-
|
|
190
|
+
keycloakRef.current.onAuthLogout = () => {
|
|
170
191
|
logger.log("Session lost");
|
|
171
192
|
dispatch({
|
|
172
193
|
type: "SET_SESSION_LOST",
|
|
173
194
|
payload: true
|
|
174
195
|
});
|
|
175
196
|
};
|
|
176
|
-
|
|
197
|
+
keycloakRef.current.onAuthError = (error) => {
|
|
177
198
|
logger.log("Authentication error", { error });
|
|
178
199
|
dispatch({
|
|
179
200
|
type: "SET_ERROR",
|
|
180
201
|
payload: error || null
|
|
181
202
|
});
|
|
182
203
|
};
|
|
183
|
-
|
|
204
|
+
keycloakRef.current.onAuthRefreshError = () => {
|
|
184
205
|
logger.log("Token refresh error");
|
|
185
206
|
dispatch({
|
|
186
207
|
type: "SET_ERROR",
|
|
187
208
|
payload: new Error("Token refresh error") || null
|
|
188
209
|
});
|
|
189
210
|
};
|
|
190
|
-
|
|
191
|
-
logger.log("Token refresh successful",
|
|
211
|
+
keycloakRef.current.onAuthRefreshSuccess = () => {
|
|
212
|
+
logger.log("Token refresh successful", keycloakRef.current?.token);
|
|
213
|
+
ConfigurationStore.setConfiguration(configurationName, config.realm, {
|
|
214
|
+
token: keycloakRef.current?.token,
|
|
215
|
+
refreshToken: keycloakRef.current?.refreshToken,
|
|
216
|
+
idToken: keycloakRef.current?.idToken
|
|
217
|
+
});
|
|
192
218
|
dispatch({
|
|
193
219
|
type: "SET_TOKEN",
|
|
194
220
|
payload: {
|
|
195
221
|
isAuthenticated: true,
|
|
196
|
-
accessToken:
|
|
197
|
-
|
|
222
|
+
accessToken: keycloakRef.current?.token,
|
|
223
|
+
refreshToken: keycloakRef.current?.refreshToken,
|
|
224
|
+
idToken: keycloakRef.current?.idToken
|
|
198
225
|
}
|
|
199
226
|
});
|
|
200
227
|
};
|
|
201
228
|
}, [
|
|
202
|
-
config.clientId,
|
|
203
229
|
config.realm,
|
|
204
230
|
config.refreshSecondsBeforeTokenExpires,
|
|
205
|
-
config.scope,
|
|
206
231
|
config.tokenRefreshIntervalInSeconds,
|
|
232
|
+
configurationName
|
|
233
|
+
]);
|
|
234
|
+
const initiateKeycloak = useCallback(() => {
|
|
235
|
+
if (keycloakRef.current && !keycloakRef.current.didInitialize) {
|
|
236
|
+
keycloakRef.current.init({
|
|
237
|
+
onLoad: "check-sso",
|
|
238
|
+
checkLoginIframe: false,
|
|
239
|
+
scope: config.scope,
|
|
240
|
+
enableLogging: ["keycloak", "both"].includes(logging ?? ""),
|
|
241
|
+
...ConfigurationStore.getConfiguration(
|
|
242
|
+
configurationName,
|
|
243
|
+
config.realm
|
|
244
|
+
)
|
|
245
|
+
}).catch((error) => {
|
|
246
|
+
logger.log("Failed to initialize Keycloak", { error });
|
|
247
|
+
dispatch({
|
|
248
|
+
type: "SET_ERROR",
|
|
249
|
+
payload: error || null
|
|
250
|
+
});
|
|
251
|
+
dispatch({
|
|
252
|
+
type: "SET_LOADING",
|
|
253
|
+
payload: false
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
} else if (!keycloakRef.current) {
|
|
257
|
+
keycloakRef.current = new Keycloak({
|
|
258
|
+
url: config.url,
|
|
259
|
+
realm: config.realm,
|
|
260
|
+
clientId: config.clientId,
|
|
261
|
+
oidcProvider: config.wellKnownUrlPrefix
|
|
262
|
+
});
|
|
263
|
+
watchKeycloakEvents();
|
|
264
|
+
dispatch({
|
|
265
|
+
type: "SET_CONFIGURATION_NAME",
|
|
266
|
+
payload: configurationName
|
|
267
|
+
});
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
}, [
|
|
271
|
+
config.clientId,
|
|
272
|
+
config.realm,
|
|
273
|
+
config.scope,
|
|
207
274
|
config.url,
|
|
208
|
-
config.wellKnownUrlPrefix
|
|
275
|
+
config.wellKnownUrlPrefix,
|
|
276
|
+
configurationName,
|
|
277
|
+
logging,
|
|
278
|
+
watchKeycloakEvents
|
|
209
279
|
]);
|
|
210
280
|
useLayoutEffect(() => {
|
|
211
281
|
initiateKeycloak();
|
|
282
|
+
return () => {
|
|
283
|
+
if (keycloakRef.current?.didInitialize && keycloakRef.current.authenticated && timeoutRef.current !== void 0) {
|
|
284
|
+
logger.log("Cleaning up Keycloak refresh token");
|
|
285
|
+
clearInterval(timeoutRef.current);
|
|
286
|
+
timeoutRef.current = void 0;
|
|
287
|
+
}
|
|
288
|
+
};
|
|
212
289
|
}, [initiateKeycloak]);
|
|
213
290
|
useLayoutEffect(() => {
|
|
214
|
-
logger.log("Checando redirecionamento ap\xF3s autentica\xE7\xE3o", {
|
|
215
|
-
isAuthenticated: state.isAuthenticated,
|
|
216
|
-
isLoading: state.isLoading,
|
|
217
|
-
redirectUri: config.redirectUri
|
|
218
|
-
});
|
|
219
291
|
if (!state.isLoading && state.isAuthenticated && config.redirectUri && window.location.href.startsWith(config.redirectUri)) {
|
|
220
|
-
const returnUrl = sessionStorage.getItem(
|
|
292
|
+
const returnUrl = sessionStorage.getItem(
|
|
293
|
+
getSessionStoragePrefixCN(configurationName, "return_url")
|
|
294
|
+
) || "/";
|
|
221
295
|
if (!window.location.href.endsWith(returnUrl)) {
|
|
222
296
|
logger.log("Redirecionando para a URL original ap\xF3s autentica\xE7\xE3o", {
|
|
223
297
|
returnUrl,
|
|
@@ -229,31 +303,44 @@ var KeycloakProvider = ({
|
|
|
229
303
|
window.location.origin + returnUrl
|
|
230
304
|
);
|
|
231
305
|
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
232
|
-
sessionStorage.removeItem(
|
|
306
|
+
sessionStorage.removeItem(
|
|
307
|
+
getSessionStoragePrefixCN(configurationName, "return_url")
|
|
308
|
+
);
|
|
233
309
|
}
|
|
234
310
|
}
|
|
235
|
-
}, [
|
|
311
|
+
}, [
|
|
312
|
+
config.redirectUri,
|
|
313
|
+
configurationName,
|
|
314
|
+
state.isAuthenticated,
|
|
315
|
+
state.isLoading
|
|
316
|
+
]);
|
|
236
317
|
const handleLogin = useCallback(
|
|
237
318
|
(redirectUri) => {
|
|
238
319
|
dispatch({
|
|
239
320
|
type: "SET_LOADING",
|
|
240
321
|
payload: true
|
|
241
322
|
});
|
|
242
|
-
return
|
|
323
|
+
return keycloakRef.current?.login({
|
|
243
324
|
redirectUri: redirectUri ?? config.redirectUri
|
|
244
325
|
}) ?? Promise.reject();
|
|
245
326
|
},
|
|
246
327
|
[config.redirectUri]
|
|
247
328
|
);
|
|
248
|
-
const handleLogout = useCallback(
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
329
|
+
const handleLogout = useCallback(
|
|
330
|
+
(redirectUriAfterLogout) => {
|
|
331
|
+
dispatch({
|
|
332
|
+
type: "SET_LOADING",
|
|
333
|
+
payload: true
|
|
334
|
+
});
|
|
335
|
+
ConfigurationStore.clearConfiguration(configurationName, config.realm);
|
|
336
|
+
return keycloakRef.current?.logout({
|
|
337
|
+
redirectUri: redirectUriAfterLogout
|
|
338
|
+
}) ?? Promise.reject();
|
|
339
|
+
},
|
|
340
|
+
[config.realm, configurationName]
|
|
341
|
+
);
|
|
342
|
+
const shouldRenderError = state?.error && !state.isLoading && AuthenticatingErrorComponent;
|
|
343
|
+
const shouldRenderSessionLost = state.sessionLost && !state.isLoading && !state?.error && SessionLostComponent;
|
|
257
344
|
const shouldRenderChildren = !state.isLoading && !state.error && !state.sessionLost;
|
|
258
345
|
return /* @__PURE__ */ jsxs(
|
|
259
346
|
KeycloakContext.Provider,
|
|
@@ -265,9 +352,9 @@ var KeycloakProvider = ({
|
|
|
265
352
|
},
|
|
266
353
|
children: [
|
|
267
354
|
shouldRenderChildren && children,
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
355
|
+
shouldRenderSessionLost && /* @__PURE__ */ jsx(SessionLostComponent, {}),
|
|
356
|
+
shouldRenderError && /* @__PURE__ */ jsx(AuthenticatingErrorComponent, { error: state?.error }),
|
|
357
|
+
LoadingComponent && /* @__PURE__ */ jsx(LoadingComponent, { opened: state?.isLoading })
|
|
271
358
|
]
|
|
272
359
|
}
|
|
273
360
|
);
|
|
@@ -281,26 +368,26 @@ function useKeycloak() {
|
|
|
281
368
|
login: ctx.login,
|
|
282
369
|
logout: ctx.logout,
|
|
283
370
|
isLoading: ctx.isLoading,
|
|
284
|
-
isAuthenticated: ctx.isAuthenticated
|
|
371
|
+
isAuthenticated: ctx.isAuthenticated,
|
|
372
|
+
configurationName: ctx.configurationName
|
|
285
373
|
};
|
|
286
374
|
}
|
|
287
375
|
|
|
288
376
|
// src/components/KeycloakSecure.tsx
|
|
289
|
-
import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
|
|
290
377
|
var KeycloakSecure = ({
|
|
291
378
|
children
|
|
292
379
|
}) => {
|
|
293
|
-
const { isAuthenticated, login, isLoading } = useKeycloak();
|
|
380
|
+
const { isAuthenticated, login, isLoading, configurationName } = useKeycloak();
|
|
294
381
|
if (isLoading) return null;
|
|
295
382
|
if (!isAuthenticated) {
|
|
296
383
|
sessionStorage.setItem(
|
|
297
|
-
"
|
|
384
|
+
getSessionStoragePrefixCN(configurationName, "return_url"),
|
|
298
385
|
window.location.pathname + window.location.search
|
|
299
386
|
);
|
|
300
387
|
login();
|
|
301
388
|
return null;
|
|
302
389
|
}
|
|
303
|
-
return
|
|
390
|
+
return children;
|
|
304
391
|
};
|
|
305
392
|
|
|
306
393
|
// src/hooks/useKeycloakUser.ts
|
|
@@ -309,7 +396,7 @@ function useKeycloakUser() {
|
|
|
309
396
|
const ctx = useContext2(KeycloakContext);
|
|
310
397
|
return {
|
|
311
398
|
user: ctx?.userInfo,
|
|
312
|
-
|
|
399
|
+
isLoading: ctx?.isLoading
|
|
313
400
|
};
|
|
314
401
|
}
|
|
315
402
|
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/provider/KeycloakProvider.tsx","../src/components/Logger.ts","../src/provider/keycloak-context.ts","../src/provider/keycloak-reducer.ts","../src/hooks/useKeycloak.ts","../src/components/KeycloakSecure.tsx","../src/hooks/useKeycloakUser.ts","../src/hooks/useKeycloakToken.ts"],"sourcesContent":["import Keycloak from \"keycloak-js\";\nimport React, {\n FC,\n ReactNode,\n useCallback,\n useLayoutEffect,\n useReducer,\n} from \"react\";\nimport Logger from \"../components/Logger\";\nimport { KeycloakConfig, KeycloakUser } from \"../types\";\nimport { KeycloakContext } from \"./keycloak-context\";\nimport {\n initialKeycloakContextValue,\n keycloakReducer,\n} from \"./keycloak-reducer\";\n\ninterface Props {\n logging?: boolean;\n children: ReactNode;\n config: KeycloakConfig;\n LoadingComponent?: FC<{ opened: boolean }>;\n AuthenticatingErrorComponent?: FC<{\n error: Error | null;\n }>;\n SessionLostComponent?: FC;\n}\n\nlet keycloak: Keycloak | undefined;\nconst logger = new Logger(false);\nexport const KeycloakProvider: React.FC<Props> = ({\n logging,\n children,\n config,\n LoadingComponent,\n AuthenticatingErrorComponent,\n SessionLostComponent,\n}) => {\n logger.setEnabled(logging ?? false);\n\n const [state, dispatch] = useReducer(\n keycloakReducer,\n initialKeycloakContextValue,\n );\n\n const initiateKeycloak = useCallback(() => {\n if (!keycloak) {\n keycloak = new Keycloak({\n url: config.url,\n realm: config.realm,\n clientId: config.clientId,\n oidcProvider: config.wellKnownUrlPrefix,\n });\n }\n\n if (keycloak && !keycloak.didInitialize) {\n keycloak\n .init({\n onLoad: \"check-sso\",\n checkLoginIframe: false,\n scope: config.scope,\n })\n .catch((error) => {\n logger.log(\"Failed to initialize Keycloak\", { error });\n dispatch({\n type: \"SET_ERROR\",\n payload: error || null,\n });\n });\n }\n\n keycloak.onReady = (authenticated) => {\n logger.log(\"Keycloak is ready\", { authenticated });\n\n if (!authenticated) {\n dispatch({\n type: \"SET_LOADING\",\n payload: false,\n });\n }\n };\n\n keycloak.onAuthSuccess = () => {\n logger.log(\"Authentication successful\");\n\n dispatch({\n type: \"SET_TOKEN\",\n payload: {\n isAuthenticated: true,\n accessToken: keycloak?.token,\n idToken: keycloak?.idToken,\n },\n });\n\n logger.log(\"Loading user info\");\n keycloak\n ?.loadUserInfo()\n .then((userInfo) => {\n logger.log(\"User info loaded\", { userInfo });\n dispatch({\n type: \"SET_USER_INFO\",\n payload: userInfo as unknown as KeycloakUser,\n });\n })\n .finally(() => {\n dispatch({\n type: \"SET_LOADING\",\n payload: false,\n });\n });\n\n setInterval(\n () => {\n keycloak\n ?.updateToken(config.refreshSecondsBeforeTokenExpires ?? 120)\n .then((refreshed) => {\n if (!refreshed) {\n logger.log(\n \"Token is still valid, no need to refresh\",\n new Date(\n (keycloak?.tokenParsed?.exp ?? 0) * 1000,\n ).toLocaleTimeString(),\n );\n }\n });\n },\n (config.tokenRefreshIntervalInSeconds ?? 10) * 1000,\n );\n };\n\n keycloak.onAuthLogout = () => {\n logger.log(\"Session lost\");\n dispatch({\n type: \"SET_SESSION_LOST\",\n payload: true,\n });\n };\n\n keycloak.onAuthError = (error) => {\n logger.log(\"Authentication error\", { error });\n\n dispatch({\n type: \"SET_ERROR\",\n payload: error || null,\n });\n };\n\n keycloak.onAuthRefreshError = () => {\n logger.log(\"Token refresh error\");\n\n dispatch({\n type: \"SET_ERROR\",\n payload: new Error(\"Token refresh error\") || null,\n });\n };\n\n keycloak.onAuthRefreshSuccess = () => {\n logger.log(\"Token refresh successful\", keycloak?.token);\n\n dispatch({\n type: \"SET_TOKEN\",\n payload: {\n isAuthenticated: true,\n accessToken: keycloak?.token,\n idToken: keycloak?.idToken,\n },\n });\n };\n }, [\n config.clientId,\n config.realm,\n config.refreshSecondsBeforeTokenExpires,\n config.scope,\n config.tokenRefreshIntervalInSeconds,\n config.url,\n config.wellKnownUrlPrefix,\n ]);\n\n useLayoutEffect(() => {\n initiateKeycloak();\n }, [initiateKeycloak]);\n\n useLayoutEffect(() => {\n logger.log(\"Checando redirecionamento após autenticação\", {\n isAuthenticated: state.isAuthenticated,\n isLoading: state.isLoading,\n redirectUri: config.redirectUri,\n });\n\n if (\n !state.isLoading &&\n state.isAuthenticated &&\n config.redirectUri &&\n window.location.href.startsWith(config.redirectUri)\n ) {\n const returnUrl = sessionStorage.getItem(\"keycloak_return_url\") || \"/\";\n if (!window.location.href.endsWith(returnUrl)) {\n logger.log(\"Redirecionando para a URL original após autenticação\", {\n returnUrl,\n origin: window.location.origin,\n });\n\n // Redireciona para a URL original\n window.history.replaceState(\n { keycloak_redirected: true },\n \"\",\n window.location.origin + returnUrl,\n );\n window.dispatchEvent(new PopStateEvent(\"popstate\"));\n sessionStorage.removeItem(\"keycloak_return_url\");\n }\n }\n }, [config.redirectUri, state.isAuthenticated, state.isLoading]);\n\n const handleLogin = useCallback(\n (redirectUri?: string) => {\n dispatch({\n type: \"SET_LOADING\",\n payload: true,\n });\n\n return (\n keycloak?.login({\n redirectUri: redirectUri ?? config.redirectUri,\n }) ?? Promise.reject()\n );\n },\n [config.redirectUri],\n );\n\n const handleLogout = useCallback((redirectUriAfterLogout: string) => {\n dispatch({\n type: \"SET_LOADING\",\n payload: true,\n });\n\n return (\n keycloak?.logout({\n redirectUri: redirectUriAfterLogout,\n }) ?? Promise.reject()\n );\n }, []);\n\n const shouldRenderChildren =\n !state.isLoading && !state.error && !state.sessionLost;\n\n return (\n <KeycloakContext.Provider\n value={{\n ...state,\n login: handleLogin,\n logout: handleLogout,\n }}\n >\n {shouldRenderChildren && children}\n\n {LoadingComponent && <LoadingComponent opened={state?.isLoading} />}\n {AuthenticatingErrorComponent && state?.error && (\n <AuthenticatingErrorComponent error={state?.error} />\n )}\n {SessionLostComponent && state?.sessionLost && <SessionLostComponent />}\n </KeycloakContext.Provider>\n );\n};\n","export default class Logger {\n enabled: boolean = false;\n\n constructor(enabled: boolean = false) {\n this.enabled = enabled;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n log(...data: any[]) {\n if (this.enabled) {\n console.log(\"[react-keycloak-wrapper]\", ...data);\n }\n }\n\n setEnabled(enabled: boolean) {\n this.enabled = enabled;\n }\n}\n","import { createContext } from \"react\";\nimport { KeycloakContextValue } from \"../types\";\nimport { initialKeycloakContextValue } from \"./keycloak-reducer\";\n\nexport const KeycloakContext = createContext<KeycloakContextValue>(\n initialKeycloakContextValue,\n);\n","import { KeycloakError } from \"keycloak-js\";\nimport { KeycloakContextValue, KeycloakUser } from \"../types\";\n\ntype GenericAction<T extends string, P = undefined> = { type: T; payload: P };\n\nexport type KeycloakAction =\n | GenericAction<\n \"SET_TOKEN\",\n { accessToken?: string; idToken?: string; isAuthenticated?: boolean }\n >\n | GenericAction<\"SET_LOADING\", boolean>\n | GenericAction<\"SET_ERROR\", Error | KeycloakError | null>\n | GenericAction<\"SET_SESSION_LOST\", boolean>\n | GenericAction<\"SET_USER_INFO\", KeycloakUser | null>;\n\nexport const initialKeycloakContextValue: KeycloakContextValue = {\n error: null,\n isAuthenticated: false,\n isLoading: true,\n sessionLost: false,\n login: () => Promise.reject(new Error(\"Not implemented\")),\n logout: () => Promise.reject(new Error(\"Not implemented\")),\n userInfo: null,\n};\n\nexport function keycloakReducer(\n state: KeycloakContextValue,\n action: KeycloakAction,\n): KeycloakContextValue {\n switch (action.type) {\n case \"SET_TOKEN\":\n return {\n ...state,\n accessToken: action.payload.accessToken,\n idToken: action.payload.idToken,\n isAuthenticated:\n action.payload.isAuthenticated ?? state.isAuthenticated,\n };\n case \"SET_LOADING\":\n return {\n ...state,\n isLoading: action.payload,\n };\n case \"SET_ERROR\":\n return {\n ...state,\n error:\n !action.payload || action.payload instanceof Error\n ? action.payload\n : new Error(\n String(\n action.payload.error || action.payload.error_description,\n ),\n ),\n };\n case \"SET_SESSION_LOST\":\n return {\n ...state,\n sessionLost: action.payload,\n };\n case \"SET_USER_INFO\":\n return {\n ...state,\n userInfo: action.payload,\n };\n\n default:\n return state;\n }\n}\n","import { useContext } from \"react\";\nimport { KeycloakContext } from \"../provider/keycloak-context\";\n\nexport function useKeycloak() {\n const ctx = useContext(KeycloakContext);\n\n return {\n login: ctx.login,\n logout: ctx.logout,\n isLoading: ctx.isLoading,\n isAuthenticated: ctx.isAuthenticated,\n };\n}\n","import React from \"react\";\nimport { useKeycloak } from \"../hooks/useKeycloak\";\n\nexport const KeycloakSecure: React.FC<React.PropsWithChildren> = ({\n children,\n}) => {\n const { isAuthenticated, login, isLoading } = useKeycloak();\n\n if (isLoading) return null;\n\n if (!isAuthenticated) {\n // Salva a URL atual antes de redirecionar\n sessionStorage.setItem(\n \"keycloak_return_url\",\n window.location.pathname + window.location.search,\n );\n\n // Redireciona para o Keycloak com callback fixo\n login(); // Usa o redirectUri configurado (ex: /authorization)\n return null;\n }\n\n return <>{children}</>;\n};\n","import { useContext } from \"react\";\nimport { KeycloakContext } from \"../provider/keycloak-context\";\nimport { KeycloakUser } from \"../types\";\n\nexport function useKeycloakUser<UserInfo = KeycloakUser>() {\n const ctx = useContext(KeycloakContext);\n\n return {\n user: ctx?.userInfo as UserInfo | null,\n loading: ctx?.isLoading,\n };\n}\n","import { useContext } from \"react\";\nimport { KeycloakContext } from \"../provider/keycloak-context\";\n\nexport function useKeycloakToken() {\n const ctx = useContext(KeycloakContext);\n\n return {\n accessToken: ctx.accessToken,\n idToken: ctx.idToken,\n };\n}\n"],"mappings":"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","names":["jsx","useContext","useContext","useContext","useContext"]}
|
|
1
|
+
{"version":3,"sources":["../src/provider/KeycloakProvider.tsx","../src/components/Logger.ts","../src/store/ConfigurationStore.ts","../src/utils/constants.ts","../src/provider/keycloak-context.ts","../src/provider/keycloak-reducer.ts","../src/hooks/useKeycloak.ts","../src/components/KeycloakSecure.tsx","../src/hooks/useKeycloakUser.ts","../src/hooks/useKeycloakToken.ts"],"sourcesContent":["import Keycloak from \"keycloak-js\";\nimport React, {\n FC,\n ReactNode,\n useCallback,\n useLayoutEffect,\n useReducer,\n useRef,\n} from \"react\";\nimport Logger from \"../components/Logger\";\nimport ConfigurationStore from \"../store/ConfigurationStore\";\nimport { KeycloakConfig, KeycloakUser } from \"../types\";\nimport { getSessionStoragePrefixCN } from \"../utils/constants\";\nimport { KeycloakContext } from \"./keycloak-context\";\nimport {\n initialKeycloakContextValue,\n keycloakReducer,\n} from \"./keycloak-reducer\";\n\ninterface Props {\n configurationName?: string;\n logging?: \"wrapper\" | \"keycloak\" | \"both\";\n children: ReactNode;\n config: KeycloakConfig;\n LoadingComponent?: FC<{ opened: boolean }>;\n AuthenticatingErrorComponent?: FC<{\n error: Error | null;\n }>;\n SessionLostComponent?: FC;\n}\n\nconst logger = new Logger(false);\nexport const KeycloakProvider: React.FC<Props> = ({\n configurationName = \"default\",\n logging,\n children,\n config,\n LoadingComponent,\n AuthenticatingErrorComponent,\n SessionLostComponent,\n}) => {\n logger.setEnabled([\"wrapper\", \"both\"].includes(logging ?? \"\"));\n\n const keycloakRef = useRef<Keycloak>();\n const timeoutRef = useRef<NodeJS.Timeout>();\n\n const [state, dispatch] = useReducer(\n keycloakReducer,\n initialKeycloakContextValue,\n );\n\n const watchKeycloakEvents = useCallback(() => {\n if (!keycloakRef.current) return;\n\n keycloakRef.current.onReady = (authenticated) => {\n logger.log(\"Keycloak is ready\", { authenticated });\n\n if (!authenticated) {\n dispatch({\n type: \"SET_LOADING\",\n payload: false,\n });\n }\n };\n\n keycloakRef.current.onAuthSuccess = () => {\n logger.log(\"Authentication successful\");\n\n ConfigurationStore.setConfiguration(configurationName, config.realm, {\n token: keycloakRef.current?.token,\n refreshToken: keycloakRef.current?.refreshToken,\n idToken: keycloakRef.current?.idToken,\n });\n\n dispatch({\n type: \"SET_TOKEN\",\n payload: {\n isAuthenticated: true,\n accessToken: keycloakRef.current?.token,\n refreshToken: keycloakRef.current?.refreshToken,\n idToken: keycloakRef.current?.idToken,\n },\n });\n\n logger.log(\"Loading user info\");\n keycloakRef.current\n ?.loadUserInfo()\n .then((userInfo) => {\n logger.log(\"User info loaded\", { userInfo });\n dispatch({\n type: \"SET_USER_INFO\",\n payload: userInfo as unknown as KeycloakUser,\n });\n })\n .finally(() => {\n dispatch({\n type: \"SET_LOADING\",\n payload: false,\n });\n });\n\n timeoutRef.current = setInterval(\n () => {\n keycloakRef.current\n ?.updateToken(config.refreshSecondsBeforeTokenExpires ?? 120)\n .then((refreshed) => {\n if (!refreshed) {\n logger.log(\n \"Token is still valid, no need to refresh\",\n new Date(\n (keycloakRef.current?.tokenParsed?.exp ?? 0) * 1000,\n ).toLocaleTimeString(),\n );\n }\n });\n },\n (config.tokenRefreshIntervalInSeconds ?? 10) * 1000,\n );\n };\n\n keycloakRef.current.onAuthLogout = () => {\n logger.log(\"Session lost\");\n dispatch({\n type: \"SET_SESSION_LOST\",\n payload: true,\n });\n };\n\n keycloakRef.current.onAuthError = (error) => {\n logger.log(\"Authentication error\", { error });\n\n dispatch({\n type: \"SET_ERROR\",\n payload: error || null,\n });\n };\n\n keycloakRef.current.onAuthRefreshError = () => {\n logger.log(\"Token refresh error\");\n\n dispatch({\n type: \"SET_ERROR\",\n payload: new Error(\"Token refresh error\") || null,\n });\n };\n\n keycloakRef.current.onAuthRefreshSuccess = () => {\n logger.log(\"Token refresh successful\", keycloakRef.current?.token);\n\n ConfigurationStore.setConfiguration(configurationName, config.realm, {\n token: keycloakRef.current?.token,\n refreshToken: keycloakRef.current?.refreshToken,\n idToken: keycloakRef.current?.idToken,\n });\n\n dispatch({\n type: \"SET_TOKEN\",\n payload: {\n isAuthenticated: true,\n accessToken: keycloakRef.current?.token,\n refreshToken: keycloakRef.current?.refreshToken,\n idToken: keycloakRef.current?.idToken,\n },\n });\n };\n }, [\n config.realm,\n config.refreshSecondsBeforeTokenExpires,\n config.tokenRefreshIntervalInSeconds,\n configurationName,\n ]);\n\n const initiateKeycloak = useCallback(() => {\n if (keycloakRef.current && !keycloakRef.current.didInitialize) {\n keycloakRef.current\n .init({\n onLoad: \"check-sso\",\n checkLoginIframe: false,\n scope: config.scope,\n enableLogging: [\"keycloak\", \"both\"].includes(logging ?? \"\"),\n ...ConfigurationStore.getConfiguration(\n configurationName,\n config.realm,\n ),\n })\n .catch((error) => {\n logger.log(\"Failed to initialize Keycloak\", { error });\n dispatch({\n type: \"SET_ERROR\",\n payload: error || null,\n });\n dispatch({\n type: \"SET_LOADING\",\n payload: false,\n });\n });\n } else if (!keycloakRef.current) {\n keycloakRef.current = new Keycloak({\n url: config.url,\n realm: config.realm,\n clientId: config.clientId,\n oidcProvider: config.wellKnownUrlPrefix,\n });\n\n watchKeycloakEvents();\n\n dispatch({\n type: \"SET_CONFIGURATION_NAME\",\n payload: configurationName,\n });\n\n return true;\n }\n }, [\n config.clientId,\n config.realm,\n config.scope,\n config.url,\n config.wellKnownUrlPrefix,\n configurationName,\n logging,\n watchKeycloakEvents,\n ]);\n\n useLayoutEffect(() => {\n initiateKeycloak();\n\n return () => {\n if (\n keycloakRef.current?.didInitialize &&\n keycloakRef.current.authenticated &&\n timeoutRef.current !== undefined\n ) {\n logger.log(\"Cleaning up Keycloak refresh token\");\n clearInterval(timeoutRef.current);\n timeoutRef.current = undefined;\n }\n };\n }, [initiateKeycloak]);\n\n useLayoutEffect(() => {\n if (\n !state.isLoading &&\n state.isAuthenticated &&\n config.redirectUri &&\n window.location.href.startsWith(config.redirectUri)\n ) {\n const returnUrl =\n sessionStorage.getItem(\n getSessionStoragePrefixCN(configurationName, \"return_url\"),\n ) || \"/\";\n if (!window.location.href.endsWith(returnUrl)) {\n logger.log(\"Redirecionando para a URL original após autenticação\", {\n returnUrl,\n origin: window.location.origin,\n });\n\n // Redireciona para a URL original\n window.history.replaceState(\n { keycloak_redirected: true },\n \"\",\n window.location.origin + returnUrl,\n );\n \n // Dispara um evento para que o ReactRouter detecte\n window.dispatchEvent(new PopStateEvent(\"popstate\"));\n sessionStorage.removeItem(\n getSessionStoragePrefixCN(configurationName, \"return_url\"),\n );\n }\n }\n }, [\n config.redirectUri,\n configurationName,\n state.isAuthenticated,\n state.isLoading,\n ]);\n\n const handleLogin = useCallback(\n (redirectUri?: string) => {\n dispatch({\n type: \"SET_LOADING\",\n payload: true,\n });\n\n return (\n keycloakRef.current?.login({\n redirectUri: redirectUri ?? config.redirectUri,\n }) ?? Promise.reject()\n );\n },\n [config.redirectUri],\n );\n\n const handleLogout = useCallback(\n (redirectUriAfterLogout: string) => {\n dispatch({\n type: \"SET_LOADING\",\n payload: true,\n });\n\n ConfigurationStore.clearConfiguration(configurationName, config.realm);\n\n return (\n keycloakRef.current?.logout({\n redirectUri: redirectUriAfterLogout,\n }) ?? Promise.reject()\n );\n },\n [config.realm, configurationName],\n );\n\n // carregando > erro > sessão perdida > children\n\n const shouldRenderError =\n state?.error && !state.isLoading && AuthenticatingErrorComponent;\n\n const shouldRenderSessionLost =\n state.sessionLost &&\n !state.isLoading &&\n !state?.error &&\n SessionLostComponent;\n\n const shouldRenderChildren =\n !state.isLoading && !state.error && !state.sessionLost;\n\n return (\n <KeycloakContext.Provider\n value={{\n ...state,\n login: handleLogin,\n logout: handleLogout,\n }}\n >\n {shouldRenderChildren && children}\n\n {shouldRenderSessionLost && <SessionLostComponent />}\n\n {shouldRenderError && (\n <AuthenticatingErrorComponent error={state?.error} />\n )}\n\n {LoadingComponent && <LoadingComponent opened={state?.isLoading} />}\n </KeycloakContext.Provider>\n );\n};\n","export default class Logger {\n enabled: boolean = false;\n\n constructor(enabled: boolean = false) {\n this.enabled = enabled;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n log(...data: any[]) {\n if (this.enabled) {\n console.log(\"[react-keycloak-wrapper]\", ...data);\n }\n }\n\n setEnabled(enabled: boolean) {\n this.enabled = enabled;\n }\n}\n","type ConfigurationTokens = {\n idToken?: string;\n token?: string;\n refreshToken?: string;\n};\n\nfunction getConfigurationKey(name: string, realm: string) {\n return [\"keycloak\", realm, name].join(\".\");\n}\n\nexport default class ConfigurationStore {\n public static setConfiguration(\n name: string,\n realm: string,\n config: ConfigurationTokens,\n ): void {\n sessionStorage.setItem(\n getConfigurationKey(name, realm),\n JSON.stringify(config),\n );\n }\n\n public static getConfiguration(\n name: string,\n realm: string,\n ): ConfigurationTokens | object {\n const config = sessionStorage.getItem(getConfigurationKey(name, realm));\n return config ? (JSON.parse(config) as ConfigurationTokens) : {};\n }\n\n public static clearConfiguration(name: string, realm: string): void {\n sessionStorage.removeItem(getConfigurationKey(name, realm));\n }\n}\n","export function getSessionStoragePrefixCN(\n configurationName?: string,\n suffix = \"\",\n) {\n return [\"keycloak\", configurationName ?? \"default\", suffix]\n .filter(Boolean)\n .join(\"_\");\n}\n","import { createContext } from \"react\";\nimport { KeycloakContextValue } from \"../types\";\nimport { initialKeycloakContextValue } from \"./keycloak-reducer\";\n\nexport const KeycloakContext = createContext<KeycloakContextValue>(\n initialKeycloakContextValue,\n);\n","import { KeycloakError } from \"keycloak-js\";\nimport { KeycloakContextValue, KeycloakUser } from \"../types\";\n\ntype GenericAction<T extends string, P = undefined> = { type: T; payload: P };\n\nexport type KeycloakAction =\n | GenericAction<\"SET_CONFIGURATION_NAME\", string>\n | GenericAction<\n \"SET_TOKEN\",\n {\n accessToken?: string;\n idToken?: string;\n refreshToken?: string;\n isAuthenticated?: boolean;\n }\n >\n | GenericAction<\"SET_LOADING\", boolean>\n | GenericAction<\"SET_ERROR\", Error | KeycloakError | null>\n | GenericAction<\"SET_SESSION_LOST\", boolean>\n | GenericAction<\"SET_USER_INFO\", KeycloakUser | null>;\n\nexport const initialKeycloakContextValue: KeycloakContextValue = {\n error: null,\n isAuthenticated: false,\n isLoading: true,\n sessionLost: false,\n login: () => Promise.reject(new Error(\"Not implemented\")),\n logout: () => Promise.reject(new Error(\"Not implemented\")),\n userInfo: null,\n configurationName: undefined,\n};\n\nexport function keycloakReducer(\n state: KeycloakContextValue,\n action: KeycloakAction,\n): KeycloakContextValue {\n switch (action.type) {\n case \"SET_CONFIGURATION_NAME\":\n return {\n ...state,\n configurationName: action.payload,\n };\n case \"SET_TOKEN\":\n return {\n ...state,\n accessToken: action.payload.accessToken,\n refreshToken: action.payload.refreshToken,\n idToken: action.payload.idToken,\n isAuthenticated:\n action.payload.isAuthenticated ?? state.isAuthenticated,\n };\n case \"SET_LOADING\":\n return {\n ...state,\n isLoading: action.payload,\n };\n case \"SET_ERROR\":\n return {\n ...state,\n error:\n !action.payload || action.payload instanceof Error\n ? action.payload\n : new Error(\n String(\n action.payload.error || action.payload.error_description,\n ),\n ),\n };\n case \"SET_SESSION_LOST\":\n return {\n ...state,\n sessionLost: action.payload,\n };\n case \"SET_USER_INFO\":\n return {\n ...state,\n userInfo: action.payload,\n };\n\n default:\n return state;\n }\n}\n","import { useContext } from \"react\";\nimport { KeycloakContext } from \"../provider/keycloak-context\";\n\nexport function useKeycloak() {\n const ctx = useContext(KeycloakContext);\n\n return {\n login: ctx.login,\n logout: ctx.logout,\n isLoading: ctx.isLoading,\n isAuthenticated: ctx.isAuthenticated,\n configurationName: ctx.configurationName,\n };\n}\n","import React from \"react\";\nimport { useKeycloak } from \"../hooks/useKeycloak\";\nimport { getSessionStoragePrefixCN } from \"../utils/constants\";\n\nexport const KeycloakSecure: React.FC<React.PropsWithChildren> = ({\n children,\n}) => {\n const { isAuthenticated, login, isLoading, configurationName } =\n useKeycloak();\n\n if (isLoading) return null;\n\n if (!isAuthenticated) {\n // Salva a URL atual antes de redirecionar\n sessionStorage.setItem(\n getSessionStoragePrefixCN(configurationName, \"return_url\"),\n window.location.pathname + window.location.search,\n );\n\n // Redireciona para o Keycloak com callback fixo\n login(); // Usa o redirectUri configurado (ex: /authorization)\n return null;\n }\n\n return children;\n};\n","import { useContext } from \"react\";\nimport { KeycloakContext } from \"../provider/keycloak-context\";\nimport { KeycloakUser } from \"../types\";\n\nexport function useKeycloakUser<UserInfo = KeycloakUser>() {\n const ctx = useContext(KeycloakContext);\n\n return {\n user: ctx?.userInfo as UserInfo | null,\n isLoading: ctx?.isLoading,\n };\n}\n","import { useContext } from \"react\";\nimport { KeycloakContext } from \"../provider/keycloak-context\";\n\nexport function useKeycloakToken() {\n const ctx = useContext(KeycloakContext);\n\n return {\n accessToken: ctx.accessToken,\n idToken: ctx.idToken,\n };\n}\n"],"mappings":"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","names":["useContext","useContext","useContext","useContext"]}
|