-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* fix token expired * Update tokenExpirationHandler.ts * update token * time expandation * update token * update token * Stop tracking yarn.lock and ignore it * Update .gitignore * update token * update token * time expandation * fix token expired * Update tokenExpirationHandler.ts * Update .gitignore * Update .gitignore to ignore yarn.lock * Restore yarn.lock to the repository * Update .gitignore to ignore yarn.lock in future changes * Update .gitignore to ignore yarn.lock * Update .gitignore to ignore yarn.lock * Update .gitignore to ignore yarn.lock * signup button * signup button
- Loading branch information
1 parent
6bf831a
commit 4e2a670
Showing
3 changed files
with
140 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import jwtDecode from 'jwt-decode'; | ||
import { toast } from 'react-toastify'; | ||
|
||
interface DecodedToken { | ||
exp?: number; | ||
iat?: number; | ||
data?: { | ||
email: string; | ||
}; | ||
email?: string; | ||
} | ||
|
||
class TokenExpirationHandler { | ||
private static readonly STORAGE_KEYS = { | ||
ACCESS_TOKEN: 'access_token', | ||
TOKEN_ISSUED_TIME: 'token_issued_time', | ||
} as const; | ||
|
||
private static readonly LOGIN_ROUTE = '/login'; | ||
|
||
private static showToast(message: string) { | ||
toast.error(message); | ||
} | ||
|
||
private static clearAuthData() { | ||
localStorage.clear(); | ||
} | ||
|
||
private static redirect() { | ||
window.location.href = this.LOGIN_ROUTE; | ||
} | ||
|
||
private static handleRedirection(message: string) { | ||
this.showToast(message); | ||
this.clearAuthData(); | ||
setTimeout(() => this.redirect(), 400); | ||
} | ||
|
||
public static isTokenExpired(token: string): boolean { | ||
try { | ||
const decoded = jwtDecode<DecodedToken>(token); | ||
const tokenIssuedTime = localStorage.getItem(this.STORAGE_KEYS.TOKEN_ISSUED_TIME); | ||
const issuedTime = tokenIssuedTime ? parseInt(tokenIssuedTime, 10) : null; | ||
|
||
|
||
const currentTime = Date.now() / 1000; | ||
|
||
|
||
const tokenIat = issuedTime || decoded.iat; | ||
if (!tokenIat) return false; | ||
|
||
const timeElapsedSinceIssue = currentTime - tokenIat; | ||
const ExTime = 60 * 60; | ||
|
||
|
||
return timeElapsedSinceIssue > ExTime; | ||
} catch { | ||
return true; | ||
} | ||
} | ||
|
||
public static validateToken(): boolean { | ||
const token = localStorage.getItem(this.STORAGE_KEYS.ACCESS_TOKEN); | ||
|
||
if (!token) { | ||
this.handleRedirection('Please login to continue'); | ||
return false; | ||
} | ||
|
||
if (this.isTokenExpired(token)) { | ||
this.handleRedirection('Your session has expired after 1 hour. Please login again'); | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
public static handleAuthError(error: any): void { | ||
const errorMessage = error?.message?.toLowerCase() || ''; | ||
|
||
if (errorMessage.includes('jwt expired')) { | ||
this.handleRedirection('Your session has expired. Please login again'); | ||
} else if (errorMessage.includes('invalid token')) { | ||
this.handleRedirection('Invalid authentication. Please login again'); | ||
} else if (errorMessage.includes('unauthorized')) { | ||
this.handleRedirection('Unauthorized access. Please login again'); | ||
} else { | ||
this.handleRedirection('Authentication error. Please login again'); | ||
} | ||
} | ||
|
||
public static forceLogout(message?: string): void { | ||
this.handleRedirection(message || 'You have been logged out'); | ||
} | ||
|
||
public static storeToken(token: string): void { | ||
localStorage.setItem(this.STORAGE_KEYS.ACCESS_TOKEN, token); | ||
|
||
localStorage.setItem(this.STORAGE_KEYS.TOKEN_ISSUED_TIME, Math.floor(Date.now() / 1000).toString()); | ||
} | ||
} | ||
|
||
export default TokenExpirationHandler; |