🐛 Fix possible race condition in Auth

This commit is contained in:
itskovacs 2025-08-06 21:08:21 +02:00
parent e5a44af210
commit 39d69199fe
2 changed files with 38 additions and 27 deletions

View File

@ -40,7 +40,7 @@
<p-floatlabel variant="in" class="mt-4"> <p-floatlabel variant="in" class="mt-4">
<input pInputText type="password" inputId="password" formControlName="password" fluid <input pInputText type="password" inputId="password" formControlName="password" fluid
(keyup.enter)="auth_or_register()" /> (keyup.enter)="onKeypressEnter()" />
<label for="password">Password</label> <label for="password">Password</label>
</p-floatlabel> </p-floatlabel>
@if ( @if (

View File

@ -1,4 +1,4 @@
import { Component } from "@angular/core"; import { Component, OnInit } from "@angular/core";
import { FloatLabelModule } from "primeng/floatlabel"; import { FloatLabelModule } from "primeng/floatlabel";
import { import {
@ -16,6 +16,7 @@ import { AuthParams, AuthService, Token } from "../../services/auth.service";
import { MessageModule } from "primeng/message"; import { MessageModule } from "primeng/message";
import { HttpErrorResponse } from "@angular/common/http"; import { HttpErrorResponse } from "@angular/common/http";
import { SkeletonModule } from "primeng/skeleton"; import { SkeletonModule } from "primeng/skeleton";
import { take } from "rxjs";
@Component({ @Component({
selector: "app-auth", selector: "app-auth",
@ -24,7 +25,6 @@ import { SkeletonModule } from "primeng/skeleton";
FloatLabelModule, FloatLabelModule,
ReactiveFormsModule, ReactiveFormsModule,
ButtonModule, ButtonModule,
FormsModule,
InputTextModule, InputTextModule,
SkeletonModule, SkeletonModule,
FocusTrapModule, FocusTrapModule,
@ -33,11 +33,11 @@ import { SkeletonModule } from "primeng/skeleton";
templateUrl: "./auth.component.html", templateUrl: "./auth.component.html",
styleUrl: "./auth.component.scss", styleUrl: "./auth.component.scss",
}) })
export class AuthComponent { export class AuthComponent implements OnInit {
private redirectURL: string; readonly redirectURL: string;
authParams: AuthParams | undefined; authParams: AuthParams | undefined;
authForm: FormGroup; authForm: FormGroup;
error: string = ""; error: string | undefined;
isRegistering: boolean = false; isRegistering: boolean = false;
constructor( constructor(
@ -46,8 +46,17 @@ export class AuthComponent {
private route: ActivatedRoute, private route: ActivatedRoute,
private fb: FormBuilder, private fb: FormBuilder,
) { ) {
this.route.queryParams.subscribe((params) => { this.redirectURL =
if (!Object.keys(params).length) return; this.route.snapshot.queryParams["redirectURL"] || "/home";
this.authForm = this.fb.group({
username: ["", { validators: Validators.required }],
password: ["", { validators: Validators.required }],
});
}
ngOnInit(): void {
this.route.queryParams.pipe(take(1)).subscribe((params) => {
const code = params["code"]; const code = params["code"];
const state = params["state"]; const state = params["state"];
if (code && state) { if (code && state) {
@ -59,33 +68,24 @@ export class AuthComponent {
} }
this.router.navigateByUrl(this.redirectURL); this.router.navigateByUrl(this.redirectURL);
}, },
error: (err: HttpErrorResponse) => {
this.error =
err.error.detail || "Login failed, check console for details";
},
}); });
} else {
this.getAuthParams();
} }
}); });
// Timeout to handle race condition
setTimeout(() => {
this.authService.authParams().subscribe({
next: (params) => (this.authParams = params),
});
}, 100);
this.redirectURL =
this.route.snapshot.queryParams["redirectURL"] || "/home";
this.authForm = this.fb.group({
username: ["", { validators: Validators.required }],
password: ["", { validators: Validators.required }],
});
} }
auth_or_register() { onKeypressEnter() {
if (this.isRegistering) this.register(); if (this.isRegistering) this.register();
else this.authenticate(); else this.authenticate();
} }
register(): void { register(): void {
this.error = ""; this.error = undefined;
if (this.authForm.valid) { if (this.authForm.valid) {
this.authService.register(this.authForm.value).subscribe({ this.authService.register(this.authForm.value).subscribe({
next: () => { next: () => {
@ -93,14 +93,16 @@ export class AuthComponent {
}, },
error: (err: HttpErrorResponse) => { error: (err: HttpErrorResponse) => {
this.authForm.reset(); this.authForm.reset();
this.error = err.error.detail; this.error =
err.error.detail ||
"Registration failed, check console for details";
}, },
}); });
} }
} }
authenticate(): void { authenticate(): void {
this.error = ""; this.error = undefined;
if (this.authParams?.oidc) { if (this.authParams?.oidc) {
window.location.replace(this.authParams.oidc); window.location.replace(this.authParams.oidc);
} }
@ -118,4 +120,13 @@ export class AuthComponent {
}, },
}); });
} }
getAuthParams() {
this.authService
.authParams()
.pipe(take(1))
.subscribe({
next: (params) => (this.authParams = params),
});
}
} }