26 lines
928 B
TypeScript
26 lines
928 B
TypeScript
import { verifyPassword } from '../../utils/password.js';
|
|
import { getDummyHash, usersRegistry } from '../../auth/users.registry.js';
|
|
import { InvalidCredentialsError } from '../../utils/errors.js';
|
|
|
|
export interface AuthenticatedUser {
|
|
id: string;
|
|
username: string;
|
|
slug: string;
|
|
displayName: string;
|
|
}
|
|
|
|
export async function verifyCredentials(
|
|
username: string,
|
|
password: string,
|
|
): Promise<AuthenticatedUser> {
|
|
const user = usersRegistry.findByUsername(username);
|
|
// Always run bcrypt.compare to keep response time stable regardless of whether
|
|
// the username exists. Otherwise an attacker could enumerate usernames by timing.
|
|
const hash = user?.passwordHash ?? (await getDummyHash());
|
|
const ok = await verifyPassword(password, hash);
|
|
if (!user || !ok) {
|
|
throw new InvalidCredentialsError();
|
|
}
|
|
return { id: user.id, username: user.username, slug: user.slug, displayName: user.displayName };
|
|
}
|