HXCS-3521 emit token_received upon user login (#9710)

* Add unit tests for redirect auth service

* add unit test for authentication service
This commit is contained in:
Ricardo Dias 2024-06-18 15:34:16 +01:00 committed by GitHub
parent b7ebfecb4d
commit eba5e10c4f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 112 additions and 2 deletions

View File

@ -42,7 +42,7 @@ describe('AuthBearerInterceptor', () => {
HttpHandler,
AuthBearerInterceptor,
AuthenticationService,
{ provide: RedirectAuthService, useValue: { onLogin: EMPTY } }
{ provide: RedirectAuthService, useValue: { onLogin: EMPTY, onTokenReceived: of() } }
]
});

View File

@ -24,6 +24,8 @@ import { Observable } from 'rxjs';
export abstract class AuthService {
abstract onLogin: Observable<any>;
abstract onTokenReceived: Observable<any>;
/** Subscribe to whether the user has valid Id/Access tokens. */
abstract authenticated$: Observable<boolean>;

View File

@ -0,0 +1,69 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { TestBed } from '@angular/core/testing';
import { OAuthService, OAuthEvent, OAuthStorage, AUTH_CONFIG } from 'angular-oauth2-oidc';
import { Subject } from 'rxjs';
import { RedirectAuthService } from './redirect-auth.service';
import { AUTH_MODULE_CONFIG } from './auth-config';
describe('RedirectAuthService', () => {
let service: RedirectAuthService;
const mockOAuthStorage: Partial<OAuthStorage> = {
getItem: jasmine.createSpy('getItem'),
removeItem: jasmine.createSpy('removeItem'),
setItem: jasmine.createSpy('setItem')
};
const oauthEvents$ = new Subject<OAuthEvent>();
const mockOauthService: Partial<OAuthService> = {
clearHashAfterLogin: false,
events: oauthEvents$
};
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
RedirectAuthService,
{ provide: OAuthService, useValue: mockOauthService },
{ provide: OAuthStorage, useValue: mockOAuthStorage },
{ provide: AUTH_CONFIG, useValue: {} },
{ provide: AUTH_MODULE_CONFIG, useValue: {} }
]
});
service = TestBed.inject(RedirectAuthService);
TestBed.inject(OAuthService);
});
it('should emit event when token_received event is received', () => {
const onTokenReceivedSpy = jasmine.createSpy();
service.onTokenReceived.subscribe(onTokenReceivedSpy);
oauthEvents$.next({ type: 'token_received' } as OAuthEvent);
expect(onTokenReceivedSpy).toHaveBeenCalled();
});
it('should not emit event when a different event is received', () => {
const onTokenReceivedSpy = jasmine.createSpy();
service.onTokenReceived.subscribe(onTokenReceivedSpy);
oauthEvents$.next({ type: 'user_profile_loaded' } as OAuthEvent);
expect(onTokenReceivedSpy).not.toHaveBeenCalled();
});
});

View File

@ -16,7 +16,7 @@
*/
import { Inject, Injectable, inject } from '@angular/core';
import { AuthConfig, AUTH_CONFIG, OAuthErrorEvent, OAuthService, OAuthStorage, TokenResponse, LoginOptions } from 'angular-oauth2-oidc';
import { AuthConfig, AUTH_CONFIG, OAuthErrorEvent, OAuthEvent, OAuthService, OAuthStorage, TokenResponse, LoginOptions } from 'angular-oauth2-oidc';
import { JwksValidationHandler } from 'angular-oauth2-oidc-jwks';
import { from, Observable } from 'rxjs';
import { distinctUntilChanged, filter, map, shareReplay } from 'rxjs/operators';
@ -32,6 +32,8 @@ export class RedirectAuthService extends AuthService {
onLogin: Observable<any>;
onTokenReceived: Observable<any>;
private _loadDiscoveryDocumentPromise = Promise.resolve(false);
/** Subscribe to whether the user has valid Id/Access tokens. */
@ -72,6 +74,11 @@ export class RedirectAuthService extends AuthService {
map(() => undefined)
);
this.onTokenReceived = this.oauthService.events.pipe(
filter((event: OAuthEvent) => event.type === 'token_received'),
map(() => undefined)
);
this.idpUnreachable$ = this.oauthService.events.pipe(
filter((event): event is OAuthErrorEvent => event.type === 'discovery_document_load_error'),
map((event) => event.reason as Error)

View File

@ -23,6 +23,10 @@ import { setupTestBed } from '../../testing/setup-test-bed';
import { CoreTestingModule } from '../../testing/core.testing.module';
import { BasicAlfrescoAuthService } from '../basic-auth/basic-alfresco-auth.service';
import { OidcAuthenticationService } from '../oidc/oidc-authentication.service';
import { OAuthEvent } from 'angular-oauth2-oidc';
import { Subject } from 'rxjs';
import { RedirectAuthService } from '../oidc/redirect-auth.service';
import { Injector } from '@angular/core';
declare let jasmine: any;
@ -507,4 +511,27 @@ describe('AuthenticationService', () => {
expect(username).toEqual('john.petrucci');
});
});
describe('onTokenReceived', () => {
let redirectAuthService: RedirectAuthService;
let authenticationService: AuthenticationService;
const onTokenReceived$: Subject<OAuthEvent> = new Subject<OAuthEvent>();
beforeEach(() => {
redirectAuthService = TestBed.inject(RedirectAuthService);
redirectAuthService.onTokenReceived = onTokenReceived$;
const injector = TestBed.inject(Injector);
authenticationService = new AuthenticationService(injector, redirectAuthService);
});
it('should emit event when RedirectAuthService onTokenReceived emits', () => {
const onTokenReceivedSpy = jasmine.createSpy();
authenticationService.onTokenReceived.subscribe(onTokenReceivedSpy);
onTokenReceived$.next();
expect(onTokenReceivedSpy).toHaveBeenCalled();
});
});
});

View File

@ -30,10 +30,15 @@ import { RedirectAuthService } from '../oidc/redirect-auth.service';
export class AuthenticationService implements AuthenticationServiceInterface, ee.Emitter {
onLogin: Subject<any> = new Subject<any>();
onLogout: Subject<any> = new Subject<any>();
onTokenReceived: Subject<any> = new Subject<any>();
constructor(private injector: Injector, private redirectAuthService: RedirectAuthService) {
this.redirectAuthService.onLogin.subscribe((value) => this.onLogin.next(value));
this.redirectAuthService.onTokenReceived.subscribe(
(value) => this.onTokenReceived.next(value)
);
this.basicAlfrescoAuthService.onLogin.subscribe((value) => this.onLogin.next(value));
if (this.isOauth()) {