Add session expired detection and auto-refresh in WebView
- Monitor page content for "session expired" patterns - Send message to React Native when detected - Auto-refresh token and reload WebView - Add logging to refreshToken for debugging
This commit is contained in:
parent
bc33230739
commit
173c0a8262
@ -10,6 +10,8 @@ import { AppColors, FontSizes, Spacing } from '@/constants/theme';
|
|||||||
const DASHBOARD_URL = 'https://react.eluxnetworks.net/dashboard';
|
const DASHBOARD_URL = 'https://react.eluxnetworks.net/dashboard';
|
||||||
// URLs that indicate session expired (login page)
|
// URLs that indicate session expired (login page)
|
||||||
const LOGIN_URL_PATTERNS = ['/login', '/auth', '/signin'];
|
const LOGIN_URL_PATTERNS = ['/login', '/auth', '/signin'];
|
||||||
|
// Text patterns that indicate session expired (shown in page content)
|
||||||
|
const SESSION_EXPIRED_PATTERNS = ['session expired', 'session has expired', 'token expired', 'please log in'];
|
||||||
|
|
||||||
export default function HomeScreen() {
|
export default function HomeScreen() {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
@ -134,12 +136,13 @@ export default function HomeScreen() {
|
|||||||
}
|
}
|
||||||
}, [isRefreshingToken]);
|
}, [isRefreshingToken]);
|
||||||
|
|
||||||
// JavaScript to inject auth token into localStorage
|
// JavaScript to inject auth token into localStorage and monitor for session expiry
|
||||||
// Web app expects auth2 as JSON: {username, token, user_id}
|
// Web app expects auth2 as JSON: {username, token, user_id}
|
||||||
const injectedJavaScript = authToken
|
const injectedJavaScript = authToken
|
||||||
? `
|
? `
|
||||||
(function() {
|
(function() {
|
||||||
try {
|
try {
|
||||||
|
// Inject auth data
|
||||||
var authData = {
|
var authData = {
|
||||||
username: '${userName || ''}',
|
username: '${userName || ''}',
|
||||||
token: '${authToken}',
|
token: '${authToken}',
|
||||||
@ -147,6 +150,33 @@ export default function HomeScreen() {
|
|||||||
};
|
};
|
||||||
localStorage.setItem('auth2', JSON.stringify(authData));
|
localStorage.setItem('auth2', JSON.stringify(authData));
|
||||||
console.log('Auth injected:', authData.username);
|
console.log('Auth injected:', authData.username);
|
||||||
|
|
||||||
|
// Monitor page content for session expired messages
|
||||||
|
var sessionExpiredPatterns = ${JSON.stringify(SESSION_EXPIRED_PATTERNS)};
|
||||||
|
|
||||||
|
function checkForSessionExpired() {
|
||||||
|
var bodyText = (document.body?.innerText || '').toLowerCase();
|
||||||
|
for (var i = 0; i < sessionExpiredPatterns.length; i++) {
|
||||||
|
if (bodyText.includes(sessionExpiredPatterns[i])) {
|
||||||
|
console.log('Session expired detected in page content');
|
||||||
|
window.ReactNativeWebView?.postMessage(JSON.stringify({ type: 'SESSION_EXPIRED' }));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check after page loads and periodically
|
||||||
|
setTimeout(checkForSessionExpired, 1000);
|
||||||
|
setTimeout(checkForSessionExpired, 3000);
|
||||||
|
|
||||||
|
// Also observe DOM changes for dynamic content
|
||||||
|
var observer = new MutationObserver(function() {
|
||||||
|
checkForSessionExpired();
|
||||||
|
});
|
||||||
|
if (document.body) {
|
||||||
|
observer.observe(document.body, { childList: true, subtree: true });
|
||||||
|
}
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.error('Failed to inject token:', e);
|
console.error('Failed to inject token:', e);
|
||||||
}
|
}
|
||||||
@ -199,6 +229,19 @@ export default function HomeScreen() {
|
|||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handle messages from WebView (session expired detection)
|
||||||
|
const handleWebViewMessage = useCallback((event: { nativeEvent: { data: string } }) => {
|
||||||
|
try {
|
||||||
|
const message = JSON.parse(event.nativeEvent.data);
|
||||||
|
if (message.type === 'SESSION_EXPIRED') {
|
||||||
|
console.log('WebView reported session expired, refreshing token...');
|
||||||
|
handleTokenRefresh();
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Ignore non-JSON messages
|
||||||
|
}
|
||||||
|
}, [handleTokenRefresh]);
|
||||||
|
|
||||||
// Wait for token to load
|
// Wait for token to load
|
||||||
if (!isTokenLoaded) {
|
if (!isTokenLoaded) {
|
||||||
return (
|
return (
|
||||||
@ -285,6 +328,7 @@ export default function HomeScreen() {
|
|||||||
onHttpError={handleError}
|
onHttpError={handleError}
|
||||||
onNavigationStateChange={handleNavigationStateChange}
|
onNavigationStateChange={handleNavigationStateChange}
|
||||||
onShouldStartLoadWithRequest={handleShouldStartLoadWithRequest}
|
onShouldStartLoadWithRequest={handleShouldStartLoadWithRequest}
|
||||||
|
onMessage={handleWebViewMessage}
|
||||||
javaScriptEnabled={true}
|
javaScriptEnabled={true}
|
||||||
domStorageEnabled={true}
|
domStorageEnabled={true}
|
||||||
startInLoadingState={true}
|
startInLoadingState={true}
|
||||||
|
|||||||
@ -100,13 +100,20 @@ class ApiService {
|
|||||||
const userName = await SecureStore.getItemAsync('userName');
|
const userName = await SecureStore.getItemAsync('userName');
|
||||||
const password = await SecureStore.getItemAsync('userPassword');
|
const password = await SecureStore.getItemAsync('userPassword');
|
||||||
|
|
||||||
|
console.log('[API] refreshToken - userName:', userName ? 'exists' : 'missing');
|
||||||
|
console.log('[API] refreshToken - password:', password ? 'exists' : 'missing');
|
||||||
|
|
||||||
if (!userName || !password) {
|
if (!userName || !password) {
|
||||||
|
console.log('[API] refreshToken - NO_CREDENTIALS');
|
||||||
return { ok: false, error: { message: 'No stored credentials', code: 'NO_CREDENTIALS' } };
|
return { ok: false, error: { message: 'No stored credentials', code: 'NO_CREDENTIALS' } };
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Refreshing token for user:', userName);
|
console.log('[API] Refreshing token for user:', userName);
|
||||||
return await this.login(userName, password);
|
const result = await this.login(userName, password);
|
||||||
|
console.log('[API] refreshToken result:', result.ok ? 'SUCCESS' : result.error?.message);
|
||||||
|
return result;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.error('[API] refreshToken error:', error);
|
||||||
return {
|
return {
|
||||||
ok: false,
|
ok: false,
|
||||||
error: { message: 'Failed to refresh token', code: 'REFRESH_ERROR' }
|
error: { message: 'Failed to refresh token', code: 'REFRESH_ERROR' }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user