import type { HttpContext } from '@adonisjs/core/http'; import User from '#models/user'; import BackupCode from '#models/backup_code'; // import Hash from '@ioc:Adonis/Core/Hash'; // import InvalidCredentialException from 'App/Exceptions/InvalidCredentialException'; import { authValidator } from '#validators/auth'; import hash from '@adonisjs/core/services/hash'; import TwoFactorAuthProvider from '#app/services/TwoFactorAuthProvider'; // import { Authenticator } from '@adonisjs/auth'; // import { LoginState } from 'Contracts/enums'; // import { StatusCodes } from 'http-status-codes'; // interface MyHttpsContext extends HttpContext { // auth: Authenticator // } export default class AuthController { // login function{ request, auth, response }:HttpContext public async login({ request, response, auth, session }: HttpContext) { // console.log({ // registerBody: request.body(), // }); // await request.validate(AuthValidator); await request.validateUsing(authValidator); // const plainPassword = await request.input('password'); // const email = await request.input('email'); // grab uid and password values off request body const { email, password } = request.only(['email', 'password']); try { // // attempt to verify credential and login user // await auth.use('web').attempt(email, plainPassword); // const user = await auth.use('web').verifyCredentials(email, password); const user = await User.verifyCredentials(email, password); if (user.isTwoFactorEnabled) { // session.put("login.id", user.id); // return view.render("pages/two-factor-challenge"); session.flash('user_id', user.id); return response.redirect().back(); // let state = LoginState.STATE_VALIDATED; // return response.status(StatusCodes.OK).json({ // state: state, // new_user_id: user.id, // }); } await auth.use('web').login(user); } catch (error) { // if login fails, return vague form message and redirect back session.flash('message', 'Your username, email, or password is incorrect'); return response.redirect().back(); } // otherwise, redirect todashboard response.redirect('/apps/dashboard'); } public async twoFactorChallenge({ request, session, auth, response }: HttpContext) { const { code, backup_code, login_id } = request.only(['code', 'backup_code', 'login_id']); const user = await User.query().where('id', login_id).firstOrFail(); if (code) { const isValid = await TwoFactorAuthProvider.validate(user, code); if (isValid) { // login user and redirect to dashboard await auth.use('web').login(user); response.redirect('/apps/dashboard'); } else { session.flash('message', 'Your two-factor code is incorrect'); return response.redirect().back(); } } else if (backup_code) { const codes: BackupCode[] = await user.getBackupCodes(); // const verifiedBackupCodes = await Promise.all( // codes.map(async (backupCode) => { // let isVerified = await hash.verify(backupCode.code, backup_code); // if (isVerified) { // return backupCode; // } // }), // ); // const backupCodeToDelete = verifiedBackupCodes.find(Boolean); let backupCodeToDelete = null; for (const backupCode of codes) { const isVerified = await hash.verify(backupCode.code, backup_code); if (isVerified) { backupCodeToDelete = backupCode; break; } } if (backupCodeToDelete) { if (backupCodeToDelete.used === false) { backupCodeToDelete.used = true; await backupCodeToDelete.save(); console.log(`BackupCode with id ${backupCodeToDelete.id} has been marked as used.`); await auth.use('web').login(user); response.redirect('/apps/dashboard'); } else { session.flash('message', 'BackupCode already used'); return response.redirect().back(); } } else { session.flash('message', 'BackupCode not found'); return response.redirect().back(); } } } // logout function public async logout({ auth, response }: HttpContext) { // await auth.logout(); await auth.use('web').logout(); return response.redirect('/app/login'); // return response.status(200); } }