Skip to content

Commit

Permalink
feat(auth): handle missing token errors by resetting to unauthenticat…
Browse files Browse the repository at this point in the history
…ed state (#2518)
  • Loading branch information
griest024 committed Jul 31, 2023
1 parent 3dec63e commit 3655843
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 9 deletions.
1 change: 1 addition & 0 deletions libs/auth/driver/src/constants/public_api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './unauthenticated-error-codes';
15 changes: 15 additions & 0 deletions libs/auth/driver/src/constants/unauthenticated-error-codes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { DaffAuthErrorCodes } from '@daffodil/auth';

import { DaffAuthDriverErrorCodes } from '../errors/public_api';

/**
* The error codes that indicate that the user definitely should not be in an unauthenticated state
* and if an auth token exists in storage, it is invalid.
* These are contrasted to network failures and other sporadic and generic errors that aren't
* a guarantee of the token's invalidity.
*/
export const DAFF_AUTH_UNAUTHENTICATED_ERROR_CODES = {
[DaffAuthDriverErrorCodes.UNAUTHORIZED]: true,
[DaffAuthDriverErrorCodes.AUTHENTICATION_FAILED]: true,
[DaffAuthErrorCodes.MISSING_TOKEN]: true,
};
1 change: 1 addition & 0 deletions libs/auth/driver/src/public_api.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './interfaces/public_api';
export * from './errors/public_api';
export * from './services/public_api';
export * from './constants/public_api';
3 changes: 2 additions & 1 deletion libs/auth/routing/src/guards/guest-only.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
DaffAuthStorageService,
} from '@daffodil/auth';
import {
DAFF_AUTH_UNAUTHENTICATED_ERROR_CODES,
DaffAuthDriverErrorCodes,
DaffAuthDriverTokenCheck,
} from '@daffodil/auth/driver';
Expand Down Expand Up @@ -58,7 +59,7 @@ export class GuestOnlyGuard implements CanActivate {
return this.tokenCheck.check().pipe(
map(() => false),
catchError((error: DaffError) => {
if (error.code === DaffAuthDriverErrorCodes.UNAUTHORIZED || error.code === DaffAuthDriverErrorCodes.AUTHENTICATION_FAILED) {
if (DAFF_AUTH_UNAUTHENTICATED_ERROR_CODES[error.code]) {
this.storage.removeAuthToken();
this.store.dispatch(new DaffAuthGuardLogout(this.errorMatcher(error)));
}
Expand Down
3 changes: 2 additions & 1 deletion libs/auth/routing/src/guards/member-only.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
DaffAuthStorageService,
} from '@daffodil/auth';
import {
DAFF_AUTH_UNAUTHENTICATED_ERROR_CODES,
DaffAuthDriverErrorCodes,
DaffAuthDriverTokenCheck,
} from '@daffodil/auth/driver';
Expand Down Expand Up @@ -59,7 +60,7 @@ export class MemberOnlyGuard implements CanActivate {
return this.tokenCheck.check().pipe(
map(() => true),
catchError((error: DaffError) => {
if (error.code === DaffAuthDriverErrorCodes.UNAUTHORIZED || error.code === DaffAuthDriverErrorCodes.AUTHENTICATION_FAILED) {
if (DAFF_AUTH_UNAUTHENTICATED_ERROR_CODES[error.code]) {
this.storage.removeAuthToken();
this.store.dispatch(new DaffAuthGuardLogout(this.errorMatcher(error)));
}
Expand Down
33 changes: 32 additions & 1 deletion libs/auth/state/src/effects/auth.effects.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import {
} from 'rxjs';
import { TestScheduler } from 'rxjs/testing';

import { DaffAuthStorageService } from '@daffodil/auth';
import {
DaffAuthMissingTokenError,
DaffAuthStorageService,
} from '@daffodil/auth';
import {
DaffAuthDriver,
DaffAuthInvalidAPIResponseError,
Expand Down Expand Up @@ -230,6 +233,34 @@ describe('@daffodil/auth/state | DaffAuthEffects', () => {
});
});

describe('when DaffAuthCheckFailure is dispatched for an authentication failed error', () => {
let revokeAction: DaffAuthCheckFailure;

beforeEach(() => {
revokeAction = new DaffAuthCheckFailure(new DaffAuthenticationFailedError('error'));
actions$ = hot('--a', { a: revokeAction });
expected = cold('--a', { a: new DaffAuthResetToUnauthenticated(revokeAction.type) });
});

it('should dispatch DaffAuthResetToUnauthenticated', () => {
expect(effects.resetToUnauthenticated$).toBeObservable(expected);
});
});

describe('when DaffAuthCheckFailure is dispatched for an missing token error', () => {
let revokeAction: DaffAuthCheckFailure;

beforeEach(() => {
revokeAction = new DaffAuthCheckFailure(new DaffAuthMissingTokenError('error'));
actions$ = hot('--a', { a: revokeAction });
expected = cold('--a', { a: new DaffAuthResetToUnauthenticated(revokeAction.type) });
});

it('should dispatch DaffAuthResetToUnauthenticated', () => {
expect(effects.resetToUnauthenticated$).toBeObservable(expected);
});
});

describe('when DaffAuthCheckFailure is dispatched for some random reason', () => {
let revokeAction: DaffAuthCheckFailure;

Expand Down
10 changes: 4 additions & 6 deletions libs/auth/state/src/effects/auth.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
import {
of,
EMPTY,
asyncScheduler,
} from 'rxjs';
import {
switchMap,
Expand All @@ -19,15 +18,14 @@ import {
repeat,
filter,
tap,
delay,
} from 'rxjs/operators';

import {
DaffAuthStorageService,
DAFF_AUTH_ERROR_MATCHER,
} from '@daffodil/auth';
import {
DaffAuthDriverErrorCodes,
DAFF_AUTH_UNAUTHENTICATED_ERROR_CODES,
DaffAuthDriverTokenCheck,
} from '@daffodil/auth/driver';
import {
Expand Down Expand Up @@ -127,11 +125,11 @@ export class DaffAuthEffects {
DaffAuthLoginActionTypes.LogoutSuccessAction,
),
filter((action) => {
// if the auth check failure is for any reason other than auth failure, don't reset
// if the auth check failure is for any reason other than auth failure,
// such as a network failure, don't reset
if (
action.type === DaffAuthActionTypes.AuthCheckFailureAction
&& action.errorMessage.code !== DaffAuthDriverErrorCodes.UNAUTHORIZED
&& action.errorMessage.code !== DaffAuthDriverErrorCodes.AUTHENTICATION_FAILED
&& !DAFF_AUTH_UNAUTHENTICATED_ERROR_CODES[action.errorMessage.code]
) {
return false;
}
Expand Down

0 comments on commit 3655843

Please sign in to comment.