Add challenge type validation

This commit is contained in:
William Oldham
2023-11-04 09:42:45 +00:00
parent bbd13453b2
commit 9c19cf509b
3 changed files with 21 additions and 7 deletions

View File

@@ -4,16 +4,20 @@ import { randomUUID } from 'crypto';
// 30 seconds // 30 seconds
const CHALLENGE_EXPIRY_MS = 3000000 * 1000; const CHALLENGE_EXPIRY_MS = 3000000 * 1000;
export type ChallengeFlow = 'registration' | 'login';
export type ChallengeType = 'mnemonic';
@Entity({ tableName: 'challenge_codes' }) @Entity({ tableName: 'challenge_codes' })
export class ChallengeCode { export class ChallengeCode {
@PrimaryKey({ name: 'code', type: 'uuid' }) @PrimaryKey({ name: 'code', type: 'uuid' })
code: string = randomUUID(); code: string = randomUUID();
@Property({ name: 'stage', type: 'text' }) @Property({ name: 'flow', type: 'text' })
stage!: 'registration' | 'login'; flow!: ChallengeFlow;
@Property({ name: 'auth_type' }) @Property({ name: 'auth_type' })
authType!: 'mnemonic'; authType!: ChallengeType;
@Property({ type: 'date' }) @Property({ type: 'date' })
createdAt: Date = new Date(); createdAt: Date = new Date();
@@ -24,7 +28,7 @@ export class ChallengeCode {
export interface ChallengeCodeDTO { export interface ChallengeCodeDTO {
code: string; code: string;
stage: string; flow: string;
authType: string; authType: string;
createdAt: string; createdAt: string;
expiresAt: string; expiresAt: string;
@@ -35,7 +39,7 @@ export function formatChallengeCode(
): ChallengeCodeDTO { ): ChallengeCodeDTO {
return { return {
code: challenge.code, code: challenge.code,
stage: challenge.stage, flow: challenge.flow,
authType: challenge.authType, authType: challenge.authType,
createdAt: challenge.createdAt.toISOString(), createdAt: challenge.createdAt.toISOString(),
expiresAt: challenge.expiresAt.toISOString(), expiresAt: challenge.expiresAt.toISOString(),

View File

@@ -37,7 +37,7 @@ export const manageAuthRouter = makeRouter((app) => {
const challenge = new ChallengeCode(); const challenge = new ChallengeCode();
challenge.authType = 'mnemonic'; challenge.authType = 'mnemonic';
challenge.stage = 'registration'; challenge.flow = 'registration';
await em.persistAndFlush(challenge); await em.persistAndFlush(challenge);
@@ -56,6 +56,8 @@ export const manageAuthRouter = makeRouter((app) => {
body.challenge.code, body.challenge.code,
body.publicKey, body.publicKey,
body.challenge.signature, body.challenge.signature,
'registration',
'mnemonic',
); );
const user = new User(); const user = new User();

View File

@@ -8,6 +8,8 @@ export async function assertChallengeCode(
code: string, code: string,
publicKey: string, publicKey: string,
signature: string, signature: string,
validFlow: ChallengeFlow,
validType: ChallengeType,
) { ) {
const now = Date.now(); const now = Date.now();
@@ -15,7 +17,13 @@ export async function assertChallengeCode(
code, code,
}); });
if (!challenge) throw new StatusError('Challenge Code Invalid', 401); if (
!challenge ||
challenge.flow !== validFlow ||
challenge.authType !== validType
) {
throw new StatusError('Challenge Code Invalid', 401);
}
if (challenge.expiresAt.getTime() <= now) if (challenge.expiresAt.getTime() <= now)
throw new StatusError('Challenge Code Expired', 401); throw new StatusError('Challenge Code Expired', 401);