pstream-backend/src/services/challenge.ts
2023-11-04 10:42:44 +00:00

55 lines
1.3 KiB
TypeScript

import {
ChallengeCode,
ChallengeFlow,
ChallengeType,
} from '@/db/models/ChallengeCode';
import { StatusError } from '@/services/error';
import { EntityManager } from '@mikro-orm/core';
import forge from 'node-forge';
const {
pki: { ed25519 },
util: { ByteStringBuffer },
} = forge;
export async function assertChallengeCode(
em: EntityManager,
code: string,
publicKey: string,
signature: string,
validFlow: ChallengeFlow,
validType: ChallengeType,
) {
const now = Date.now();
const challenge = await em.findOne(ChallengeCode, {
code,
});
if (
!challenge ||
challenge.flow !== validFlow ||
challenge.authType !== validType
) {
throw new StatusError('Challenge Code Invalid', 401);
}
if (challenge.expiresAt.getTime() <= now)
throw new StatusError('Challenge Code Expired', 401);
try {
const verifiedChallenge = ed25519.verify({
publicKey: new ByteStringBuffer(Buffer.from(publicKey, 'base64url')),
encoding: 'utf8',
signature: new ByteStringBuffer(Buffer.from(signature, 'base64url')),
message: code,
});
if (!verifiedChallenge)
throw new StatusError('Challenge Code Signature Invalid', 401);
em.remove(challenge);
} catch (e) {
throw new StatusError('Challenge Code Signature Invalid', 401);
}
}