From 040f58fafe156ad941f96dccf603b2829e581b43 Mon Sep 17 00:00:00 2001 From: itskovacs Date: Tue, 28 Oct 2025 18:19:11 +0100 Subject: [PATCH] :lipstick: TOTP auth --- .../app/components/auth/auth.component.html | 25 ++++++++++++++- src/src/app/components/auth/auth.component.ts | 31 ++++++++++++++----- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/src/app/components/auth/auth.component.html b/src/src/app/components/auth/auth.component.html index 1fe32cc..01caff2 100644 --- a/src/src/app/components/auth/auth.component.html +++ b/src/src/app/components/auth/auth.component.html @@ -1,11 +1,21 @@
-
+
+
+
+
+ Welcome to TRIP +
+
Tourism and Recreational Interest Points. +
+
+
+
{{ isRegistering ? "Register" : "Sign in" }}
@@ -18,6 +28,18 @@
} + @if (pendingOTP) { +
+

+ Enter your TOTP code +

+ +
+ + +
+
+ } @else { @defer () { @if (authParams?.oidc) {
@@ -91,6 +113,7 @@
} + }
diff --git a/src/src/app/components/auth/auth.component.ts b/src/src/app/components/auth/auth.component.ts index 2adf5a5..ed2e6dd 100644 --- a/src/src/app/components/auth/auth.component.ts +++ b/src/src/app/components/auth/auth.component.ts @@ -1,15 +1,16 @@ import { Component, OnInit } from '@angular/core'; import { FloatLabelModule } from 'primeng/floatlabel'; -import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; +import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { InputTextModule } from 'primeng/inputtext'; import { ButtonModule } from 'primeng/button'; import { FocusTrapModule } from 'primeng/focustrap'; -import { AuthParams, AuthService } from '../../services/auth.service'; +import { AuthParams, AuthService, TOTPRequired, Token } from '../../services/auth.service'; import { MessageModule } from 'primeng/message'; import { HttpErrorResponse } from '@angular/common/http'; import { SkeletonModule } from 'primeng/skeleton'; +import { InputOtpModule } from 'primeng/inputotp'; import { take } from 'rxjs'; @Component({ @@ -19,10 +20,12 @@ import { take } from 'rxjs'; FloatLabelModule, ReactiveFormsModule, ButtonModule, + FormsModule, InputTextModule, SkeletonModule, FocusTrapModule, MessageModule, + InputOtpModule, ], templateUrl: './auth.component.html', styleUrl: './auth.component.scss', @@ -33,6 +36,9 @@ export class AuthComponent implements OnInit { authForm: FormGroup; error: string | undefined; isRegistering: boolean = false; + pendingOTP: string = ''; + otp: string = ''; + username: string = ''; constructor( private authService: AuthService, @@ -99,11 +105,12 @@ export class AuthComponent implements OnInit { this.authService.login(this.authForm.value).subscribe({ next: (data) => { - if (!data.access_token) { - this.error = 'Authentication failed'; - return; - } - this.router.navigateByUrl(this.redirectURL); + if ((data as Token)?.access_token) this.router.navigateByUrl(this.redirectURL); + + // If we're here, it means it's OTP time + this.username = (data as TOTPRequired).username; + this.pendingOTP = (data as TOTPRequired).pending_code; + this.authForm.reset(); }, error: () => { this.authForm.reset(); @@ -111,6 +118,16 @@ export class AuthComponent implements OnInit { }); } + verifyTOTP(): void { + this.error = ''; + this.authService.verify_totp(this.username, this.pendingOTP, this.otp).subscribe({ + next: (token) => { + if (token) this.router.navigateByUrl(this.redirectURL); + }, + error: () => (this.otp = ''), + }); + } + getAuthParams() { this.authService .authParams()