say-auth 1.1.0 → 1.1.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.
- package/dist/index.d.mts +24 -1
- package/dist/index.d.ts +24 -1
- package/dist/index.js +270 -55
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +208 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -290,6 +290,29 @@ interface AuthProviderProps {
|
|
|
290
290
|
}
|
|
291
291
|
declare function AuthProvider({ children, apiUrl, onError, onSessionExpired, onLogin, onLogout, autoRefresh, refreshThreshold }: AuthProviderProps): react_jsx_runtime.JSX.Element;
|
|
292
292
|
declare function useAuthContext(): AuthContextValue;
|
|
293
|
+
declare function withAuth<P extends object>(Component: React__default.ComponentType<P>): React__default.FC<P & {
|
|
294
|
+
auth?: AuthContextValue;
|
|
295
|
+
}>;
|
|
296
|
+
interface RoleBasedProps {
|
|
297
|
+
children: React__default.ReactNode;
|
|
298
|
+
roles: string | string[];
|
|
299
|
+
fallback?: React__default.ReactNode;
|
|
300
|
+
}
|
|
301
|
+
declare function RoleBased({ children, roles, fallback }: RoleBasedProps): react_jsx_runtime.JSX.Element;
|
|
302
|
+
interface MFARequiredProps {
|
|
303
|
+
children: React__default.ReactNode;
|
|
304
|
+
redirectTo?: string;
|
|
305
|
+
}
|
|
306
|
+
declare function MFARequired({ children, redirectTo }: MFARequiredProps): react_jsx_runtime.JSX.Element | null;
|
|
307
|
+
declare function AuthStatus(): react_jsx_runtime.JSX.Element;
|
|
308
|
+
declare function SessionTimer(): react_jsx_runtime.JSX.Element | null;
|
|
309
|
+
declare function AuthDebug(): react_jsx_runtime.JSX.Element | null;
|
|
310
|
+
declare function SessionMonitor(): null;
|
|
311
|
+
interface SessionExpiryWarningProps {
|
|
312
|
+
warningMinutes?: number[];
|
|
313
|
+
onExtend?: () => void;
|
|
314
|
+
}
|
|
315
|
+
declare function SessionExpiryWarning({ warningMinutes, onExtend }: SessionExpiryWarningProps): react_jsx_runtime.JSX.Element | null;
|
|
293
316
|
|
|
294
317
|
interface ProtectedRouteProps {
|
|
295
318
|
children: React.ReactNode;
|
|
@@ -379,4 +402,4 @@ declare const securityHeaders: {
|
|
|
379
402
|
};
|
|
380
403
|
declare function applySecurityHeaders(response: Response): Response;
|
|
381
404
|
|
|
382
|
-
export { API_ENDPOINTS, AUTH_CONFIG, AuditAction, type AuditEntry$1 as AuditEntry, AuditLogger, AuthProvider, AuthService, type AuthState, type AuthTokens, DeviceFingerprint, type LoginCredentials, LoginForm, MFAService, MFASetup, MFAVerification, type MFAVerify, ProtectedRoute, RateLimiter, type RegisterData, STORAGE_KEYS, SessionManager, SessionWarning, TokenBlacklist, type TokenBlacklistEntry, TokenManager, SecureTokenStorage as TokenStorage, type User, applySecurityHeaders, cn, errorTracker, formatDate, generateRandomString, getErrorMessage, initErrorTracker, isValidEmail, securityHeaders, setupAuthInterceptors, useAuth, useAuthContext, useProtectedRoute, validateEnvironment };
|
|
405
|
+
export { API_ENDPOINTS, AUTH_CONFIG, AuditAction, type AuditEntry$1 as AuditEntry, AuditLogger, AuthDebug, AuthProvider, AuthService, type AuthState, AuthStatus, type AuthTokens, DeviceFingerprint, type LoginCredentials, LoginForm, MFARequired, MFAService, MFASetup, MFAVerification, type MFAVerify, ProtectedRoute, RateLimiter, type RegisterData, RoleBased, STORAGE_KEYS, SessionExpiryWarning, SessionManager, SessionMonitor, SessionTimer, SessionWarning, TokenBlacklist, type TokenBlacklistEntry, TokenManager, SecureTokenStorage as TokenStorage, type User, applySecurityHeaders, cn, errorTracker, formatDate, generateRandomString, getErrorMessage, initErrorTracker, isValidEmail, securityHeaders, setupAuthInterceptors, useAuth, useAuthContext, useProtectedRoute, validateEnvironment, withAuth };
|
package/dist/index.d.ts
CHANGED
|
@@ -290,6 +290,29 @@ interface AuthProviderProps {
|
|
|
290
290
|
}
|
|
291
291
|
declare function AuthProvider({ children, apiUrl, onError, onSessionExpired, onLogin, onLogout, autoRefresh, refreshThreshold }: AuthProviderProps): react_jsx_runtime.JSX.Element;
|
|
292
292
|
declare function useAuthContext(): AuthContextValue;
|
|
293
|
+
declare function withAuth<P extends object>(Component: React__default.ComponentType<P>): React__default.FC<P & {
|
|
294
|
+
auth?: AuthContextValue;
|
|
295
|
+
}>;
|
|
296
|
+
interface RoleBasedProps {
|
|
297
|
+
children: React__default.ReactNode;
|
|
298
|
+
roles: string | string[];
|
|
299
|
+
fallback?: React__default.ReactNode;
|
|
300
|
+
}
|
|
301
|
+
declare function RoleBased({ children, roles, fallback }: RoleBasedProps): react_jsx_runtime.JSX.Element;
|
|
302
|
+
interface MFARequiredProps {
|
|
303
|
+
children: React__default.ReactNode;
|
|
304
|
+
redirectTo?: string;
|
|
305
|
+
}
|
|
306
|
+
declare function MFARequired({ children, redirectTo }: MFARequiredProps): react_jsx_runtime.JSX.Element | null;
|
|
307
|
+
declare function AuthStatus(): react_jsx_runtime.JSX.Element;
|
|
308
|
+
declare function SessionTimer(): react_jsx_runtime.JSX.Element | null;
|
|
309
|
+
declare function AuthDebug(): react_jsx_runtime.JSX.Element | null;
|
|
310
|
+
declare function SessionMonitor(): null;
|
|
311
|
+
interface SessionExpiryWarningProps {
|
|
312
|
+
warningMinutes?: number[];
|
|
313
|
+
onExtend?: () => void;
|
|
314
|
+
}
|
|
315
|
+
declare function SessionExpiryWarning({ warningMinutes, onExtend }: SessionExpiryWarningProps): react_jsx_runtime.JSX.Element | null;
|
|
293
316
|
|
|
294
317
|
interface ProtectedRouteProps {
|
|
295
318
|
children: React.ReactNode;
|
|
@@ -379,4 +402,4 @@ declare const securityHeaders: {
|
|
|
379
402
|
};
|
|
380
403
|
declare function applySecurityHeaders(response: Response): Response;
|
|
381
404
|
|
|
382
|
-
export { API_ENDPOINTS, AUTH_CONFIG, AuditAction, type AuditEntry$1 as AuditEntry, AuditLogger, AuthProvider, AuthService, type AuthState, type AuthTokens, DeviceFingerprint, type LoginCredentials, LoginForm, MFAService, MFASetup, MFAVerification, type MFAVerify, ProtectedRoute, RateLimiter, type RegisterData, STORAGE_KEYS, SessionManager, SessionWarning, TokenBlacklist, type TokenBlacklistEntry, TokenManager, SecureTokenStorage as TokenStorage, type User, applySecurityHeaders, cn, errorTracker, formatDate, generateRandomString, getErrorMessage, initErrorTracker, isValidEmail, securityHeaders, setupAuthInterceptors, useAuth, useAuthContext, useProtectedRoute, validateEnvironment };
|
|
405
|
+
export { API_ENDPOINTS, AUTH_CONFIG, AuditAction, type AuditEntry$1 as AuditEntry, AuditLogger, AuthDebug, AuthProvider, AuthService, type AuthState, AuthStatus, type AuthTokens, DeviceFingerprint, type LoginCredentials, LoginForm, MFARequired, MFAService, MFASetup, MFAVerification, type MFAVerify, ProtectedRoute, RateLimiter, type RegisterData, RoleBased, STORAGE_KEYS, SessionExpiryWarning, SessionManager, SessionMonitor, SessionTimer, SessionWarning, TokenBlacklist, type TokenBlacklistEntry, TokenManager, SecureTokenStorage as TokenStorage, type User, applySecurityHeaders, cn, errorTracker, formatDate, generateRandomString, getErrorMessage, initErrorTracker, isValidEmail, securityHeaders, setupAuthInterceptors, useAuth, useAuthContext, useProtectedRoute, validateEnvironment, withAuth };
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ var CryptoJS = require('crypto-js');
|
|
|
5
5
|
var OTPAuth = require('otpauth');
|
|
6
6
|
var QRCode = require('qrcode');
|
|
7
7
|
var rfc4648 = require('rfc4648');
|
|
8
|
-
var
|
|
8
|
+
var React = require('react');
|
|
9
9
|
var navigation = require('next/navigation');
|
|
10
10
|
var jsxRuntime = require('react/jsx-runtime');
|
|
11
11
|
var lucideReact = require('lucide-react');
|
|
@@ -34,6 +34,7 @@ var axios__default = /*#__PURE__*/_interopDefault(axios);
|
|
|
34
34
|
var CryptoJS__default = /*#__PURE__*/_interopDefault(CryptoJS);
|
|
35
35
|
var OTPAuth__namespace = /*#__PURE__*/_interopNamespace(OTPAuth);
|
|
36
36
|
var QRCode__default = /*#__PURE__*/_interopDefault(QRCode);
|
|
37
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
37
38
|
|
|
38
39
|
// src/utils/constants.ts
|
|
39
40
|
var AUTH_CONFIG = {
|
|
@@ -1017,8 +1018,8 @@ var AuthService = class _AuthService {
|
|
|
1017
1018
|
}
|
|
1018
1019
|
};
|
|
1019
1020
|
function useAuth(apiUrl) {
|
|
1020
|
-
const [state, setState] =
|
|
1021
|
-
|
|
1021
|
+
const [state, setState] = React.useState(AuthService.getInstance(apiUrl).getState());
|
|
1022
|
+
React.useEffect(() => {
|
|
1022
1023
|
const unsubscribe = AuthService.getInstance(apiUrl).subscribe(setState);
|
|
1023
1024
|
return unsubscribe;
|
|
1024
1025
|
}, [apiUrl]);
|
|
@@ -1053,7 +1054,7 @@ function useAuth(apiUrl) {
|
|
|
1053
1054
|
function useProtectedRoute(redirectTo = "/login", requiredRole) {
|
|
1054
1055
|
const { isAuthenticated, isLoading, hasRole } = useAuth();
|
|
1055
1056
|
const router = navigation.useRouter();
|
|
1056
|
-
|
|
1057
|
+
React.useEffect(() => {
|
|
1057
1058
|
if (!isLoading && !isAuthenticated) {
|
|
1058
1059
|
router.push(redirectTo);
|
|
1059
1060
|
}
|
|
@@ -1063,7 +1064,7 @@ function useProtectedRoute(redirectTo = "/login", requiredRole) {
|
|
|
1063
1064
|
}, [isAuthenticated, isLoading, router, redirectTo, requiredRole, hasRole]);
|
|
1064
1065
|
return { isAuthenticated, isLoading };
|
|
1065
1066
|
}
|
|
1066
|
-
var AuthContext =
|
|
1067
|
+
var AuthContext = React.createContext(null);
|
|
1067
1068
|
function AuthProvider({
|
|
1068
1069
|
children,
|
|
1069
1070
|
apiUrl,
|
|
@@ -1074,17 +1075,17 @@ function AuthProvider({
|
|
|
1074
1075
|
autoRefresh = true,
|
|
1075
1076
|
refreshThreshold = AUTH_CONFIG.tokenRefreshThreshold
|
|
1076
1077
|
}) {
|
|
1077
|
-
const [state, setState] =
|
|
1078
|
+
const [state, setState] = React.useState({
|
|
1078
1079
|
user: null,
|
|
1079
1080
|
tokens: null,
|
|
1080
1081
|
isAuthenticated: false,
|
|
1081
1082
|
isLoading: true,
|
|
1082
1083
|
error: null
|
|
1083
1084
|
});
|
|
1084
|
-
const [refreshTimeout, setRefreshTimeout] =
|
|
1085
|
-
const [sessionTimeout, setSessionTimeout] =
|
|
1086
|
-
const authService =
|
|
1087
|
-
|
|
1085
|
+
const [refreshTimeout, setRefreshTimeout] = React.useState(null);
|
|
1086
|
+
const [sessionTimeout, setSessionTimeout] = React.useState(null);
|
|
1087
|
+
const authService = React.useMemo(() => AuthService.getInstance(apiUrl), [apiUrl]);
|
|
1088
|
+
React.useEffect(() => {
|
|
1088
1089
|
const unsubscribe = authService.subscribe((newState) => {
|
|
1089
1090
|
setState(newState);
|
|
1090
1091
|
if (!newState.isAuthenticated && newState.error === "Session expired") {
|
|
@@ -1105,7 +1106,7 @@ function AuthProvider({
|
|
|
1105
1106
|
if (sessionTimeout) clearTimeout(sessionTimeout);
|
|
1106
1107
|
};
|
|
1107
1108
|
}, [authService, onError, onSessionExpired, onLogin, onLogout]);
|
|
1108
|
-
|
|
1109
|
+
React.useEffect(() => {
|
|
1109
1110
|
if (!autoRefresh || !state.tokens?.accessToken || !state.isAuthenticated) {
|
|
1110
1111
|
return;
|
|
1111
1112
|
}
|
|
@@ -1128,7 +1129,7 @@ function AuthProvider({
|
|
|
1128
1129
|
if (refreshTimeout) clearTimeout(refreshTimeout);
|
|
1129
1130
|
};
|
|
1130
1131
|
}, [state.tokens?.accessToken, state.isAuthenticated, autoRefresh, refreshThreshold]);
|
|
1131
|
-
|
|
1132
|
+
React.useEffect(() => {
|
|
1132
1133
|
if (!state.isAuthenticated || !state.tokens?.accessToken) {
|
|
1133
1134
|
return;
|
|
1134
1135
|
}
|
|
@@ -1150,7 +1151,7 @@ function AuthProvider({
|
|
|
1150
1151
|
if (sessionTimeout) clearTimeout(sessionTimeout);
|
|
1151
1152
|
};
|
|
1152
1153
|
}, [state.tokens?.accessToken, state.isAuthenticated]);
|
|
1153
|
-
const getTokenExpiry =
|
|
1154
|
+
const getTokenExpiry = React.useCallback((token) => {
|
|
1154
1155
|
try {
|
|
1155
1156
|
const payload = JSON.parse(atob(token.split(".")[1]));
|
|
1156
1157
|
return payload.exp ? new Date(payload.exp * 1e3) : null;
|
|
@@ -1158,12 +1159,12 @@ function AuthProvider({
|
|
|
1158
1159
|
return null;
|
|
1159
1160
|
}
|
|
1160
1161
|
}, []);
|
|
1161
|
-
const handleSessionExpired =
|
|
1162
|
+
const handleSessionExpired = React.useCallback(async () => {
|
|
1162
1163
|
console.warn("Session expired");
|
|
1163
1164
|
await authService.logout("security");
|
|
1164
1165
|
onSessionExpired?.();
|
|
1165
1166
|
}, [authService, onSessionExpired]);
|
|
1166
|
-
const login =
|
|
1167
|
+
const login = React.useCallback(async (credentials) => {
|
|
1167
1168
|
try {
|
|
1168
1169
|
const result = await authService.login(credentials);
|
|
1169
1170
|
return result;
|
|
@@ -1172,7 +1173,7 @@ function AuthProvider({
|
|
|
1172
1173
|
throw new Error(errorMessage);
|
|
1173
1174
|
}
|
|
1174
1175
|
}, [authService]);
|
|
1175
|
-
const register =
|
|
1176
|
+
const register = React.useCallback(async (data) => {
|
|
1176
1177
|
try {
|
|
1177
1178
|
const user = await authService.register(data);
|
|
1178
1179
|
return user;
|
|
@@ -1181,14 +1182,14 @@ function AuthProvider({
|
|
|
1181
1182
|
throw new Error(errorMessage);
|
|
1182
1183
|
}
|
|
1183
1184
|
}, [authService]);
|
|
1184
|
-
const logout =
|
|
1185
|
+
const logout = React.useCallback(async () => {
|
|
1185
1186
|
try {
|
|
1186
1187
|
await authService.logout("logout");
|
|
1187
1188
|
} catch (error) {
|
|
1188
1189
|
console.error("Logout error:", error);
|
|
1189
1190
|
}
|
|
1190
1191
|
}, [authService]);
|
|
1191
|
-
const logoutAllDevices =
|
|
1192
|
+
const logoutAllDevices = React.useCallback(async () => {
|
|
1192
1193
|
try {
|
|
1193
1194
|
await authService.logoutAllDevices();
|
|
1194
1195
|
} catch (error) {
|
|
@@ -1196,14 +1197,14 @@ function AuthProvider({
|
|
|
1196
1197
|
throw error;
|
|
1197
1198
|
}
|
|
1198
1199
|
}, [authService]);
|
|
1199
|
-
const refreshSession =
|
|
1200
|
+
const refreshSession = React.useCallback(async () => {
|
|
1200
1201
|
try {
|
|
1201
1202
|
await authService.refreshSession();
|
|
1202
1203
|
} catch (error) {
|
|
1203
1204
|
console.error("Session refresh failed:", error);
|
|
1204
1205
|
}
|
|
1205
1206
|
}, [authService]);
|
|
1206
|
-
const changePassword =
|
|
1207
|
+
const changePassword = React.useCallback(async (currentPassword, newPassword) => {
|
|
1207
1208
|
try {
|
|
1208
1209
|
await authService.changePassword(currentPassword, newPassword);
|
|
1209
1210
|
} catch (error) {
|
|
@@ -1211,7 +1212,7 @@ function AuthProvider({
|
|
|
1211
1212
|
throw new Error(errorMessage);
|
|
1212
1213
|
}
|
|
1213
1214
|
}, [authService]);
|
|
1214
|
-
const verifyMFA =
|
|
1215
|
+
const verifyMFA = React.useCallback(async (code, trustDevice) => {
|
|
1215
1216
|
try {
|
|
1216
1217
|
const user = await authService.verifyMFA(code, trustDevice || false);
|
|
1217
1218
|
return user;
|
|
@@ -1220,7 +1221,7 @@ function AuthProvider({
|
|
|
1220
1221
|
throw new Error(errorMessage);
|
|
1221
1222
|
}
|
|
1222
1223
|
}, [authService]);
|
|
1223
|
-
const setupMFA =
|
|
1224
|
+
const setupMFA = React.useCallback(async () => {
|
|
1224
1225
|
try {
|
|
1225
1226
|
const response = await authService.getAxiosInstance().post("/auth/mfa/setup");
|
|
1226
1227
|
return response.data;
|
|
@@ -1229,7 +1230,7 @@ function AuthProvider({
|
|
|
1229
1230
|
throw new Error(errorMessage);
|
|
1230
1231
|
}
|
|
1231
1232
|
}, [authService]);
|
|
1232
|
-
const disableMFA =
|
|
1233
|
+
const disableMFA = React.useCallback(async (code) => {
|
|
1233
1234
|
try {
|
|
1234
1235
|
await authService.getAxiosInstance().post("/auth/mfa/disable", { code });
|
|
1235
1236
|
if (state.user) {
|
|
@@ -1243,16 +1244,16 @@ function AuthProvider({
|
|
|
1243
1244
|
throw new Error(errorMessage);
|
|
1244
1245
|
}
|
|
1245
1246
|
}, [authService, state.user]);
|
|
1246
|
-
const hasRole =
|
|
1247
|
+
const hasRole = React.useCallback((role) => {
|
|
1247
1248
|
return authService.hasRole(role);
|
|
1248
1249
|
}, [authService]);
|
|
1249
|
-
const getAxiosInstance =
|
|
1250
|
+
const getAxiosInstance = React.useCallback(() => {
|
|
1250
1251
|
return authService.getAxiosInstance();
|
|
1251
1252
|
}, [authService]);
|
|
1252
|
-
const getUser =
|
|
1253
|
+
const getUser = React.useCallback(() => {
|
|
1253
1254
|
return authService.getUser();
|
|
1254
1255
|
}, [authService]);
|
|
1255
|
-
const updateUser =
|
|
1256
|
+
const updateUser = React.useCallback(async (userData) => {
|
|
1256
1257
|
try {
|
|
1257
1258
|
const updatedUser = await authService.getAxiosInstance().put("/users/profile", userData);
|
|
1258
1259
|
setState((prev) => ({ ...prev, user: updatedUser.data }));
|
|
@@ -1261,34 +1262,34 @@ function AuthProvider({
|
|
|
1261
1262
|
throw new Error(errorMessage);
|
|
1262
1263
|
}
|
|
1263
1264
|
}, [authService]);
|
|
1264
|
-
const clearError =
|
|
1265
|
+
const clearError = React.useCallback(() => {
|
|
1265
1266
|
setState((prev) => ({ ...prev, error: null }));
|
|
1266
1267
|
}, []);
|
|
1267
|
-
const isTokenExpired =
|
|
1268
|
+
const isTokenExpired = React.useCallback(() => {
|
|
1268
1269
|
if (!state.tokens?.accessToken) return true;
|
|
1269
1270
|
const expiry = getTokenExpiry(state.tokens.accessToken);
|
|
1270
1271
|
if (!expiry) return true;
|
|
1271
1272
|
return expiry.getTime() <= Date.now();
|
|
1272
1273
|
}, [state.tokens?.accessToken, getTokenExpiry]);
|
|
1273
|
-
const getAccessToken =
|
|
1274
|
+
const getAccessToken = React.useCallback(() => {
|
|
1274
1275
|
return state.tokens?.accessToken || null;
|
|
1275
1276
|
}, [state.tokens?.accessToken]);
|
|
1276
|
-
const healthCheck =
|
|
1277
|
+
const healthCheck = React.useCallback(async () => {
|
|
1277
1278
|
return await authService.healthCheckWithRetry();
|
|
1278
1279
|
}, [authService]);
|
|
1279
|
-
const refreshTokens =
|
|
1280
|
+
const refreshTokens = React.useCallback(async () => {
|
|
1280
1281
|
await authService.refreshSession();
|
|
1281
1282
|
}, [authService]);
|
|
1282
|
-
const getRemainingSessionTime =
|
|
1283
|
+
const getRemainingSessionTime = React.useCallback(() => {
|
|
1283
1284
|
if (!state.tokens?.accessToken) return 0;
|
|
1284
1285
|
const expiry = getTokenExpiry(state.tokens.accessToken);
|
|
1285
1286
|
if (!expiry) return 0;
|
|
1286
1287
|
return Math.max(expiry.getTime() - Date.now(), 0);
|
|
1287
1288
|
}, [state.tokens?.accessToken, getTokenExpiry]);
|
|
1288
|
-
const extendSession =
|
|
1289
|
+
const extendSession = React.useCallback(async () => {
|
|
1289
1290
|
await refreshSession();
|
|
1290
1291
|
}, [refreshSession]);
|
|
1291
|
-
const value =
|
|
1292
|
+
const value = React.useMemo(() => ({
|
|
1292
1293
|
...state,
|
|
1293
1294
|
login,
|
|
1294
1295
|
register,
|
|
@@ -1336,12 +1337,218 @@ function AuthProvider({
|
|
|
1336
1337
|
return /* @__PURE__ */ jsxRuntime.jsx(AuthContext.Provider, { value, children });
|
|
1337
1338
|
}
|
|
1338
1339
|
function useAuthContext() {
|
|
1339
|
-
const context =
|
|
1340
|
+
const context = React.useContext(AuthContext);
|
|
1340
1341
|
if (!context) {
|
|
1341
1342
|
throw new Error("useAuthContext must be used within AuthProvider");
|
|
1342
1343
|
}
|
|
1343
1344
|
return context;
|
|
1344
1345
|
}
|
|
1346
|
+
function withAuth(Component) {
|
|
1347
|
+
return function WithAuthComponent(props) {
|
|
1348
|
+
const auth = useAuthContext();
|
|
1349
|
+
return React__default.default.createElement(Component, { ...props, auth });
|
|
1350
|
+
};
|
|
1351
|
+
}
|
|
1352
|
+
function RoleBased({ children, roles, fallback = null }) {
|
|
1353
|
+
const { hasRole, isAuthenticated } = useAuthContext();
|
|
1354
|
+
if (isAuthenticated && hasRole(roles)) {
|
|
1355
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
|
|
1356
|
+
}
|
|
1357
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: fallback });
|
|
1358
|
+
}
|
|
1359
|
+
function MFARequired({ children, redirectTo = "/mfa/setup" }) {
|
|
1360
|
+
const { user, isAuthenticated, isLoading } = useAuthContext();
|
|
1361
|
+
if (isLoading) {
|
|
1362
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { children: "Loading..." });
|
|
1363
|
+
}
|
|
1364
|
+
if (!isAuthenticated) {
|
|
1365
|
+
return null;
|
|
1366
|
+
}
|
|
1367
|
+
if (!user?.mfaEnabled) {
|
|
1368
|
+
if (typeof window !== "undefined") {
|
|
1369
|
+
window.location.href = redirectTo;
|
|
1370
|
+
}
|
|
1371
|
+
return null;
|
|
1372
|
+
}
|
|
1373
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
|
|
1374
|
+
}
|
|
1375
|
+
function AuthStatus() {
|
|
1376
|
+
const { user, isAuthenticated, isLoading, getRemainingSessionTime } = useAuthContext();
|
|
1377
|
+
if (isLoading) return /* @__PURE__ */ jsxRuntime.jsx("div", { children: "Checking authentication..." });
|
|
1378
|
+
if (!isAuthenticated) return /* @__PURE__ */ jsxRuntime.jsx("div", { children: "Not authenticated" });
|
|
1379
|
+
const remainingTime = getRemainingSessionTime();
|
|
1380
|
+
const remainingMinutes = Math.floor(remainingTime / 6e4);
|
|
1381
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm", children: [
|
|
1382
|
+
"Logged in as: ",
|
|
1383
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: user?.name }),
|
|
1384
|
+
" (",
|
|
1385
|
+
user?.email,
|
|
1386
|
+
")",
|
|
1387
|
+
user?.role && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-2 text-blue-600", children: [
|
|
1388
|
+
"Role: ",
|
|
1389
|
+
user.role
|
|
1390
|
+
] }),
|
|
1391
|
+
user?.mfaEnabled && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 text-green-600", children: "\u2713 MFA" }),
|
|
1392
|
+
remainingMinutes > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-2 text-gray-500", children: [
|
|
1393
|
+
"Session: ",
|
|
1394
|
+
remainingMinutes,
|
|
1395
|
+
"min"
|
|
1396
|
+
] })
|
|
1397
|
+
] });
|
|
1398
|
+
}
|
|
1399
|
+
function SessionTimer() {
|
|
1400
|
+
const { getRemainingSessionTime, extendSession, logout } = useAuthContext();
|
|
1401
|
+
const [timeLeft, setTimeLeft] = React.useState(getRemainingSessionTime());
|
|
1402
|
+
React.useEffect(() => {
|
|
1403
|
+
const interval = setInterval(() => {
|
|
1404
|
+
const remaining = getRemainingSessionTime();
|
|
1405
|
+
setTimeLeft(remaining);
|
|
1406
|
+
if (remaining <= 5 * 60 * 1e3 && remaining > 0) {
|
|
1407
|
+
const shouldExtend = window.confirm(
|
|
1408
|
+
`Your session will expire in ${Math.floor(remaining / 6e4)} minutes. Would you like to extend it?`
|
|
1409
|
+
);
|
|
1410
|
+
if (shouldExtend) {
|
|
1411
|
+
extendSession();
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
if (remaining <= 0) {
|
|
1415
|
+
logout();
|
|
1416
|
+
}
|
|
1417
|
+
}, 1e3);
|
|
1418
|
+
return () => clearInterval(interval);
|
|
1419
|
+
}, [getRemainingSessionTime, extendSession, logout]);
|
|
1420
|
+
if (timeLeft <= 0) return null;
|
|
1421
|
+
const minutes = Math.floor(timeLeft / 6e4);
|
|
1422
|
+
const seconds = Math.floor(timeLeft % 6e4 / 1e3);
|
|
1423
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed bottom-4 left-4 bg-gray-900 text-white px-3 py-1 rounded text-xs font-mono", children: [
|
|
1424
|
+
"Session: ",
|
|
1425
|
+
minutes,
|
|
1426
|
+
":",
|
|
1427
|
+
seconds.toString().padStart(2, "0")
|
|
1428
|
+
] });
|
|
1429
|
+
}
|
|
1430
|
+
function AuthDebug() {
|
|
1431
|
+
const auth = useAuthContext();
|
|
1432
|
+
if (process.env.NODE_ENV !== "development") {
|
|
1433
|
+
return null;
|
|
1434
|
+
}
|
|
1435
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed bottom-4 right-4 bg-black text-white p-4 rounded-lg text-xs font-mono z-50 max-w-md overflow-auto shadow-xl", children: /* @__PURE__ */ jsxRuntime.jsxs("details", { children: [
|
|
1436
|
+
/* @__PURE__ */ jsxRuntime.jsx("summary", { className: "cursor-pointer font-bold hover:text-gray-300", children: "\u{1F510} Auth Debug Info" }),
|
|
1437
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 space-y-1", children: [
|
|
1438
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1439
|
+
"\u2705 Authenticated: ",
|
|
1440
|
+
auth.isAuthenticated ? "Yes" : "No"
|
|
1441
|
+
] }),
|
|
1442
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1443
|
+
"\u23F3 Loading: ",
|
|
1444
|
+
auth.isLoading ? "Yes" : "No"
|
|
1445
|
+
] }),
|
|
1446
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1447
|
+
"\u{1F464} User: ",
|
|
1448
|
+
auth.user?.email || "None"
|
|
1449
|
+
] }),
|
|
1450
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1451
|
+
"\u{1F4DB} Name: ",
|
|
1452
|
+
auth.user?.name || "None"
|
|
1453
|
+
] }),
|
|
1454
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1455
|
+
"\u{1F3AD} Role: ",
|
|
1456
|
+
auth.user?.role || "None"
|
|
1457
|
+
] }),
|
|
1458
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1459
|
+
"\u{1F510} MFA: ",
|
|
1460
|
+
auth.user?.mfaEnabled ? "Enabled" : "Disabled"
|
|
1461
|
+
] }),
|
|
1462
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1463
|
+
"\u23F0 Token Expired: ",
|
|
1464
|
+
auth.isTokenExpired() ? "Yes" : "No"
|
|
1465
|
+
] }),
|
|
1466
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1467
|
+
"\u{1F3AB} Has Token: ",
|
|
1468
|
+
auth.getAccessToken() ? "Yes" : "No"
|
|
1469
|
+
] }),
|
|
1470
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1471
|
+
"\u23F1\uFE0F Session Time: ",
|
|
1472
|
+
Math.floor(auth.getRemainingSessionTime() / 1e3),
|
|
1473
|
+
"s"
|
|
1474
|
+
] }),
|
|
1475
|
+
auth.error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500", children: [
|
|
1476
|
+
"\u274C Error: ",
|
|
1477
|
+
auth.error
|
|
1478
|
+
] })
|
|
1479
|
+
] })
|
|
1480
|
+
] }) });
|
|
1481
|
+
}
|
|
1482
|
+
function SessionMonitor() {
|
|
1483
|
+
const { isAuthenticated, refreshSession } = useAuthContext();
|
|
1484
|
+
React.useEffect(() => {
|
|
1485
|
+
if (!isAuthenticated) return;
|
|
1486
|
+
const interval = setInterval(async () => {
|
|
1487
|
+
try {
|
|
1488
|
+
await refreshSession();
|
|
1489
|
+
} catch (error) {
|
|
1490
|
+
console.error("Session health check failed:", error);
|
|
1491
|
+
}
|
|
1492
|
+
}, 5 * 60 * 1e3);
|
|
1493
|
+
return () => clearInterval(interval);
|
|
1494
|
+
}, [isAuthenticated, refreshSession]);
|
|
1495
|
+
return null;
|
|
1496
|
+
}
|
|
1497
|
+
function SessionExpiryWarning({
|
|
1498
|
+
warningMinutes = [5, 2, 1],
|
|
1499
|
+
onExtend
|
|
1500
|
+
}) {
|
|
1501
|
+
const { getRemainingSessionTime, extendSession } = useAuthContext();
|
|
1502
|
+
const [showWarning, setShowWarning] = React.useState(false);
|
|
1503
|
+
const [timeLeft, setTimeLeft] = React.useState(0);
|
|
1504
|
+
React.useEffect(() => {
|
|
1505
|
+
const interval = setInterval(() => {
|
|
1506
|
+
const remaining = getRemainingSessionTime();
|
|
1507
|
+
setTimeLeft(remaining);
|
|
1508
|
+
const shouldShow = warningMinutes.some(
|
|
1509
|
+
(minutes2) => Math.abs(remaining - minutes2 * 60 * 1e3) < 1e3
|
|
1510
|
+
);
|
|
1511
|
+
setShowWarning(shouldShow && remaining > 0);
|
|
1512
|
+
}, 1e3);
|
|
1513
|
+
return () => clearInterval(interval);
|
|
1514
|
+
}, [getRemainingSessionTime, warningMinutes]);
|
|
1515
|
+
const handleExtend = async () => {
|
|
1516
|
+
await extendSession();
|
|
1517
|
+
setShowWarning(false);
|
|
1518
|
+
onExtend?.();
|
|
1519
|
+
};
|
|
1520
|
+
if (!showWarning) return null;
|
|
1521
|
+
const minutes = Math.floor(timeLeft / 6e4);
|
|
1522
|
+
const seconds = Math.floor(timeLeft % 6e4 / 1e3);
|
|
1523
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg p-6 max-w-md mx-4", children: [
|
|
1524
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold mb-2", children: "Session Expiring Soon" }),
|
|
1525
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-gray-600 mb-4", children: [
|
|
1526
|
+
"Your session will expire in ",
|
|
1527
|
+
minutes,
|
|
1528
|
+
":",
|
|
1529
|
+
seconds.toString().padStart(2, "0"),
|
|
1530
|
+
" minutes. Would you like to extend it?"
|
|
1531
|
+
] }),
|
|
1532
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
|
|
1533
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1534
|
+
"button",
|
|
1535
|
+
{
|
|
1536
|
+
onClick: handleExtend,
|
|
1537
|
+
className: "bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600",
|
|
1538
|
+
children: "Extend Session"
|
|
1539
|
+
}
|
|
1540
|
+
),
|
|
1541
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1542
|
+
"button",
|
|
1543
|
+
{
|
|
1544
|
+
onClick: () => setShowWarning(false),
|
|
1545
|
+
className: "bg-gray-300 text-gray-700 px-4 py-2 rounded hover:bg-gray-400",
|
|
1546
|
+
children: "Dismiss"
|
|
1547
|
+
}
|
|
1548
|
+
)
|
|
1549
|
+
] })
|
|
1550
|
+
] }) });
|
|
1551
|
+
}
|
|
1345
1552
|
function ProtectedRoute({
|
|
1346
1553
|
children,
|
|
1347
1554
|
requiredRole,
|
|
@@ -1389,11 +1596,11 @@ function generateRandomString(length) {
|
|
|
1389
1596
|
return result;
|
|
1390
1597
|
}
|
|
1391
1598
|
function LoginForm({ onSubmit, isLoading = false, error, className }) {
|
|
1392
|
-
const [email, setEmail] =
|
|
1393
|
-
const [password, setPassword] =
|
|
1394
|
-
const [showPassword, setShowPassword] =
|
|
1395
|
-
const [rememberMe, setRememberMe] =
|
|
1396
|
-
const [localError, setLocalError] =
|
|
1599
|
+
const [email, setEmail] = React.useState("");
|
|
1600
|
+
const [password, setPassword] = React.useState("");
|
|
1601
|
+
const [showPassword, setShowPassword] = React.useState(false);
|
|
1602
|
+
const [rememberMe, setRememberMe] = React.useState(false);
|
|
1603
|
+
const [localError, setLocalError] = React.useState("");
|
|
1397
1604
|
const handleSubmit = async (e) => {
|
|
1398
1605
|
e.preventDefault();
|
|
1399
1606
|
setLocalError("");
|
|
@@ -1494,13 +1701,13 @@ function LoginForm({ onSubmit, isLoading = false, error, className }) {
|
|
|
1494
1701
|
] }) }) });
|
|
1495
1702
|
}
|
|
1496
1703
|
function MFASetup({ userId, email, onComplete, onCancel }) {
|
|
1497
|
-
const [step, setStep] =
|
|
1498
|
-
const [qrCode, setQrCode] =
|
|
1499
|
-
const [backupCodes, setBackupCodes] =
|
|
1500
|
-
const [verificationCode, setVerificationCode] =
|
|
1501
|
-
const [error, setError] =
|
|
1502
|
-
const [copied, setCopied] =
|
|
1503
|
-
const [isLoading, setIsLoading] =
|
|
1704
|
+
const [step, setStep] = React.useState("setup");
|
|
1705
|
+
const [qrCode, setQrCode] = React.useState("");
|
|
1706
|
+
const [backupCodes, setBackupCodes] = React.useState([]);
|
|
1707
|
+
const [verificationCode, setVerificationCode] = React.useState("");
|
|
1708
|
+
const [error, setError] = React.useState("");
|
|
1709
|
+
const [copied, setCopied] = React.useState(false);
|
|
1710
|
+
const [isLoading, setIsLoading] = React.useState(false);
|
|
1504
1711
|
const handleSetup = async () => {
|
|
1505
1712
|
setIsLoading(true);
|
|
1506
1713
|
try {
|
|
@@ -1641,10 +1848,10 @@ function MFASetup({ userId, email, onComplete, onCancel }) {
|
|
|
1641
1848
|
] });
|
|
1642
1849
|
}
|
|
1643
1850
|
function MFAVerification({ onSubmit, onBack }) {
|
|
1644
|
-
const [code, setCode] =
|
|
1645
|
-
const [trustDevice, setTrustDevice] =
|
|
1646
|
-
const [error, setError] =
|
|
1647
|
-
const [isLoading, setIsLoading] =
|
|
1851
|
+
const [code, setCode] = React.useState("");
|
|
1852
|
+
const [trustDevice, setTrustDevice] = React.useState(false);
|
|
1853
|
+
const [error, setError] = React.useState("");
|
|
1854
|
+
const [isLoading, setIsLoading] = React.useState(false);
|
|
1648
1855
|
const handleSubmit = async (e) => {
|
|
1649
1856
|
e.preventDefault();
|
|
1650
1857
|
if (code.length !== 6) {
|
|
@@ -1721,9 +1928,9 @@ function MFAVerification({ onSubmit, onBack }) {
|
|
|
1721
1928
|
}
|
|
1722
1929
|
function SessionWarning({ warningMinutes = 2 }) {
|
|
1723
1930
|
const { refreshSession } = useAuth();
|
|
1724
|
-
const [showWarning, setShowWarning] =
|
|
1725
|
-
const [timeLeft, setTimeLeft] =
|
|
1726
|
-
|
|
1931
|
+
const [showWarning, setShowWarning] = React.useState(false);
|
|
1932
|
+
const [timeLeft, setTimeLeft] = React.useState(0);
|
|
1933
|
+
React.useEffect(() => {
|
|
1727
1934
|
const checkSession = () => {
|
|
1728
1935
|
const tokens = localStorage.getItem("auth_tokens_encrypted");
|
|
1729
1936
|
if (!tokens) return;
|
|
@@ -1903,17 +2110,24 @@ exports.API_ENDPOINTS = API_ENDPOINTS;
|
|
|
1903
2110
|
exports.AUTH_CONFIG = AUTH_CONFIG;
|
|
1904
2111
|
exports.AuditAction = AuditAction;
|
|
1905
2112
|
exports.AuditLogger = AuditLogger;
|
|
2113
|
+
exports.AuthDebug = AuthDebug;
|
|
1906
2114
|
exports.AuthProvider = AuthProvider;
|
|
1907
2115
|
exports.AuthService = AuthService;
|
|
2116
|
+
exports.AuthStatus = AuthStatus;
|
|
1908
2117
|
exports.DeviceFingerprint = DeviceFingerprint;
|
|
1909
2118
|
exports.LoginForm = LoginForm;
|
|
2119
|
+
exports.MFARequired = MFARequired;
|
|
1910
2120
|
exports.MFAService = MFAService;
|
|
1911
2121
|
exports.MFASetup = MFASetup;
|
|
1912
2122
|
exports.MFAVerification = MFAVerification;
|
|
1913
2123
|
exports.ProtectedRoute = ProtectedRoute;
|
|
1914
2124
|
exports.RateLimiter = RateLimiter;
|
|
2125
|
+
exports.RoleBased = RoleBased;
|
|
1915
2126
|
exports.STORAGE_KEYS = STORAGE_KEYS;
|
|
2127
|
+
exports.SessionExpiryWarning = SessionExpiryWarning;
|
|
1916
2128
|
exports.SessionManager = SessionManager;
|
|
2129
|
+
exports.SessionMonitor = SessionMonitor;
|
|
2130
|
+
exports.SessionTimer = SessionTimer;
|
|
1917
2131
|
exports.SessionWarning = SessionWarning;
|
|
1918
2132
|
exports.TokenBlacklist = TokenBlacklist;
|
|
1919
2133
|
exports.TokenManager = TokenManager;
|
|
@@ -1931,5 +2145,6 @@ exports.useAuth = useAuth;
|
|
|
1931
2145
|
exports.useAuthContext = useAuthContext;
|
|
1932
2146
|
exports.useProtectedRoute = useProtectedRoute;
|
|
1933
2147
|
exports.validateEnvironment = validateEnvironment;
|
|
2148
|
+
exports.withAuth = withAuth;
|
|
1934
2149
|
//# sourceMappingURL=index.js.map
|
|
1935
2150
|
//# sourceMappingURL=index.js.map
|