challenge validate session

This commit is contained in:
Evert Prants 2022-09-20 17:55:43 +03:00
parent a94f987519
commit 3d97f6659e
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
2 changed files with 35 additions and 9 deletions

View File

@ -25,6 +25,13 @@ import { UserService } from 'src/modules/objects/user/user.service';
import { FormUtilityService } from 'src/modules/utility/services/form-utility.service'; import { FormUtilityService } from 'src/modules/utility/services/form-utility.service';
import { TokenService } from 'src/modules/utility/services/token.service'; import { TokenService } from 'src/modules/utility/services/token.service';
interface VerifyChallenge {
type: 'verify';
id: string;
user: string;
remember: boolean;
}
@Controller('/login') @Controller('/login')
export class LoginController { export class LoginController {
constructor( constructor(
@ -80,7 +87,12 @@ export class LoginController {
await this.audit.auditRequest(req, AuditAction.LOGIN, req.session.id, user); await this.audit.auditRequest(req, AuditAction.LOGIN, req.session.id, user);
if (await this.totpService.userHasTOTP(user)) { if (await this.totpService.userHasTOTP(user)) {
const challenge = { type: 'verify', user: user.uuid, remember }; const challenge: VerifyChallenge = {
type: 'verify',
id: req.session.id,
user: user.uuid,
remember,
};
const encrypted = await this.token.encryptChallenge(challenge); const encrypted = await this.token.encryptChallenge(challenge);
res.redirect( res.redirect(
`login/verify?challenge=${encrypted}${ `login/verify?challenge=${encrypted}${
@ -141,12 +153,15 @@ export class LoginController {
throw new Error('No challenge'); throw new Error('No challenge');
} }
const decrypted = await this.token.decryptChallenge<{ const decrypted = await this.token.decryptChallenge<VerifyChallenge>(
type: 'verify'; query.challenge,
user: string; );
remember: boolean; if (
}>(query.challenge); !decrypted ||
if (!decrypted || decrypted.type !== 'verify' || !decrypted.user) { decrypted.type !== 'verify' ||
decrypted.id !== req.session.id ||
!decrypted.user
) {
throw new Error('Bad challenge'); throw new Error('Bad challenge');
} }

View File

@ -9,6 +9,7 @@ import { QRCodeService } from 'src/modules/utility/services/qr-code.service';
import { TokenService } from 'src/modules/utility/services/token.service'; import { TokenService } from 'src/modules/utility/services/token.service';
interface ChallengeType { interface ChallengeType {
id: string;
secret: string; secret: string;
type: 'totp'; type: 'totp';
user: string; user: string;
@ -36,14 +37,23 @@ export class TwoFactorController {
const challenge = await this.token.decryptChallenge<ChallengeType>( const challenge = await this.token.decryptChallenge<ChallengeType>(
challengeString, challengeString,
); );
if (challenge.type === 'totp' && challenge.user === req.user.uuid) { if (
challenge.type === 'totp' &&
challenge.user === req.user.uuid &&
challenge.id === req.session.id
) {
secret = challenge.secret; secret = challenge.secret;
} }
} }
if (!secret) { if (!secret) {
secret = this.totp.createTOTPSecret(); secret = this.totp.createTOTPSecret();
const challenge = { type: 'totp', secret, user: req.user.uuid }; const challenge = {
type: 'totp',
secret,
id: req.session.id,
user: req.user.uuid,
};
const encrypted = await this.token.encryptChallenge(challenge); const encrypted = await this.token.encryptChallenge(challenge);
const cleanURL = req.originalUrl.replace(/\?(.*)$/, ''); const cleanURL = req.originalUrl.replace(/\?(.*)$/, '');
res.redirect(`${cleanURL}?challenge=${encrypted}`); res.redirect(`${cleanURL}?challenge=${encrypted}`);
@ -85,6 +95,7 @@ export class TwoFactorController {
if ( if (
challenge.type !== 'totp' || challenge.type !== 'totp' ||
challenge.user !== req.user.uuid || challenge.user !== req.user.uuid ||
challenge.id !== req.session.id ||
!secret !secret
) { ) {
throw new Error('Invalid request'); throw new Error('Invalid request');