Feature/improve error handling in biometric authentication registration (#3496)
* Improve error handling in biometric authentication registration * Update changelog
This commit is contained in:
parent
6c2acf2aa6
commit
a25d5b9dc0
@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- Improved the error handling in the biometric authentication registration
|
||||||
- Set up SSL for local development
|
- Set up SSL for local development
|
||||||
|
|
||||||
## 2.89.0 - 2024-06-14
|
## 2.89.0 - 2024-06-14
|
||||||
|
@ -20,9 +20,10 @@ import {
|
|||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { FormBuilder, Validators } from '@angular/forms';
|
import { FormBuilder, Validators } from '@angular/forms';
|
||||||
import { MatSlideToggleChange } from '@angular/material/slide-toggle';
|
import { MatSlideToggleChange } from '@angular/material/slide-toggle';
|
||||||
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
import { format, parseISO } from 'date-fns';
|
import { format, parseISO } from 'date-fns';
|
||||||
import { uniq } from 'lodash';
|
import { uniq } from 'lodash';
|
||||||
import { EMPTY, Subject } from 'rxjs';
|
import { EMPTY, Subject, throwError } from 'rxjs';
|
||||||
import { catchError, takeUntil } from 'rxjs/operators';
|
import { catchError, takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -42,6 +43,7 @@ export class UserAccountSettingsComponent implements OnDestroy, OnInit {
|
|||||||
public hasPermissionToUpdateViewMode: boolean;
|
public hasPermissionToUpdateViewMode: boolean;
|
||||||
public hasPermissionToUpdateUserSettings: boolean;
|
public hasPermissionToUpdateUserSettings: boolean;
|
||||||
public isAccessTokenHidden = true;
|
public isAccessTokenHidden = true;
|
||||||
|
public isFingerprintSupported = this.doesBrowserSupportAuthn();
|
||||||
public isWebAuthnEnabled: boolean;
|
public isWebAuthnEnabled: boolean;
|
||||||
public language = document.documentElement.lang;
|
public language = document.documentElement.lang;
|
||||||
public locales = [
|
public locales = [
|
||||||
@ -67,6 +69,7 @@ export class UserAccountSettingsComponent implements OnDestroy, OnInit {
|
|||||||
private dataService: DataService,
|
private dataService: DataService,
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
private settingsStorageService: SettingsStorageService,
|
private settingsStorageService: SettingsStorageService,
|
||||||
|
private snackBar: MatSnackBar,
|
||||||
private tokenStorageService: TokenStorageService,
|
private tokenStorageService: TokenStorageService,
|
||||||
private userService: UserService,
|
private userService: UserService,
|
||||||
public webAuthnService: WebAuthnService
|
public webAuthnService: WebAuthnService
|
||||||
@ -222,9 +225,15 @@ export class UserAccountSettingsComponent implements OnDestroy, OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public onSignInWithFingerprintChange(aEvent: MatSlideToggleChange) {
|
public async onSignInWithFingerprintChange(aEvent: MatSlideToggleChange) {
|
||||||
if (aEvent.checked) {
|
if (aEvent.checked) {
|
||||||
this.registerDevice();
|
try {
|
||||||
|
await this.registerDevice();
|
||||||
|
} catch {
|
||||||
|
aEvent.source.checked = false;
|
||||||
|
|
||||||
|
this.changeDetectorRef.markForCheck();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const confirmation = confirm(
|
const confirmation = confirm(
|
||||||
$localize`Do you really want to remove this sign in method?`
|
$localize`Do you really want to remove this sign in method?`
|
||||||
@ -265,35 +274,54 @@ export class UserAccountSettingsComponent implements OnDestroy, OnInit {
|
|||||||
this.webAuthnService
|
this.webAuthnService
|
||||||
.deregister()
|
.deregister()
|
||||||
.pipe(
|
.pipe(
|
||||||
takeUntil(this.unsubscribeSubject),
|
|
||||||
catchError(() => {
|
catchError(() => {
|
||||||
this.update();
|
this.update();
|
||||||
|
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
})
|
}),
|
||||||
|
takeUntil(this.unsubscribeSubject)
|
||||||
)
|
)
|
||||||
.subscribe(() => {
|
.subscribe(() => {
|
||||||
this.update();
|
this.update();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private registerDevice() {
|
private doesBrowserSupportAuthn() {
|
||||||
this.webAuthnService
|
// Authn is built on top of PublicKeyCredential: https://stackoverflow.com/a/55868189
|
||||||
.register()
|
return typeof PublicKeyCredential !== 'undefined';
|
||||||
.pipe(
|
}
|
||||||
takeUntil(this.unsubscribeSubject),
|
|
||||||
catchError(() => {
|
|
||||||
this.update();
|
|
||||||
|
|
||||||
return EMPTY;
|
private registerDevice(): Promise<void> {
|
||||||
})
|
return new Promise((resolve, reject) => {
|
||||||
)
|
this.webAuthnService
|
||||||
.subscribe(() => {
|
.register()
|
||||||
this.settingsStorageService.removeSetting(KEY_STAY_SIGNED_IN);
|
.pipe(
|
||||||
this.settingsStorageService.removeSetting(KEY_TOKEN);
|
catchError((error: Error) => {
|
||||||
|
this.snackBar.open(
|
||||||
|
$localize`Oops! There was an error setting up biometric authentication.`,
|
||||||
|
undefined,
|
||||||
|
{ duration: 3000 }
|
||||||
|
);
|
||||||
|
|
||||||
this.update();
|
return throwError(() => {
|
||||||
});
|
return error;
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
takeUntil(this.unsubscribeSubject)
|
||||||
|
)
|
||||||
|
.subscribe({
|
||||||
|
next: () => {
|
||||||
|
this.settingsStorageService.removeSetting(KEY_STAY_SIGNED_IN);
|
||||||
|
this.settingsStorageService.removeSetting(KEY_TOKEN);
|
||||||
|
|
||||||
|
this.update();
|
||||||
|
resolve();
|
||||||
|
},
|
||||||
|
error: (error) => {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private update() {
|
private update() {
|
||||||
|
@ -189,7 +189,9 @@
|
|||||||
color="primary"
|
color="primary"
|
||||||
hideIcon="true"
|
hideIcon="true"
|
||||||
[checked]="isWebAuthnEnabled === true"
|
[checked]="isWebAuthnEnabled === true"
|
||||||
[disabled]="!hasPermissionToUpdateUserSettings"
|
[disabled]="
|
||||||
|
!hasPermissionToUpdateUserSettings || !isFingerprintSupported
|
||||||
|
"
|
||||||
(change)="onSignInWithFingerprintChange($event)"
|
(change)="onSignInWithFingerprintChange($event)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user