41 lines
1.0 KiB
TypeScript
41 lines
1.0 KiB
TypeScript
import {
|
|
hexToBytes,
|
|
parseFreshAccessToken,
|
|
resolveAccessCodeSessionTtlSeconds,
|
|
type AccessTokenValidationOptions,
|
|
} from '@/lib/server/access-token-policy';
|
|
|
|
/** Verify an ACCESS_CODE token with the Web Crypto API (Edge-compatible). */
|
|
export async function verifyAccessTokenWithWebCrypto(
|
|
token: string,
|
|
accessCode: string,
|
|
options: AccessTokenValidationOptions = {},
|
|
): Promise<boolean> {
|
|
const parsed = parseFreshAccessToken(token, {
|
|
...options,
|
|
ttlSeconds:
|
|
options.ttlSeconds ??
|
|
resolveAccessCodeSessionTtlSeconds(process.env.ACCESS_CODE_SESSION_TTL_SECONDS),
|
|
});
|
|
if (!parsed) return false;
|
|
|
|
const signature = hexToBytes(parsed.signatureHex);
|
|
if (!signature) return false;
|
|
|
|
const encoder = new TextEncoder();
|
|
const key = await crypto.subtle.importKey(
|
|
'raw',
|
|
encoder.encode(accessCode),
|
|
{ name: 'HMAC', hash: 'SHA-256' },
|
|
false,
|
|
['verify'],
|
|
);
|
|
|
|
return crypto.subtle.verify(
|
|
'HMAC',
|
|
key,
|
|
signature.buffer as ArrayBuffer,
|
|
encoder.encode(parsed.issuedAtText),
|
|
);
|
|
}
|