From 34c07fd9040af4e5adc020029247204eb8e2df49 Mon Sep 17 00:00:00 2001 From: Nathan Buckingham Date: Thu, 2 Feb 2023 17:51:30 -0500 Subject: [PATCH 1/5] w2p-99039 Add xsrf token to createShortLivedToken get request --- src/app/core/auth/server-auth-request.service.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/app/core/auth/server-auth-request.service.ts b/src/app/core/auth/server-auth-request.service.ts index 751389f71d..4ed44b9cc9 100644 --- a/src/app/core/auth/server-auth-request.service.ts +++ b/src/app/core/auth/server-auth-request.service.ts @@ -4,6 +4,8 @@ import { GetRequest } from '../data/request.models'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { RequestService } from '../data/request.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { HttpHeaders, HttpXsrfTokenExtractor } from '@angular/common/http'; +import { XSRF_REQUEST_HEADER } from '../xsrf/xsrf.interceptor'; /** * Server side version of the service to send authentication requests @@ -14,7 +16,8 @@ export class ServerAuthRequestService extends AuthRequestService { constructor( halService: HALEndpointService, requestService: RequestService, - rdbService: RemoteDataBuildService + rdbService: RemoteDataBuildService, + protected tokenExtractor: HttpXsrfTokenExtractor, ) { super(halService, requestService, rdbService); } @@ -28,7 +31,13 @@ export class ServerAuthRequestService extends AuthRequestService { * @protected */ protected createShortLivedTokenRequest(href: string): GetRequest { - return Object.assign(new GetRequest(this.requestService.generateRequestId(), href), { + let options = new HttpHeaders(); + options = options.set('Content-Type', 'application/json; charset=utf-8'); + options = options.set(XSRF_REQUEST_HEADER, this.tokenExtractor.getToken()); + let requestOptions = { + headers: options, + }; + return Object.assign(new GetRequest(this.requestService.generateRequestId(), href, {}, requestOptions), { responseMsToLive: 2 * 1000 // A short lived token is only valid for 2 seconds. }); } From 6d99f51d78a836ed713c925998793c286e284305 Mon Sep 17 00:00:00 2001 From: Nathan Buckingham Date: Fri, 3 Feb 2023 15:45:44 -0500 Subject: [PATCH 2/5] Add test for xsrf and change to Post so xsrf is tested for validity --- .../auth/server-auth-request.service.spec.ts | 16 +++++++++++++--- src/app/core/auth/server-auth-request.service.ts | 6 +++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/app/core/auth/server-auth-request.service.spec.ts b/src/app/core/auth/server-auth-request.service.spec.ts index 69053fbb3a..2612f9d5b4 100644 --- a/src/app/core/auth/server-auth-request.service.spec.ts +++ b/src/app/core/auth/server-auth-request.service.spec.ts @@ -1,24 +1,29 @@ import { AuthRequestService } from './auth-request.service'; import { RequestService } from '../data/request.service'; import { ServerAuthRequestService } from './server-auth-request.service'; +import { HttpXsrfTokenExtractorMock } from '../../shared/mocks/http-xsrf-token-extractor.mock'; describe(`ServerAuthRequestService`, () => { let href: string; let requestService: RequestService; let service: AuthRequestService; + let xsrfExtractor: HttpXsrfTokenExtractorMock; + + const mockToken = 'mockToken'; beforeEach(() => { href = 'https://rest.api/auth/shortlivedtokens'; requestService = jasmine.createSpyObj('requestService', { 'generateRequestId': '8bb0582d-5013-4337-af9c-763beb25aae2' }); - service = new ServerAuthRequestService(null, requestService, null); + xsrfExtractor = new HttpXsrfTokenExtractorMock(mockToken); + service = new ServerAuthRequestService(null, requestService, null, xsrfExtractor); }); describe(`createShortLivedTokenRequest`, () => { - it(`should return a GetRequest`, () => { + it(`should return a PostRequest`, () => { const result = (service as any).createShortLivedTokenRequest(href); - expect(result.constructor.name).toBe('GetRequest'); + expect(result.constructor.name).toBe('PostRequest'); }); it(`should return a request with the given href`, () => { @@ -26,6 +31,11 @@ describe(`ServerAuthRequestService`, () => { expect(result.href).toBe(href) ; }); + it(`should return a request with a xsrf header`, () => { + const result = (service as any).createShortLivedTokenRequest(href); + expect(result.options.headers.get('X-XSRF-TOKEN')).toBe(mockToken); + }); + it(`should have a responseMsToLive of 2 seconds`, () => { const result = (service as any).createShortLivedTokenRequest(href); expect(result.responseMsToLive).toBe(2 * 1000) ; diff --git a/src/app/core/auth/server-auth-request.service.ts b/src/app/core/auth/server-auth-request.service.ts index 4ed44b9cc9..9954e7c7ef 100644 --- a/src/app/core/auth/server-auth-request.service.ts +++ b/src/app/core/auth/server-auth-request.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { AuthRequestService } from './auth-request.service'; -import { GetRequest } from '../data/request.models'; +import { PostRequest } from '../data/request.models'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { RequestService } from '../data/request.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; @@ -30,14 +30,14 @@ export class ServerAuthRequestService extends AuthRequestService { * @param href The href to send the request to * @protected */ - protected createShortLivedTokenRequest(href: string): GetRequest { + protected createShortLivedTokenRequest(href: string): PostRequest { let options = new HttpHeaders(); options = options.set('Content-Type', 'application/json; charset=utf-8'); options = options.set(XSRF_REQUEST_HEADER, this.tokenExtractor.getToken()); let requestOptions = { headers: options, }; - return Object.assign(new GetRequest(this.requestService.generateRequestId(), href, {}, requestOptions), { + return Object.assign(new PostRequest(this.requestService.generateRequestId(), href, {}, requestOptions), { responseMsToLive: 2 * 1000 // A short lived token is only valid for 2 seconds. }); } From 06de559974c085e0098831054cc9e0f6b446502c Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Tue, 7 Feb 2023 14:49:22 +0100 Subject: [PATCH 3/5] Retrieve the XSRF token first, and set it as both the XSRF header and cookie --- src/app/core/auth/auth-request.service.ts | 8 ++- .../core/auth/browser-auth-request.service.ts | 9 ++-- .../core/auth/server-auth-request.service.ts | 54 +++++++++++++------ src/app/core/services/server-xhr.service.ts | 16 ++++++ src/app/core/xsrf/xsrf.interceptor.ts | 2 + src/modules/app/server-app.module.ts | 6 +++ 6 files changed, 69 insertions(+), 26 deletions(-) create mode 100644 src/app/core/services/server-xhr.service.ts diff --git a/src/app/core/auth/auth-request.service.ts b/src/app/core/auth/auth-request.service.ts index 5c0c3340c7..7c1f17dec2 100644 --- a/src/app/core/auth/auth-request.service.ts +++ b/src/app/core/auth/auth-request.service.ts @@ -100,14 +100,12 @@ export abstract class AuthRequestService { ); } /** - * Factory function to create the request object to send. This needs to be a POST client side and - * a GET server side. Due to CSRF validation, the server isn't allowed to send a POST, so we allow - * only the server IP to send a GET to this endpoint. + * Factory function to create the request object to send. * * @param href The href to send the request to * @protected */ - protected abstract createShortLivedTokenRequest(href: string): GetRequest | PostRequest; + protected abstract createShortLivedTokenRequest(href: string): Observable; /** * Send a request to retrieve a short-lived token which provides download access of restricted files @@ -117,7 +115,7 @@ export abstract class AuthRequestService { filter((href: string) => isNotEmpty(href)), distinctUntilChanged(), map((href: string) => new URLCombiner(href, this.shortlivedtokensEndpoint).toString()), - map((endpointURL: string) => this.createShortLivedTokenRequest(endpointURL)), + switchMap((endpointURL: string) => this.createShortLivedTokenRequest(endpointURL)), tap((request: RestRequest) => this.requestService.send(request)), switchMap((request: RestRequest) => this.rdbService.buildFromRequestUUID(request.uuid)), getFirstCompletedRemoteData(), diff --git a/src/app/core/auth/browser-auth-request.service.ts b/src/app/core/auth/browser-auth-request.service.ts index 85d5f54340..485e2ef9c4 100644 --- a/src/app/core/auth/browser-auth-request.service.ts +++ b/src/app/core/auth/browser-auth-request.service.ts @@ -4,6 +4,7 @@ import { PostRequest } from '../data/request.models'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { RequestService } from '../data/request.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { Observable, of as observableOf } from 'rxjs'; /** * Client side version of the service to send authentication requests @@ -20,15 +21,13 @@ export class BrowserAuthRequestService extends AuthRequestService { } /** - * Factory function to create the request object to send. This needs to be a POST client side and - * a GET server side. Due to CSRF validation, the server isn't allowed to send a POST, so we allow - * only the server IP to send a GET to this endpoint. + * Factory function to create the request object to send. * * @param href The href to send the request to * @protected */ - protected createShortLivedTokenRequest(href: string): PostRequest { - return new PostRequest(this.requestService.generateRequestId(), href); + protected createShortLivedTokenRequest(href: string): Observable { + return observableOf(new PostRequest(this.requestService.generateRequestId(), href)); } } diff --git a/src/app/core/auth/server-auth-request.service.ts b/src/app/core/auth/server-auth-request.service.ts index 9954e7c7ef..05131b7375 100644 --- a/src/app/core/auth/server-auth-request.service.ts +++ b/src/app/core/auth/server-auth-request.service.ts @@ -4,8 +4,19 @@ import { PostRequest } from '../data/request.models'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { RequestService } from '../data/request.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { HttpHeaders, HttpXsrfTokenExtractor } from '@angular/common/http'; -import { XSRF_REQUEST_HEADER } from '../xsrf/xsrf.interceptor'; +import { + HttpHeaders, + HttpXsrfTokenExtractor, + HttpClient, + HttpResponse +} from '@angular/common/http'; +import { + XSRF_REQUEST_HEADER, + XSRF_RESPONSE_HEADER, + DSPACE_XSRF_COOKIE +} from '../xsrf/xsrf.interceptor'; +import { map } from 'rxjs/operators'; +import { Observable } from 'rxjs'; /** * Server side version of the service to send authentication requests @@ -17,29 +28,40 @@ export class ServerAuthRequestService extends AuthRequestService { halService: HALEndpointService, requestService: RequestService, rdbService: RemoteDataBuildService, - protected tokenExtractor: HttpXsrfTokenExtractor, + protected httpClient: HttpClient, ) { super(halService, requestService, rdbService); } /** - * Factory function to create the request object to send. This needs to be a POST client side and - * a GET server side. Due to CSRF validation, the server isn't allowed to send a POST, so we allow - * only the server IP to send a GET to this endpoint. + * Factory function to create the request object to send. * * @param href The href to send the request to * @protected */ - protected createShortLivedTokenRequest(href: string): PostRequest { - let options = new HttpHeaders(); - options = options.set('Content-Type', 'application/json; charset=utf-8'); - options = options.set(XSRF_REQUEST_HEADER, this.tokenExtractor.getToken()); - let requestOptions = { - headers: options, - }; - return Object.assign(new PostRequest(this.requestService.generateRequestId(), href, {}, requestOptions), { - responseMsToLive: 2 * 1000 // A short lived token is only valid for 2 seconds. - }); + protected createShortLivedTokenRequest(href: string): Observable { + // First do a call to the root endpoint in order to get an XSRF token + return this.httpClient.get(this.halService.getRootHref(), { observe: 'response' }).pipe( + // retrieve the XSRF token from the response header + map((response: HttpResponse) => response.headers.get(XSRF_RESPONSE_HEADER)), + // Use that token to create an HttpHeaders object + map((xsrfToken: string) => new HttpHeaders() + .set('Content-Type', 'application/json; charset=utf-8') + // set the token as the XSRF header + .set(XSRF_REQUEST_HEADER, xsrfToken) + // and as the DSPACE-XSRF-COOKIE + .set('Cookie', `${DSPACE_XSRF_COOKIE}=${xsrfToken}`)), + map((headers: HttpHeaders) => + // Create a new PostRequest using those headers and the given href + new PostRequest( + this.requestService.generateRequestId(), + href, + {}, + { + headers: headers, + } + )) + ) } } diff --git a/src/app/core/services/server-xhr.service.ts b/src/app/core/services/server-xhr.service.ts new file mode 100644 index 0000000000..835072bbd3 --- /dev/null +++ b/src/app/core/services/server-xhr.service.ts @@ -0,0 +1,16 @@ +import { XhrFactory } from '@angular/common'; +import { Injectable } from '@angular/core'; +import * as xhr2 from 'xhr2'; + +/** + * Overrides the default XhrFactoru server side, to allow us to set cookies in requests to the + * backend. This was added to be able to perform a working XSRF request from the node server, as it + * needs to set a cookie for the XSRF token + */ +@Injectable() +export class ServerXhrService implements XhrFactory { + build(): XMLHttpRequest { + xhr2.prototype._restrictedHeaders.cookie = false; + return new xhr2.XMLHttpRequest(); + } +} diff --git a/src/app/core/xsrf/xsrf.interceptor.ts b/src/app/core/xsrf/xsrf.interceptor.ts index d527924a28..cded432397 100644 --- a/src/app/core/xsrf/xsrf.interceptor.ts +++ b/src/app/core/xsrf/xsrf.interceptor.ts @@ -19,6 +19,8 @@ export const XSRF_REQUEST_HEADER = 'X-XSRF-TOKEN'; export const XSRF_RESPONSE_HEADER = 'DSPACE-XSRF-TOKEN'; // Name of cookie where we store the XSRF token export const XSRF_COOKIE = 'XSRF-TOKEN'; +// Name of cookie the backend expects the XSRF token to be in +export const DSPACE_XSRF_COOKIE = 'DSPACE-XSRF-COOKIE'; /** * Custom Http Interceptor intercepting Http Requests & Responses to diff --git a/src/modules/app/server-app.module.ts b/src/modules/app/server-app.module.ts index 81426e7fcc..7d162c5fd1 100644 --- a/src/modules/app/server-app.module.ts +++ b/src/modules/app/server-app.module.ts @@ -33,6 +33,8 @@ import { Angulartics2Mock } from '../../app/shared/mocks/angulartics2.service.mo import { AuthRequestService } from '../../app/core/auth/auth-request.service'; import { ServerAuthRequestService } from '../../app/core/auth/server-auth-request.service'; import { ServerInitService } from './server-init.service'; +import { XhrFactory } from '@angular/common'; +import { ServerXhrService } from '../../app/core/services/server-xhr.service'; export function createTranslateLoader(transferState: TransferState) { return new TranslateServerLoader(transferState, 'dist/server/assets/i18n/', '.json'); @@ -104,6 +106,10 @@ export function createTranslateLoader(transferState: TransferState) { provide: HardRedirectService, useClass: ServerHardRedirectService, }, + { + provide: XhrFactory, + useClass: ServerXhrService, + }, ] }) export class ServerAppModule { From ce6324a569e6ecde23b49ab4eca9a4e5b1229248 Mon Sep 17 00:00:00 2001 From: Nathan Buckingham Date: Tue, 7 Feb 2023 11:50:42 -0500 Subject: [PATCH 4/5] Fix lint and test issues --- .../core/auth/auth-request.service.spec.ts | 5 +- .../auth/browser-auth-request.service.spec.ts | 14 ++++-- .../auth/server-auth-request.service.spec.ts | 50 ++++++++++++------- .../core/auth/server-auth-request.service.ts | 10 ++-- src/app/core/services/server-xhr.service.ts | 8 +-- 5 files changed, 55 insertions(+), 32 deletions(-) diff --git a/src/app/core/auth/auth-request.service.spec.ts b/src/app/core/auth/auth-request.service.spec.ts index 704922c5b5..063aad612f 100644 --- a/src/app/core/auth/auth-request.service.spec.ts +++ b/src/app/core/auth/auth-request.service.spec.ts @@ -11,6 +11,7 @@ import { HttpOptions } from '../dspace-rest/dspace-rest.service'; import objectContaining = jasmine.objectContaining; import { AuthStatus } from './models/auth-status.model'; import { RestRequestMethod } from '../data/rest-request-method'; +import { Observable, of as observableOf } from 'rxjs'; describe(`AuthRequestService`, () => { let halService: HALEndpointService; @@ -34,8 +35,8 @@ describe(`AuthRequestService`, () => { super(hes, rs, rdbs); } - protected createShortLivedTokenRequest(href: string): PostRequest { - return new PostRequest(this.requestService.generateRequestId(), href); + protected createShortLivedTokenRequest(href: string): Observable { + return observableOf(new PostRequest(this.requestService.generateRequestId(), href)); } } diff --git a/src/app/core/auth/browser-auth-request.service.spec.ts b/src/app/core/auth/browser-auth-request.service.spec.ts index 18d27340af..2875553feb 100644 --- a/src/app/core/auth/browser-auth-request.service.spec.ts +++ b/src/app/core/auth/browser-auth-request.service.spec.ts @@ -1,6 +1,8 @@ import { AuthRequestService } from './auth-request.service'; import { RequestService } from '../data/request.service'; import { BrowserAuthRequestService } from './browser-auth-request.service'; +import { Observable } from 'rxjs'; +import { PostRequest } from '../data/request.models'; describe(`BrowserAuthRequestService`, () => { let href: string; @@ -17,13 +19,17 @@ describe(`BrowserAuthRequestService`, () => { describe(`createShortLivedTokenRequest`, () => { it(`should return a PostRequest`, () => { - const result = (service as any).createShortLivedTokenRequest(href); - expect(result.constructor.name).toBe('PostRequest'); + const obs = (service as any).createShortLivedTokenRequest(href) as Observable; + obs.subscribe((result: PostRequest) => { + expect(result.constructor.name).toBe('PostRequest'); + }); }); it(`should return a request with the given href`, () => { - const result = (service as any).createShortLivedTokenRequest(href); - expect(result.href).toBe(href) ; + const obs = (service as any).createShortLivedTokenRequest(href) as Observable; + obs.subscribe((result: PostRequest) => { + expect(result.href).toBe(href); + }); }); }); }); diff --git a/src/app/core/auth/server-auth-request.service.spec.ts b/src/app/core/auth/server-auth-request.service.spec.ts index 2612f9d5b4..181603eef7 100644 --- a/src/app/core/auth/server-auth-request.service.spec.ts +++ b/src/app/core/auth/server-auth-request.service.spec.ts @@ -1,44 +1,60 @@ import { AuthRequestService } from './auth-request.service'; import { RequestService } from '../data/request.service'; import { ServerAuthRequestService } from './server-auth-request.service'; -import { HttpXsrfTokenExtractorMock } from '../../shared/mocks/http-xsrf-token-extractor.mock'; +import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http'; +import { Observable, of as observableOf } from 'rxjs'; +import { XSRF_RESPONSE_HEADER } from '../xsrf/xsrf.interceptor'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { PostRequest } from '../data/request.models'; describe(`ServerAuthRequestService`, () => { let href: string; let requestService: RequestService; let service: AuthRequestService; - let xsrfExtractor: HttpXsrfTokenExtractorMock; - - const mockToken = 'mockToken'; + let httpClient: HttpClient; + let httpResponse: HttpResponse; + let halService: HALEndpointService; + const mockToken = 'mock-token'; beforeEach(() => { href = 'https://rest.api/auth/shortlivedtokens'; requestService = jasmine.createSpyObj('requestService', { 'generateRequestId': '8bb0582d-5013-4337-af9c-763beb25aae2' }); - xsrfExtractor = new HttpXsrfTokenExtractorMock(mockToken); - service = new ServerAuthRequestService(null, requestService, null, xsrfExtractor); + httpResponse = { + body: { bar: false }, + headers: new HttpHeaders({ XSRF_RESPONSE_HEADER: mockToken }), + statusText: '200' + } as HttpResponse; + httpClient = jasmine.createSpyObj('httpClient', { + get: observableOf(httpResponse), + }); + halService = jasmine.createSpyObj('halService', { + 'getRootHref': '/api' + }); + service = new ServerAuthRequestService(halService, requestService, null, httpClient); }); describe(`createShortLivedTokenRequest`, () => { it(`should return a PostRequest`, () => { - const result = (service as any).createShortLivedTokenRequest(href); - expect(result.constructor.name).toBe('PostRequest'); + const obs = (service as any).createShortLivedTokenRequest(href) as Observable; + obs.subscribe((result: PostRequest) => { + expect(result.constructor.name).toBe('PostRequest'); + }); }); it(`should return a request with the given href`, () => { - const result = (service as any).createShortLivedTokenRequest(href); - expect(result.href).toBe(href) ; + const obs = (service as any).createShortLivedTokenRequest(href) as Observable; + obs.subscribe((result: PostRequest) => { + expect(result.href).toBe(href) ; + }); }); it(`should return a request with a xsrf header`, () => { - const result = (service as any).createShortLivedTokenRequest(href); - expect(result.options.headers.get('X-XSRF-TOKEN')).toBe(mockToken); - }); - - it(`should have a responseMsToLive of 2 seconds`, () => { - const result = (service as any).createShortLivedTokenRequest(href); - expect(result.responseMsToLive).toBe(2 * 1000) ; + const obs = (service as any).createShortLivedTokenRequest(href) as Observable; + obs.subscribe((result: PostRequest) => { + expect(result.options.headers.get(XSRF_RESPONSE_HEADER)).toBe(mockToken); + }); }); }); }); diff --git a/src/app/core/auth/server-auth-request.service.ts b/src/app/core/auth/server-auth-request.service.ts index 05131b7375..183e085589 100644 --- a/src/app/core/auth/server-auth-request.service.ts +++ b/src/app/core/auth/server-auth-request.service.ts @@ -6,7 +6,6 @@ import { RequestService } from '../data/request.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { HttpHeaders, - HttpXsrfTokenExtractor, HttpClient, HttpResponse } from '@angular/common/http'; @@ -53,15 +52,16 @@ export class ServerAuthRequestService extends AuthRequestService { .set('Cookie', `${DSPACE_XSRF_COOKIE}=${xsrfToken}`)), map((headers: HttpHeaders) => // Create a new PostRequest using those headers and the given href - new PostRequest( + Object.assign(new PostRequest( this.requestService.generateRequestId(), href, {}, { headers: headers, - } - )) - ) + }, + ),{}) + ) + ); } } diff --git a/src/app/core/services/server-xhr.service.ts b/src/app/core/services/server-xhr.service.ts index 835072bbd3..69ae741402 100644 --- a/src/app/core/services/server-xhr.service.ts +++ b/src/app/core/services/server-xhr.service.ts @@ -1,16 +1,16 @@ import { XhrFactory } from '@angular/common'; import { Injectable } from '@angular/core'; -import * as xhr2 from 'xhr2'; +import { prototype, XMLHttpRequest } from 'xhr2'; /** - * Overrides the default XhrFactoru server side, to allow us to set cookies in requests to the + * Overrides the default XhrFactory server side, to allow us to set cookies in requests to the * backend. This was added to be able to perform a working XSRF request from the node server, as it * needs to set a cookie for the XSRF token */ @Injectable() export class ServerXhrService implements XhrFactory { build(): XMLHttpRequest { - xhr2.prototype._restrictedHeaders.cookie = false; - return new xhr2.XMLHttpRequest(); + prototype._restrictedHeaders.cookie = false; + return new XMLHttpRequest(); } } From 9435f1c4a73e7a3e3ce1e26619ce322c8839ab1c Mon Sep 17 00:00:00 2001 From: Nathan Buckingham Date: Tue, 7 Feb 2023 13:59:57 -0500 Subject: [PATCH 5/5] Add done() to async tests --- .../auth/browser-auth-request.service.spec.ts | 6 +++-- .../auth/server-auth-request.service.spec.ts | 22 +++++++++++++------ .../core/auth/server-auth-request.service.ts | 4 ++-- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/app/core/auth/browser-auth-request.service.spec.ts b/src/app/core/auth/browser-auth-request.service.spec.ts index 2875553feb..b41d981bcf 100644 --- a/src/app/core/auth/browser-auth-request.service.spec.ts +++ b/src/app/core/auth/browser-auth-request.service.spec.ts @@ -18,17 +18,19 @@ describe(`BrowserAuthRequestService`, () => { }); describe(`createShortLivedTokenRequest`, () => { - it(`should return a PostRequest`, () => { + it(`should return a PostRequest`, (done) => { const obs = (service as any).createShortLivedTokenRequest(href) as Observable; obs.subscribe((result: PostRequest) => { expect(result.constructor.name).toBe('PostRequest'); + done(); }); }); - it(`should return a request with the given href`, () => { + it(`should return a request with the given href`, (done) => { const obs = (service as any).createShortLivedTokenRequest(href) as Observable; obs.subscribe((result: PostRequest) => { expect(result.href).toBe(href); + done(); }); }); }); diff --git a/src/app/core/auth/server-auth-request.service.spec.ts b/src/app/core/auth/server-auth-request.service.spec.ts index 181603eef7..df6d78256b 100644 --- a/src/app/core/auth/server-auth-request.service.spec.ts +++ b/src/app/core/auth/server-auth-request.service.spec.ts @@ -3,9 +3,12 @@ import { RequestService } from '../data/request.service'; import { ServerAuthRequestService } from './server-auth-request.service'; import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http'; import { Observable, of as observableOf } from 'rxjs'; -import { XSRF_RESPONSE_HEADER } from '../xsrf/xsrf.interceptor'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { PostRequest } from '../data/request.models'; +import { + XSRF_REQUEST_HEADER, + XSRF_RESPONSE_HEADER +} from '../xsrf/xsrf.interceptor'; describe(`ServerAuthRequestService`, () => { let href: string; @@ -21,9 +24,11 @@ describe(`ServerAuthRequestService`, () => { requestService = jasmine.createSpyObj('requestService', { 'generateRequestId': '8bb0582d-5013-4337-af9c-763beb25aae2' }); + let headers = new HttpHeaders(); + headers = headers.set(XSRF_RESPONSE_HEADER, mockToken); httpResponse = { body: { bar: false }, - headers: new HttpHeaders({ XSRF_RESPONSE_HEADER: mockToken }), + headers: headers, statusText: '200' } as HttpResponse; httpClient = jasmine.createSpyObj('httpClient', { @@ -36,24 +41,27 @@ describe(`ServerAuthRequestService`, () => { }); describe(`createShortLivedTokenRequest`, () => { - it(`should return a PostRequest`, () => { + it(`should return a PostRequest`, (done) => { const obs = (service as any).createShortLivedTokenRequest(href) as Observable; obs.subscribe((result: PostRequest) => { expect(result.constructor.name).toBe('PostRequest'); + done(); }); }); - it(`should return a request with the given href`, () => { + it(`should return a request with the given href`, (done) => { const obs = (service as any).createShortLivedTokenRequest(href) as Observable; obs.subscribe((result: PostRequest) => { - expect(result.href).toBe(href) ; + expect(result.href).toBe(href); + done(); }); }); - it(`should return a request with a xsrf header`, () => { + it(`should return a request with a xsrf header`, (done) => { const obs = (service as any).createShortLivedTokenRequest(href) as Observable; obs.subscribe((result: PostRequest) => { - expect(result.options.headers.get(XSRF_RESPONSE_HEADER)).toBe(mockToken); + expect(result.options.headers.get(XSRF_REQUEST_HEADER)).toBe(mockToken); + done(); }); }); }); diff --git a/src/app/core/auth/server-auth-request.service.ts b/src/app/core/auth/server-auth-request.service.ts index 183e085589..d6302081bc 100644 --- a/src/app/core/auth/server-auth-request.service.ts +++ b/src/app/core/auth/server-auth-request.service.ts @@ -52,14 +52,14 @@ export class ServerAuthRequestService extends AuthRequestService { .set('Cookie', `${DSPACE_XSRF_COOKIE}=${xsrfToken}`)), map((headers: HttpHeaders) => // Create a new PostRequest using those headers and the given href - Object.assign(new PostRequest( + new PostRequest( this.requestService.generateRequestId(), href, {}, { headers: headers, }, - ),{}) + ) ) ); }