@e280/authlocal
Version:
User-sovereign login system for everybody
41 lines • 1.89 kB
JavaScript
import { decodeToken } from "./decode.js";
import { tokentime } from "./tokentime.js";
import { verify } from "../crypto/crypto.js";
import { TokenVerifyError } from "./types.js";
export async function verifyToken(id, token, options = {}) {
const [headerText, payloadText] = token.split(".");
const { payload, signature } = decodeToken(token);
const signingText = `${headerText}.${payloadText}`;
const signingBytes = new TextEncoder().encode(signingText);
if (!await verify(signingBytes, signature, id))
throw new TokenVerifyError("token signature invalid");
if (options.atTime !== null) {
const atTime = options.atTime ?? Date.now();
if (payload.exp) {
const expiresAt = tokentime.toMs(payload.exp);
if (atTime > expiresAt)
throw new TokenVerifyError("token expired");
}
if (payload.nbf) {
const notBefore = tokentime.toMs(payload.nbf);
if (atTime < notBefore)
throw new TokenVerifyError("token not ready");
}
}
if (options.allowedIssuers) {
if (!payload.iss)
throw new TokenVerifyError(`required iss (issuer) is missing`);
if (!options.allowedIssuers.includes(payload.iss))
throw new TokenVerifyError(`invalid iss (issuer) "${payload.iss}"`);
}
if (options.allowedAudiences) {
if (!payload.aud)
throw new TokenVerifyError(`required aud (audience) is missing`);
if (!options.allowedAudiences.includes(payload.aud))
throw new TokenVerifyError(`invalid aud (audience) "${payload.aud}"`);
}
if (payload.aud && !options.allowedAudiences)
throw new TokenVerifyError(`allowedAudiences verification option was not provided, but is required because the token included "aud"`);
return payload;
}
//# sourceMappingURL=verify.js.map