Skip to content

Commit c381541

Browse files
committed
fix: address PR review feedback on passkey and MyAccount API
- Refactor passkey.signup/login to use of(client).pipe(concatMap, tap, catchError) pattern, aligning with getAccessTokenSilently and loginWithCustomTokenExchange: errors now emit on error$ via authState.setError(), and the Observable is lazy (deferred until subscription) - Add corresponding unit tests asserting error$ receives passkey errors - Fix switchMap callbacks in EXAMPLES.md enrollment snippets: add async to all callbacks that use await (passkey, TOTP, phone, email, password)
1 parent 401f07c commit c381541

3 files changed

Lines changed: 51 additions & 11 deletions

File tree

EXAMPLES.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1823,7 +1823,7 @@ import { switchMap } from 'rxjs';
18231823
this.auth.myAccount
18241824
.enrollmentChallenge({ type: 'passkey' })
18251825
.pipe(
1826-
switchMap((challenge) => {
1826+
switchMap(async (challenge) => {
18271827
// Trigger the browser's WebAuthn credential creation ceremony
18281828
const credential = await navigator.credentials.create({
18291829
publicKey: {
@@ -1858,7 +1858,7 @@ import { switchMap } from 'rxjs';
18581858
this.auth.myAccount
18591859
.enrollmentChallenge({ type: 'totp' })
18601860
.pipe(
1861-
switchMap((challenge) => {
1861+
switchMap(async (challenge) => {
18621862
// challenge.barcode_uri — render as a QR code for the user to scan
18631863
// challenge.manual_input_code — fallback code for manual entry
18641864
showQrCode(challenge.barcode_uri);
@@ -1888,7 +1888,7 @@ this.auth.myAccount
18881888
preferred_authentication_method: 'sms', // or 'voice'
18891889
})
18901890
.pipe(
1891-
switchMap((challenge) => {
1891+
switchMap(async (challenge) => {
18921892
const otpCode = await promptUserForOtp();
18931893
18941894
return this.auth.myAccount.enrollmentVerify({
@@ -1910,7 +1910,7 @@ import { switchMap } from 'rxjs';
19101910
this.auth.myAccount
19111911
.enrollmentChallenge({ type: 'email', email: 'user@example.com' })
19121912
.pipe(
1913-
switchMap((challenge) => {
1913+
switchMap(async (challenge) => {
19141914
const otpCode = await promptUserForOtp();
19151915
19161916
return this.auth.myAccount.enrollmentVerify({
@@ -1977,7 +1977,7 @@ import { switchMap } from 'rxjs';
19771977
this.auth.myAccount
19781978
.enrollmentChallenge({ type: 'password' })
19791979
.pipe(
1980-
switchMap((challenge) => {
1980+
switchMap(async (challenge) => {
19811981
const newPassword = await promptUserForPassword();
19821982
19831983
return this.auth.myAccount.enrollmentVerify({

projects/auth0-angular/src/lib/auth.service.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1670,6 +1670,23 @@ describe('AuthService', () => {
16701670
});
16711671
});
16721672

1673+
it('should record errors in the error$ observable', (done) => {
1674+
const errorObj = new Error('WebAuthn not supported');
1675+
(
1676+
auth0Client.passkey.signup as unknown as jest.SpyInstance
1677+
).mockRejectedValue(errorObj);
1678+
const service = createService();
1679+
1680+
service.passkey.signup({ email: 'user@example.com' }).subscribe({
1681+
error: () => {},
1682+
});
1683+
1684+
service.error$.subscribe((err: Error) => {
1685+
expect(err).toBe(errorObj);
1686+
done();
1687+
});
1688+
});
1689+
16731690
it('should bubble errors', (done) => {
16741691
const errorObj = new Error('WebAuthn not supported');
16751692
(
@@ -1734,6 +1751,23 @@ describe('AuthService', () => {
17341751
});
17351752
});
17361753

1754+
it('should record errors in the error$ observable', (done) => {
1755+
const errorObj = new Error('User cancelled');
1756+
(
1757+
auth0Client.passkey.login as unknown as jest.SpyInstance
1758+
).mockRejectedValue(errorObj);
1759+
const service = createService();
1760+
1761+
service.passkey.login().subscribe({
1762+
error: () => {},
1763+
});
1764+
1765+
service.error$.subscribe((err: Error) => {
1766+
expect(err).toBe(errorObj);
1767+
done();
1768+
});
1769+
});
1770+
17371771
it('should bubble errors', (done) => {
17381772
const errorObj = new Error('User cancelled');
17391773
(

projects/auth0-angular/src/lib/auth.service.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -529,17 +529,23 @@ export class AuthService<TAppState extends AppState = AppState>
529529
*/
530530
readonly passkey: ObservablePasskeyApiClient = {
531531
signup: (options: PasskeySignupOptions) =>
532-
from(
533-
this.auth0Client.passkey.signup(options).then((tokenResponse) => {
532+
of(this.auth0Client).pipe(
533+
concatMap((client) => client.passkey.signup(options)),
534+
tap(() => this.authState.refresh()),
535+
catchError((error) => {
536+
this.authState.setError(error);
534537
this.authState.refresh();
535-
return tokenResponse;
538+
return throwError(error);
536539
})
537540
),
538541
login: (options?: PasskeyLoginOptions) =>
539-
from(
540-
this.auth0Client.passkey.login(options).then((tokenResponse) => {
542+
of(this.auth0Client).pipe(
543+
concatMap((client) => client.passkey.login(options)),
544+
tap(() => this.authState.refresh()),
545+
catchError((error) => {
546+
this.authState.setError(error);
541547
this.authState.refresh();
542-
return tokenResponse;
548+
return throwError(error);
543549
})
544550
),
545551
};

0 commit comments

Comments
 (0)