another step

This commit is contained in:
hamid
2026-06-23 23:36:19 +03:30
parent 3fd147cf80
commit be07c703ec
27 changed files with 3682 additions and 194 deletions
+38
View File
@@ -0,0 +1,38 @@
/**
* JWT helpers shared by the edge middleware and server components.
*
* Pure functions with no `next/headers` dependency, so they are safe to import
* from `middleware.ts` (edge runtime) and from RSCs alike. They only inspect the
* token's `exp` claim — a cheap liveness check for routing/UX, NOT a security
* boundary. The signature is never verified here; the API server is the only
* authority that actually trusts the token.
*/
export interface JwtPayload {
exp?: number;
sub?: string;
[claim: string]: unknown;
}
// JWTs use base64url (no padding, `-`/`_` instead of `+`/`/`); atob expects
// standard base64, so normalise before decoding.
function base64UrlDecode(segment: string): string {
const base64 = segment.replace(/-/g, '+').replace(/_/g, '/');
const padded = base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), '=');
return atob(padded);
}
export function decodeJwtPayload(token: string | undefined): JwtPayload | null {
if (!token) return null;
const segment = token.split('.')[1];
if (!segment) return null;
try {
return JSON.parse(base64UrlDecode(segment)) as JwtPayload;
} catch {
return null;
}
}
export function isTokenAlive(token: string | undefined): boolean {
const payload = decodeJwtPayload(token);
return typeof payload?.exp === 'number' && payload.exp * 1000 > Date.now();
}