@spidy092/auth-client 2.1.8 → 3.0.1

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.
@@ -1,150 +0,0 @@
1
- // auth-client/react/AuthProvider.jsx
2
- import React, { createContext, useState, useEffect, useRef } from 'react';
3
- import { getToken, setToken, clearToken } from '../token';
4
- import { getConfig } from '../config';
5
- import {
6
- login as coreLogin,
7
- logout as coreLogout,
8
- startSessionSecurity,
9
- stopSessionSecurity,
10
- onSessionInvalid
11
- } from '../core';
12
-
13
- export const AuthContext = createContext();
14
-
15
- export function AuthProvider({ children, onSessionExpired }) {
16
- const [token, setTokenState] = useState(getToken());
17
- const [user, setUser] = useState(null);
18
- const [loading, setLoading] = useState(!!token); // Loading if we have a token to validate
19
- const [sessionValid, setSessionValid] = useState(true);
20
- const sessionSecurityRef = useRef(null);
21
-
22
- // Handle session invalidation (from Keycloak admin deletion or expiry)
23
- const handleSessionInvalid = (reason) => {
24
- console.log('🚨 AuthProvider: Session invalidated -', reason);
25
- setSessionValid(false);
26
- setUser(null);
27
- setTokenState(null);
28
-
29
- // Call custom callback if provided
30
- if (onSessionExpired && typeof onSessionExpired === 'function') {
31
- onSessionExpired(reason);
32
- }
33
- };
34
-
35
- // Start session security on mount (when we have a token)
36
- useEffect(() => {
37
- if (token && !sessionSecurityRef.current) {
38
- console.log('🔐 AuthProvider: Starting session security');
39
-
40
- // Register session invalid handler
41
- const unsubscribe = onSessionInvalid(handleSessionInvalid);
42
-
43
- // Start proactive refresh + session monitoring
44
- sessionSecurityRef.current = startSessionSecurity(handleSessionInvalid);
45
-
46
- return () => {
47
- unsubscribe();
48
- if (sessionSecurityRef.current) {
49
- sessionSecurityRef.current.stopAll();
50
- sessionSecurityRef.current = null;
51
- }
52
- };
53
- }
54
-
55
- // Cleanup when token is removed
56
- if (!token && sessionSecurityRef.current) {
57
- sessionSecurityRef.current.stopAll();
58
- sessionSecurityRef.current = null;
59
- }
60
- }, [token]);
61
-
62
- useEffect(() => {
63
- console.log('🔍 AuthProvider useEffect triggered:', {
64
- hasToken: !!token,
65
- tokenLength: token?.length
66
- });
67
-
68
- if (!token) {
69
- console.log('⚠️ AuthProvider: No token, setting loading=false');
70
- setLoading(false);
71
- return;
72
- }
73
-
74
- const { authBaseUrl } = getConfig();
75
- if (!authBaseUrl) {
76
- console.warn('AuthProvider: No authBaseUrl configured');
77
- setLoading(false);
78
- return;
79
- }
80
-
81
- console.log('🌐 AuthProvider: Fetching profile with token...', {
82
- authBaseUrl,
83
- tokenPreview: token.slice(0, 50) + '...'
84
- });
85
-
86
- fetch(`${authBaseUrl}/account/profile`, {
87
- headers: { Authorization: `Bearer ${token}` },
88
- credentials: 'include',
89
- })
90
- .then(res => {
91
- console.log('📥 Profile response status:', res.status);
92
- if (!res.ok) throw new Error('Failed to fetch user');
93
- return res.json();
94
- })
95
- .then(userData => {
96
- console.log('✅ Profile fetched successfully:', userData.email);
97
- setUser(userData);
98
- setSessionValid(true);
99
- setLoading(false);
100
- })
101
- .catch(err => {
102
- console.error('❌ Fetch user error:', err);
103
- clearToken();
104
- setTokenState(null);
105
- setUser(null);
106
- setLoading(false);
107
- });
108
- }, [token]);
109
-
110
- const login = (clientKey, redirectUri, state) => {
111
- coreLogin(clientKey, redirectUri, state);
112
- };
113
-
114
- const logout = () => {
115
- // Stop session security before logout
116
- stopSessionSecurity();
117
- sessionSecurityRef.current = null;
118
-
119
- coreLogout();
120
- setUser(null);
121
- setTokenState(null);
122
- setSessionValid(true);
123
- };
124
-
125
- const value = {
126
- token,
127
- user,
128
- loading,
129
- login,
130
- logout,
131
- isAuthenticated: !!token && !!user && sessionValid,
132
- sessionValid,
133
- setUser,
134
- setToken: (newToken) => {
135
- setToken(newToken);
136
- setTokenState(newToken);
137
- setSessionValid(true);
138
- },
139
- clearToken: () => {
140
- stopSessionSecurity();
141
- sessionSecurityRef.current = null;
142
- clearToken();
143
- setTokenState(null);
144
- setUser(null);
145
- },
146
- };
147
-
148
- return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
149
- }
150
-
package/react/useAuth.js DELETED
@@ -1,10 +0,0 @@
1
- import { useContext } from 'react';
2
- import { AuthContext } from './AuthProvider';
3
-
4
- export function useAuth() {
5
- const context = useContext(AuthContext);
6
- if (!context) {
7
- throw new Error('useAuth must be used within an AuthProvider');
8
- }
9
- return context;
10
- }
@@ -1,121 +0,0 @@
1
- // auth-client/react/useSessionMonitor.js
2
- // Enhanced session monitoring hook for detecting Keycloak admin session deletions
3
- import { useQuery, useQueryClient } from '@tanstack/react-query';
4
- import { useEffect, useCallback } from 'react';
5
- import { auth } from '../index';
6
-
7
- /**
8
- * useSessionMonitor - React hook for periodic session validation
9
- *
10
- * This hook validates that the user's session still exists in Keycloak.
11
- * When an admin deletes a session from Keycloak Admin UI, this hook
12
- * will detect it and trigger the onSessionInvalid callback.
13
- *
14
- * @param {Object} options Configuration options
15
- * @param {boolean} options.enabled - Enable/disable monitoring (default: true)
16
- * @param {number} options.refetchInterval - Validation interval in ms (default: 120000 = 2 min)
17
- * @param {Function} options.onSessionInvalid - Callback when session is deleted
18
- * @param {Function} options.onError - Callback for validation errors
19
- * @param {boolean} options.autoLogout - Auto logout on invalid session (default: true)
20
- * @param {boolean} options.validateOnMount - Validate session immediately on mount (default: true)
21
- */
22
- export const useSessionMonitor = (options = {}) => {
23
- const queryClient = useQueryClient();
24
-
25
- const {
26
- enabled = true,
27
- refetchInterval = 2 * 60 * 1000, // 2 minutes (matching config default)
28
- onSessionInvalid,
29
- onError,
30
- autoLogout = true,
31
- validateOnMount = true,
32
- } = options;
33
-
34
- // Handle session invalidation
35
- const handleInvalid = useCallback(() => {
36
- console.log('🚨 useSessionMonitor: Session invalid detected');
37
-
38
- // Clear all react-query cache
39
- queryClient.clear();
40
-
41
- // Auto logout if enabled
42
- if (autoLogout) {
43
- auth.clearToken();
44
- auth.clearRefreshToken();
45
- }
46
-
47
- // Call custom callback
48
- if (onSessionInvalid) {
49
- onSessionInvalid();
50
- }
51
- }, [queryClient, autoLogout, onSessionInvalid]);
52
-
53
- // Session validation query
54
- const query = useQuery({
55
- queryKey: ['session-validation'],
56
- queryFn: async () => {
57
- try {
58
- const token = auth.getToken();
59
- if (!token) {
60
- return { valid: false, reason: 'no_token' };
61
- }
62
-
63
- console.log('🔍 useSessionMonitor: Validating session...');
64
- const isValid = await auth.validateCurrentSession();
65
-
66
- if (!isValid) {
67
- console.log('❌ useSessionMonitor: Session no longer valid');
68
- handleInvalid();
69
- return { valid: false, reason: 'session_deleted' };
70
- }
71
-
72
- console.log('✅ useSessionMonitor: Session still valid');
73
- return { valid: true };
74
- } catch (error) {
75
- console.error('⚠️ useSessionMonitor: Validation error:', error);
76
- if (onError) {
77
- onError(error);
78
- }
79
- throw error;
80
- }
81
- },
82
- enabled: enabled && !!auth.getToken(),
83
- refetchInterval,
84
- refetchIntervalInBackground: true,
85
- retry: 2,
86
- retryDelay: 5000,
87
- staleTime: refetchInterval / 2, // Consider stale at half the interval
88
- });
89
-
90
- // Validate on visibility change (when user returns to tab)
91
- useEffect(() => {
92
- if (!enabled) return;
93
-
94
- const handleVisibilityChange = () => {
95
- if (document.visibilityState === 'visible' && auth.getToken()) {
96
- console.log('👁️ useSessionMonitor: Tab visible - triggering validation');
97
- queryClient.invalidateQueries({ queryKey: ['session-validation'] });
98
- }
99
- };
100
-
101
- document.addEventListener('visibilitychange', handleVisibilityChange);
102
- return () => {
103
- document.removeEventListener('visibilitychange', handleVisibilityChange);
104
- };
105
- }, [enabled, queryClient]);
106
-
107
- // Validate immediately on mount if enabled
108
- useEffect(() => {
109
- if (validateOnMount && enabled && auth.getToken()) {
110
- queryClient.invalidateQueries({ queryKey: ['session-validation'] });
111
- }
112
- }, [validateOnMount, enabled, queryClient]);
113
-
114
- return {
115
- ...query,
116
- isSessionValid: query.data?.valid ?? true,
117
- invalidationReason: query.data?.reason,
118
- manualValidate: () => queryClient.invalidateQueries({ queryKey: ['session-validation'] }),
119
- };
120
- };
121
-