71809: ForwardClientIpInterceptor

This commit is contained in:
Kristof De Langhe
2020-07-13 15:47:59 +02:00
parent 56d8a99c51
commit 0fa1e17078
4 changed files with 76 additions and 4 deletions

View File

@@ -27,9 +27,6 @@ export class ServerAuthService extends AuthService {
headers = headers.append('Accept', 'application/json');
headers = headers.append('Authorization', `Bearer ${token.accessToken}`);
// NB this is used to pass server client IP check.
const clientIp = this.req.get('x-forwarded-for') || this.req.connection.remoteAddress;
headers = headers.append('X-Forwarded-For', clientIp);
options.headers = headers;
return this.authRequestService.getRequest('status', options).pipe(

View File

@@ -0,0 +1,44 @@
import { ForwardClientIpInterceptor } from './forward-client-ip.interceptor';
import { DSpaceRESTv2Service } from '../dspace-rest-v2/dspace-rest-v2.service';
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HTTP_INTERCEPTORS, HttpRequest } from '@angular/common/http';
import { REQUEST } from '@nguniversal/express-engine/tokens';
describe('ForwardClientIpInterceptor', () => {
let service: DSpaceRESTv2Service;
let httpMock: HttpTestingController;
let requestUrl;
let clientIp;
beforeEach(() => {
requestUrl = 'test-url';
clientIp = '1.2.3.4';
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
DSpaceRESTv2Service,
{
provide: HTTP_INTERCEPTORS,
useClass: ForwardClientIpInterceptor,
multi: true,
},
{ provide: REQUEST, useValue: { get: () => undefined, connection: { remoteAddress: clientIp } }}
],
});
service = TestBed.get(DSpaceRESTv2Service);
httpMock = TestBed.get(HttpTestingController);
});
it('should add an X-Forwarded-For header matching the client\'s IP', () => {
service.get(requestUrl).subscribe((response) => {
expect(response).toBeTruthy();
});
const httpRequest = httpMock.expectOne(requestUrl);
expect(httpRequest.request.headers.get('X-Forwarded-For')).toEqual(clientIp);
});
});

View File

@@ -0,0 +1,23 @@
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Inject, Injectable } from '@angular/core';
import { Observable } from 'rxjs/internal/Observable';
import { REQUEST } from '@nguniversal/express-engine/tokens';
@Injectable()
/**
* Http Interceptor intercepting Http Requests, adding the client's IP to their X-Forwarded-For header
*/
export class ForwardClientIpInterceptor implements HttpInterceptor {
constructor(@Inject(REQUEST) protected req: any) {
}
/**
* Intercept http requests and add the client's IP to the X-Forwarded-For header
* @param httpRequest
* @param next
*/
intercept(httpRequest: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const clientIp = this.req.get('x-forwarded-for') || this.req.connection.remoteAddress;
return next.handle(httpRequest.clone({ setHeaders: { 'X-Forwarded-For': clientIp } }));
}
}

View File

@@ -25,6 +25,8 @@ import { ServerSubmissionService } from '../../app/submission/server-submission.
import { Angulartics2DSpace } from '../../app/statistics/angulartics/dspace-provider';
import { Angulartics2RouterlessModule } from 'angulartics2/routerlessmodule';
import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { ForwardClientIpInterceptor } from '../../app/core/forward-client-ip/forward-client-ip.interceptor';
export function createTranslateLoader() {
return new TranslateJson5UniversalLoader('dist/server/assets/i18n/', '.json5');
@@ -73,7 +75,13 @@ export function createTranslateLoader() {
{
provide: SubmissionService,
useClass: ServerSubmissionService
}
},
// register ForwardClientIpInterceptor as HttpInterceptor
{
provide: HTTP_INTERCEPTORS,
useClass: ForwardClientIpInterceptor,
multi: true
},
]
})
export class ServerAppModule {