Skip to content

Commit 6ae7ec2

Browse files
committed
feat: add isAuthenticated and refreshToken functions
1 parent 11852c7 commit 6ae7ec2

File tree

3 files changed

+119
-0
lines changed

3 files changed

+119
-0
lines changed

lib/utils/token/index.ts

+5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ import { getPermission, PermissionAccess } from "./getPermission";
1010
import { getPermissions, Permissions } from "./getPermissions";
1111
import { getUserOrganizations } from "./getUserOrganistaions";
1212
import { getRoles } from "./getRoles";
13+
import { isAuthenticated } from "./isAuthenticated";
14+
import { refreshToken } from "./refreshToken";
15+
1316
const storage = {
1417
value: null as SessionManager | null,
1518
};
@@ -38,6 +41,8 @@ export {
3841
getPermissions,
3942
getUserOrganizations,
4043
getRoles,
44+
isAuthenticated,
45+
refreshToken,
4146
};
4247

4348
export type { UserProfile, Permissions, PermissionAccess };

lib/utils/token/isAuthenticated.ts

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { JWTDecoded } from "@kinde/jwt-decoder";
2+
import { getDecodedToken, refreshToken } from ".";
3+
4+
export interface IsAuthenticatedPropsWithRefreshToken {
5+
useRefreshToken?: true;
6+
domain?: string;
7+
clientId?: string;
8+
}
9+
10+
export interface IsAuthenticatedPropsWithoutRefreshToken {
11+
useRefreshToken?: false;
12+
domain?: never;
13+
clientId?: never;
14+
}
15+
16+
type IsAuthenticatedProps =
17+
| IsAuthenticatedPropsWithRefreshToken
18+
| IsAuthenticatedPropsWithoutRefreshToken;
19+
20+
/**
21+
* check if the user is authenticated with option to refresh the token
22+
* @returns { Promise<boolean> }
23+
*/
24+
export const isAuthenticated = async (
25+
props?: IsAuthenticatedProps,
26+
): Promise<boolean> => {
27+
try {
28+
const token = await getDecodedToken<JWTDecoded>("accessToken");
29+
if (!token) return false;
30+
31+
const isExpired = token.exp < Math.floor(Date.now() / 1000);
32+
33+
if (isExpired && props?.useRefreshToken) {
34+
return refreshToken(props.domain, props.clientId);
35+
}
36+
return !isExpired;
37+
} catch (error) {
38+
console.error("Error checking authentication:", error);
39+
return false;
40+
}
41+
};

lib/utils/token/refreshToken.ts

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { getActiveStorage } from ".";
2+
import { StorageKeys } from "../../sessionManager";
3+
import { sanatizeURL } from "../sanatizeUrl";
4+
5+
/**
6+
* refreshes the token
7+
* @returns { Promise<boolean> }
8+
*/
9+
export const refreshToken = async (
10+
domain?: string,
11+
clientId?: string,
12+
): Promise<boolean> => {
13+
try {
14+
if (!domain) {
15+
console.error("Domain is required for token refresh");
16+
return false;
17+
}
18+
19+
if (!clientId) {
20+
console.error("Client ID is required for token refresh");
21+
return false;
22+
}
23+
24+
const storage = getActiveStorage();
25+
const refreshTokenValue = await storage.getSessionItem(
26+
StorageKeys.refreshToken,
27+
);
28+
29+
if (!refreshTokenValue) {
30+
console.error("No refresh token found");
31+
return false;
32+
}
33+
34+
const response = await fetch(`${sanatizeURL(domain)}/oauth2/token`, {
35+
method: "POST",
36+
headers: {
37+
"Content-Type": "multipart/form-data",
38+
"Kinde-SDK": "js-utils",
39+
},
40+
body: JSON.stringify({
41+
refresh_token: refreshTokenValue,
42+
grant_type: "refresh_token",
43+
client_id: clientId,
44+
}),
45+
});
46+
47+
if (!response.ok) {
48+
console.error("Failed to refresh token");
49+
return false;
50+
}
51+
52+
const data = await response.json();
53+
54+
if (data.access_token) {
55+
await storage.setSessionItem(StorageKeys.accessToken, data.access_token);
56+
if (data.id_token) {
57+
await storage.setSessionItem(StorageKeys.idToken, data.id_token);
58+
}
59+
if (data.refresh_token) {
60+
await storage.setSessionItem(
61+
StorageKeys.refreshToken,
62+
data.refresh_token,
63+
);
64+
}
65+
return true;
66+
}
67+
68+
return false;
69+
} catch (error) {
70+
console.error("Error refreshing token:", error);
71+
return false;
72+
}
73+
};

0 commit comments

Comments
 (0)