mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-04 04:23:13 +00:00
Ignore stored AuthUser.orgScope so a scoped token cannot open the unscoped account picker via localStorage.
44 lines
1.3 KiB
TypeScript
44 lines
1.3 KiB
TypeScript
import type { AuthUser } from "@/domain/auth/types/auth-user";
|
|
|
|
const ORG_SCOPE_ALL = "all";
|
|
|
|
function readJwtClaims(token: string): Record<string, unknown> | null {
|
|
const parts = token.split(".");
|
|
if (parts.length < 2) {
|
|
return null;
|
|
}
|
|
try {
|
|
const normalized = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "=");
|
|
const parsed: unknown = JSON.parse(globalThis.atob(padded));
|
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
return null;
|
|
}
|
|
return parsed as Record<string, unknown>;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function readStringClaim(source: Record<string, unknown> | null, keys: string[]): string {
|
|
if (!source) {
|
|
return "";
|
|
}
|
|
for (const key of keys) {
|
|
const value = source[key];
|
|
if (typeof value === "string" && value.trim()) {
|
|
return value.trim();
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
/** Org-wide only when the JWT claim is explicitly `all`. Fail-closed otherwise. */
|
|
export function isOrgWideScope(user: AuthUser | null | undefined): boolean {
|
|
if (!user || typeof user.token !== "string") {
|
|
return false;
|
|
}
|
|
const claims = readJwtClaims(user.token);
|
|
const scope = readStringClaim(claims, ["org_scope", "orgScope", "OrgScope"]);
|
|
return scope.toLowerCase() === ORG_SCOPE_ALL;
|
|
}
|