@chemmangat/msal-next 5.0.0 → 5.1.0
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/CHANGELOG.md +86 -0
- package/README.md +82 -1
- package/dist/index.d.mts +183 -76
- package/dist/index.d.ts +183 -76
- package/dist/index.js +258 -24
- package/dist/index.mjs +241 -9
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -54,6 +54,8 @@ __export(client_exports, {
|
|
|
54
54
|
useMsalAuth: () => useMsalAuth,
|
|
55
55
|
useMultiAccount: () => useMultiAccount,
|
|
56
56
|
useRoles: () => useRoles,
|
|
57
|
+
useTenant: () => useTenant,
|
|
58
|
+
useTenantConfig: () => useTenantConfig,
|
|
57
59
|
useTokenRefresh: () => useTokenRefresh,
|
|
58
60
|
useUserProfile: () => useUserProfile,
|
|
59
61
|
validateConfig: () => validateConfig,
|
|
@@ -131,19 +133,44 @@ function createMsalConfig(config) {
|
|
|
131
133
|
navigateToLoginRequestUrl = false,
|
|
132
134
|
enableLogging = false,
|
|
133
135
|
loggerCallback,
|
|
134
|
-
allowedRedirectUris
|
|
136
|
+
allowedRedirectUris,
|
|
137
|
+
multiTenant
|
|
135
138
|
} = config;
|
|
136
139
|
if (!clientId) {
|
|
137
140
|
throw new Error("@chemmangat/msal-next: clientId is required");
|
|
138
141
|
}
|
|
139
|
-
const
|
|
142
|
+
const resolveAuthorityType = () => {
|
|
143
|
+
if (multiTenant?.type) {
|
|
144
|
+
switch (multiTenant.type) {
|
|
145
|
+
case "single":
|
|
146
|
+
if (!tenantId) {
|
|
147
|
+
throw new Error(
|
|
148
|
+
'@chemmangat/msal-next: tenantId is required when multiTenant.type is "single"'
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
return tenantId;
|
|
152
|
+
case "multi":
|
|
153
|
+
case "common":
|
|
154
|
+
return "common";
|
|
155
|
+
case "organizations":
|
|
156
|
+
return "organizations";
|
|
157
|
+
case "consumers":
|
|
158
|
+
return "consumers";
|
|
159
|
+
}
|
|
160
|
+
}
|
|
140
161
|
if (authorityType === "tenant") {
|
|
141
162
|
if (!tenantId) {
|
|
142
|
-
throw new Error(
|
|
163
|
+
throw new Error(
|
|
164
|
+
'@chemmangat/msal-next: tenantId is required when authorityType is "tenant"'
|
|
165
|
+
);
|
|
143
166
|
}
|
|
144
|
-
return
|
|
167
|
+
return tenantId;
|
|
145
168
|
}
|
|
146
|
-
return
|
|
169
|
+
return authorityType;
|
|
170
|
+
};
|
|
171
|
+
const getAuthority = () => {
|
|
172
|
+
const resolved = resolveAuthorityType();
|
|
173
|
+
return `https://login.microsoftonline.com/${resolved}`;
|
|
147
174
|
};
|
|
148
175
|
const defaultRedirectUri = typeof window !== "undefined" ? window.location.origin : "http://localhost:3000";
|
|
149
176
|
const finalRedirectUri = redirectUri || defaultRedirectUri;
|
|
@@ -764,6 +791,31 @@ function useMsalAuth(defaultScopes = ["User.Read"]) {
|
|
|
764
791
|
instance.setActiveAccount(null);
|
|
765
792
|
await instance.clearCache();
|
|
766
793
|
}, [instance]);
|
|
794
|
+
const acquireTokenForTenant = (0, import_react.useCallback)(
|
|
795
|
+
async (tenantId, scopes) => {
|
|
796
|
+
if (!account) {
|
|
797
|
+
throw new Error("[MSAL] No active account. Please login first.");
|
|
798
|
+
}
|
|
799
|
+
try {
|
|
800
|
+
const response = await instance.acquireTokenSilent({
|
|
801
|
+
scopes,
|
|
802
|
+
account,
|
|
803
|
+
authority: `https://login.microsoftonline.com/${tenantId}`,
|
|
804
|
+
forceRefresh: false
|
|
805
|
+
});
|
|
806
|
+
return response.accessToken;
|
|
807
|
+
} catch (error) {
|
|
808
|
+
const msalError = wrapMsalError(error);
|
|
809
|
+
if (process.env.NODE_ENV === "development") {
|
|
810
|
+
console.error(msalError.toConsoleString());
|
|
811
|
+
} else {
|
|
812
|
+
console.error("[MSAL] Cross-tenant token acquisition failed:", msalError.message);
|
|
813
|
+
}
|
|
814
|
+
throw msalError;
|
|
815
|
+
}
|
|
816
|
+
},
|
|
817
|
+
[instance, account]
|
|
818
|
+
);
|
|
767
819
|
return {
|
|
768
820
|
account,
|
|
769
821
|
accounts,
|
|
@@ -774,7 +826,8 @@ function useMsalAuth(defaultScopes = ["User.Read"]) {
|
|
|
774
826
|
acquireToken,
|
|
775
827
|
acquireTokenSilent,
|
|
776
828
|
acquireTokenRedirect,
|
|
777
|
-
clearSession
|
|
829
|
+
clearSession,
|
|
830
|
+
acquireTokenForTenant
|
|
778
831
|
};
|
|
779
832
|
}
|
|
780
833
|
|
|
@@ -863,6 +916,86 @@ function TokenRefreshManager({
|
|
|
863
916
|
return null;
|
|
864
917
|
}
|
|
865
918
|
|
|
919
|
+
// src/utils/tenantValidator.ts
|
|
920
|
+
function getTenantDomain(account) {
|
|
921
|
+
const upn = account.username || account.idTokenClaims?.preferred_username || account.idTokenClaims?.upn || "";
|
|
922
|
+
return upn.includes("@") ? upn.split("@")[1].toLowerCase() : null;
|
|
923
|
+
}
|
|
924
|
+
function getTenantId(account) {
|
|
925
|
+
return account.tenantId || account.idTokenClaims?.tid || null;
|
|
926
|
+
}
|
|
927
|
+
function matchesTenant(value, tenantId, tenantDomain) {
|
|
928
|
+
const v = value.toLowerCase();
|
|
929
|
+
if (tenantId && v === tenantId.toLowerCase()) return true;
|
|
930
|
+
if (tenantDomain && v === tenantDomain.toLowerCase()) return true;
|
|
931
|
+
return false;
|
|
932
|
+
}
|
|
933
|
+
function isGuestAccount(account) {
|
|
934
|
+
const claims = account.idTokenClaims ?? {};
|
|
935
|
+
const resourceTenantId = account.tenantId || claims["tid"] || null;
|
|
936
|
+
const issuer = claims["iss"] || null;
|
|
937
|
+
if (!issuer || !resourceTenantId) return false;
|
|
938
|
+
const match = issuer.match(
|
|
939
|
+
/https:\/\/login\.microsoftonline\.com\/([^/]+)(?:\/|$)/i
|
|
940
|
+
);
|
|
941
|
+
if (!match) return false;
|
|
942
|
+
const homeTenantId = match[1];
|
|
943
|
+
return homeTenantId.toLowerCase() !== resourceTenantId.toLowerCase();
|
|
944
|
+
}
|
|
945
|
+
function validateTenantAccess(account, config) {
|
|
946
|
+
const tenantId = getTenantId(account);
|
|
947
|
+
const tenantDomain = getTenantDomain(account);
|
|
948
|
+
const claims = account.idTokenClaims ?? {};
|
|
949
|
+
if (config.blockList && config.blockList.length > 0) {
|
|
950
|
+
const blocked = config.blockList.some(
|
|
951
|
+
(entry) => matchesTenant(entry, tenantId, tenantDomain)
|
|
952
|
+
);
|
|
953
|
+
if (blocked) {
|
|
954
|
+
return {
|
|
955
|
+
allowed: false,
|
|
956
|
+
reason: `Tenant "${tenantDomain || tenantId}" is blocked from accessing this application.`
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
if (config.allowList && config.allowList.length > 0) {
|
|
961
|
+
const allowed = config.allowList.some(
|
|
962
|
+
(entry) => matchesTenant(entry, tenantId, tenantDomain)
|
|
963
|
+
);
|
|
964
|
+
if (!allowed) {
|
|
965
|
+
return {
|
|
966
|
+
allowed: false,
|
|
967
|
+
reason: `Tenant "${tenantDomain || tenantId}" is not in the allowed list for this application.`
|
|
968
|
+
};
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
if (config.requireType) {
|
|
972
|
+
const isGuest = isGuestAccount(account);
|
|
973
|
+
if (config.requireType === "Member" && isGuest) {
|
|
974
|
+
return {
|
|
975
|
+
allowed: false,
|
|
976
|
+
reason: "Only member accounts are allowed. Guest (B2B) accounts are not permitted."
|
|
977
|
+
};
|
|
978
|
+
}
|
|
979
|
+
if (config.requireType === "Guest" && !isGuest) {
|
|
980
|
+
return {
|
|
981
|
+
allowed: false,
|
|
982
|
+
reason: "Only guest (B2B) accounts are allowed."
|
|
983
|
+
};
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
if (config.requireMFA) {
|
|
987
|
+
const amr = claims["amr"] || [];
|
|
988
|
+
const hasMfa = amr.includes("mfa") || amr.includes("ngcmfa") || amr.includes("hwk") || amr.includes("swk");
|
|
989
|
+
if (!hasMfa) {
|
|
990
|
+
return {
|
|
991
|
+
allowed: false,
|
|
992
|
+
reason: "Multi-factor authentication (MFA) is required to access this application."
|
|
993
|
+
};
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
return { allowed: true };
|
|
997
|
+
}
|
|
998
|
+
|
|
866
999
|
// src/components/MsalAuthProvider.tsx
|
|
867
1000
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
868
1001
|
var globalMsalInstance = null;
|
|
@@ -875,6 +1008,7 @@ function MsalAuthProvider({
|
|
|
875
1008
|
onInitialized,
|
|
876
1009
|
autoRefreshToken = false,
|
|
877
1010
|
refreshBeforeExpiry = 300,
|
|
1011
|
+
onTenantDenied,
|
|
878
1012
|
...config
|
|
879
1013
|
}) {
|
|
880
1014
|
const [msalInstance, setMsalInstance] = (0, import_react3.useState)(null);
|
|
@@ -904,6 +1038,22 @@ function MsalAuthProvider({
|
|
|
904
1038
|
}
|
|
905
1039
|
if (response.account) {
|
|
906
1040
|
instance.setActiveAccount(response.account);
|
|
1041
|
+
if (config.multiTenant) {
|
|
1042
|
+
const validation = validateTenantAccess(response.account, config.multiTenant);
|
|
1043
|
+
if (!validation.allowed) {
|
|
1044
|
+
try {
|
|
1045
|
+
await instance.logoutRedirect({ account: response.account });
|
|
1046
|
+
} catch {
|
|
1047
|
+
}
|
|
1048
|
+
const reason = validation.reason || "Tenant access denied.";
|
|
1049
|
+
if (onTenantDenied) {
|
|
1050
|
+
onTenantDenied(reason);
|
|
1051
|
+
} else {
|
|
1052
|
+
console.error("[MSAL] Tenant access denied:", reason);
|
|
1053
|
+
}
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
907
1057
|
}
|
|
908
1058
|
if (window.location.hash) {
|
|
909
1059
|
window.history.replaceState(null, "", window.location.pathname + window.location.search);
|
|
@@ -1003,8 +1153,12 @@ function MsalAuthProvider({
|
|
|
1003
1153
|
var import_react4 = require("react");
|
|
1004
1154
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1005
1155
|
var ProtectionConfigContext = (0, import_react4.createContext)(void 0);
|
|
1006
|
-
|
|
1007
|
-
|
|
1156
|
+
var TenantConfigContext = (0, import_react4.createContext)(void 0);
|
|
1157
|
+
function useTenantConfig() {
|
|
1158
|
+
return (0, import_react4.useContext)(TenantConfigContext);
|
|
1159
|
+
}
|
|
1160
|
+
function MSALProvider({ children, protection, onTenantDenied, ...props }) {
|
|
1161
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ProtectionConfigContext.Provider, { value: protection, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(TenantConfigContext.Provider, { value: props.multiTenant, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MsalAuthProvider, { ...props, onTenantDenied, children }) }) });
|
|
1008
1162
|
}
|
|
1009
1163
|
|
|
1010
1164
|
// src/components/MicrosoftSignInButton.tsx
|
|
@@ -2419,8 +2573,48 @@ function AccountList({
|
|
|
2419
2573
|
}) });
|
|
2420
2574
|
}
|
|
2421
2575
|
|
|
2422
|
-
// src/hooks/
|
|
2576
|
+
// src/hooks/useTenant.ts
|
|
2423
2577
|
var import_react13 = require("react");
|
|
2578
|
+
function useTenant() {
|
|
2579
|
+
const { account, isAuthenticated } = useMsalAuth();
|
|
2580
|
+
const tenantInfo = (0, import_react13.useMemo)(() => {
|
|
2581
|
+
if (!account) {
|
|
2582
|
+
return {
|
|
2583
|
+
tenantId: null,
|
|
2584
|
+
tenantDomain: null,
|
|
2585
|
+
isGuestUser: false,
|
|
2586
|
+
homeTenantId: null,
|
|
2587
|
+
resourceTenantId: null,
|
|
2588
|
+
claims: null
|
|
2589
|
+
};
|
|
2590
|
+
}
|
|
2591
|
+
const claims = account.idTokenClaims ?? {};
|
|
2592
|
+
const resourceTenantId = account.tenantId || claims["tid"] || null;
|
|
2593
|
+
const issuer = claims["iss"] || null;
|
|
2594
|
+
let homeTenantId = null;
|
|
2595
|
+
if (issuer) {
|
|
2596
|
+
const match = issuer.match(
|
|
2597
|
+
/https:\/\/login\.microsoftonline\.com\/([^/]+)(?:\/|$)/i
|
|
2598
|
+
);
|
|
2599
|
+
if (match) homeTenantId = match[1];
|
|
2600
|
+
}
|
|
2601
|
+
const isGuestUser = !!homeTenantId && !!resourceTenantId && homeTenantId.toLowerCase() !== resourceTenantId.toLowerCase();
|
|
2602
|
+
const upn = account.username || claims["preferred_username"] || claims["upn"] || "";
|
|
2603
|
+
const tenantDomain = upn.includes("@") ? upn.split("@")[1] : null;
|
|
2604
|
+
return {
|
|
2605
|
+
tenantId: resourceTenantId,
|
|
2606
|
+
tenantDomain,
|
|
2607
|
+
isGuestUser,
|
|
2608
|
+
homeTenantId,
|
|
2609
|
+
resourceTenantId,
|
|
2610
|
+
claims
|
|
2611
|
+
};
|
|
2612
|
+
}, [account]);
|
|
2613
|
+
return { ...tenantInfo, isAuthenticated };
|
|
2614
|
+
}
|
|
2615
|
+
|
|
2616
|
+
// src/hooks/useRoles.ts
|
|
2617
|
+
var import_react14 = require("react");
|
|
2424
2618
|
var rolesCache = /* @__PURE__ */ new Map();
|
|
2425
2619
|
var CACHE_DURATION2 = 5 * 60 * 1e3;
|
|
2426
2620
|
var MAX_CACHE_SIZE2 = 100;
|
|
@@ -2442,11 +2636,11 @@ function enforceCacheLimit2() {
|
|
|
2442
2636
|
function useRoles() {
|
|
2443
2637
|
const { isAuthenticated, account } = useMsalAuth();
|
|
2444
2638
|
const graph = useGraphApi();
|
|
2445
|
-
const [roles, setRoles] = (0,
|
|
2446
|
-
const [groups, setGroups] = (0,
|
|
2447
|
-
const [loading, setLoading] = (0,
|
|
2448
|
-
const [error, setError] = (0,
|
|
2449
|
-
const fetchRolesAndGroups = (0,
|
|
2639
|
+
const [roles, setRoles] = (0, import_react14.useState)([]);
|
|
2640
|
+
const [groups, setGroups] = (0, import_react14.useState)([]);
|
|
2641
|
+
const [loading, setLoading] = (0, import_react14.useState)(false);
|
|
2642
|
+
const [error, setError] = (0, import_react14.useState)(null);
|
|
2643
|
+
const fetchRolesAndGroups = (0, import_react14.useCallback)(async () => {
|
|
2450
2644
|
if (!isAuthenticated || !account) {
|
|
2451
2645
|
setRoles([]);
|
|
2452
2646
|
setGroups([]);
|
|
@@ -2489,31 +2683,31 @@ function useRoles() {
|
|
|
2489
2683
|
setLoading(false);
|
|
2490
2684
|
}
|
|
2491
2685
|
}, [isAuthenticated, account, graph]);
|
|
2492
|
-
const hasRole = (0,
|
|
2686
|
+
const hasRole = (0, import_react14.useCallback)(
|
|
2493
2687
|
(role) => {
|
|
2494
2688
|
return roles.includes(role);
|
|
2495
2689
|
},
|
|
2496
2690
|
[roles]
|
|
2497
2691
|
);
|
|
2498
|
-
const hasGroup = (0,
|
|
2692
|
+
const hasGroup = (0, import_react14.useCallback)(
|
|
2499
2693
|
(groupId) => {
|
|
2500
2694
|
return groups.includes(groupId);
|
|
2501
2695
|
},
|
|
2502
2696
|
[groups]
|
|
2503
2697
|
);
|
|
2504
|
-
const hasAnyRole = (0,
|
|
2698
|
+
const hasAnyRole = (0, import_react14.useCallback)(
|
|
2505
2699
|
(checkRoles) => {
|
|
2506
2700
|
return checkRoles.some((role) => roles.includes(role));
|
|
2507
2701
|
},
|
|
2508
2702
|
[roles]
|
|
2509
2703
|
);
|
|
2510
|
-
const hasAllRoles = (0,
|
|
2704
|
+
const hasAllRoles = (0, import_react14.useCallback)(
|
|
2511
2705
|
(checkRoles) => {
|
|
2512
2706
|
return checkRoles.every((role) => roles.includes(role));
|
|
2513
2707
|
},
|
|
2514
2708
|
[roles]
|
|
2515
2709
|
);
|
|
2516
|
-
(0,
|
|
2710
|
+
(0, import_react14.useEffect)(() => {
|
|
2517
2711
|
fetchRolesAndGroups();
|
|
2518
2712
|
return () => {
|
|
2519
2713
|
if (account) {
|
|
@@ -2811,7 +3005,7 @@ function createScopedLogger(scope, config) {
|
|
|
2811
3005
|
}
|
|
2812
3006
|
|
|
2813
3007
|
// src/protection/ProtectedPage.tsx
|
|
2814
|
-
var
|
|
3008
|
+
var import_react15 = require("react");
|
|
2815
3009
|
var import_navigation = require("next/navigation");
|
|
2816
3010
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
2817
3011
|
function ProtectedPage({
|
|
@@ -2824,9 +3018,10 @@ function ProtectedPage({
|
|
|
2824
3018
|
}) {
|
|
2825
3019
|
const router = (0, import_navigation.useRouter)();
|
|
2826
3020
|
const { isAuthenticated, account, inProgress } = useMsalAuth();
|
|
2827
|
-
const
|
|
2828
|
-
const [
|
|
2829
|
-
(0,
|
|
3021
|
+
const tenantInfo = useTenant();
|
|
3022
|
+
const [isValidating, setIsValidating] = (0, import_react15.useState)(true);
|
|
3023
|
+
const [isAuthorized, setIsAuthorized] = (0, import_react15.useState)(false);
|
|
3024
|
+
(0, import_react15.useEffect)(() => {
|
|
2830
3025
|
async function checkAuth() {
|
|
2831
3026
|
if (debug) {
|
|
2832
3027
|
console.log("[ProtectedPage] Checking auth...", {
|
|
@@ -2867,6 +3062,17 @@ function ProtectedPage({
|
|
|
2867
3062
|
return;
|
|
2868
3063
|
}
|
|
2869
3064
|
}
|
|
3065
|
+
if (config.tenant && account) {
|
|
3066
|
+
const tenantResult = validateTenantAccess(account, config.tenant);
|
|
3067
|
+
if (!tenantResult.allowed) {
|
|
3068
|
+
if (debug) {
|
|
3069
|
+
console.log("[ProtectedPage] Tenant validation failed:", tenantResult.reason);
|
|
3070
|
+
}
|
|
3071
|
+
setIsAuthorized(false);
|
|
3072
|
+
setIsValidating(false);
|
|
3073
|
+
return;
|
|
3074
|
+
}
|
|
3075
|
+
}
|
|
2870
3076
|
if (config.validate) {
|
|
2871
3077
|
try {
|
|
2872
3078
|
const isValid = await config.validate(account);
|
|
@@ -2892,7 +3098,7 @@ function ProtectedPage({
|
|
|
2892
3098
|
setIsValidating(false);
|
|
2893
3099
|
}
|
|
2894
3100
|
checkAuth();
|
|
2895
|
-
}, [isAuthenticated, account, inProgress, config, router, defaultRedirectTo, debug]);
|
|
3101
|
+
}, [isAuthenticated, account, inProgress, config, router, defaultRedirectTo, debug, tenantInfo]);
|
|
2896
3102
|
if (isValidating || inProgress) {
|
|
2897
3103
|
if (config.loading) {
|
|
2898
3104
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_jsx_runtime12.Fragment, { children: config.loading });
|
|
@@ -2947,6 +3153,8 @@ function createAuthMiddleware(config = {}) {
|
|
|
2947
3153
|
redirectAfterLogin = "/",
|
|
2948
3154
|
sessionCookie = "msal.account",
|
|
2949
3155
|
isAuthenticated: customAuthCheck,
|
|
3156
|
+
tenantConfig,
|
|
3157
|
+
tenantDeniedPath = "/unauthorized",
|
|
2950
3158
|
debug = false
|
|
2951
3159
|
} = config;
|
|
2952
3160
|
return async function authMiddleware(request) {
|
|
@@ -2979,6 +3187,30 @@ function createAuthMiddleware(config = {}) {
|
|
|
2979
3187
|
url.searchParams.set("returnUrl", pathname);
|
|
2980
3188
|
return import_server.NextResponse.redirect(url);
|
|
2981
3189
|
}
|
|
3190
|
+
if (isProtectedRoute && authenticated && tenantConfig) {
|
|
3191
|
+
try {
|
|
3192
|
+
const sessionData = request.cookies.get(sessionCookie);
|
|
3193
|
+
if (sessionData?.value) {
|
|
3194
|
+
const account = safeJsonParse(sessionData.value, isValidAccountData);
|
|
3195
|
+
if (account) {
|
|
3196
|
+
const tenantResult = validateTenantAccess(account, tenantConfig);
|
|
3197
|
+
if (!tenantResult.allowed) {
|
|
3198
|
+
if (debug) {
|
|
3199
|
+
console.log("[AuthMiddleware] Tenant access denied:", tenantResult.reason);
|
|
3200
|
+
}
|
|
3201
|
+
const url = request.nextUrl.clone();
|
|
3202
|
+
url.pathname = tenantDeniedPath;
|
|
3203
|
+
url.searchParams.set("reason", tenantResult.reason || "access_denied");
|
|
3204
|
+
return import_server.NextResponse.redirect(url);
|
|
3205
|
+
}
|
|
3206
|
+
}
|
|
3207
|
+
}
|
|
3208
|
+
} catch (error) {
|
|
3209
|
+
if (debug) {
|
|
3210
|
+
console.warn("[AuthMiddleware] Tenant validation error:", error);
|
|
3211
|
+
}
|
|
3212
|
+
}
|
|
3213
|
+
}
|
|
2982
3214
|
if (isPublicOnlyRoute && authenticated) {
|
|
2983
3215
|
if (debug) {
|
|
2984
3216
|
console.log("[AuthMiddleware] Redirecting to home");
|
|
@@ -3047,6 +3279,8 @@ var import_msal_react4 = require("@azure/msal-react");
|
|
|
3047
3279
|
useMsalAuth,
|
|
3048
3280
|
useMultiAccount,
|
|
3049
3281
|
useRoles,
|
|
3282
|
+
useTenant,
|
|
3283
|
+
useTenantConfig,
|
|
3050
3284
|
useTokenRefresh,
|
|
3051
3285
|
useUserProfile,
|
|
3052
3286
|
validateConfig,
|