Skip to content

Commit

Permalink
Remove Regex support from the HTTP interceptor (#29)
Browse files Browse the repository at this point in the history
* Remove regex support from Http Interceptor

* Reinstate tests that were no longer covered

* Remove redundant test

* Trim the route value before processing
  • Loading branch information
Steve Hobbs authored Aug 14, 2020
1 parent be26384 commit 0b86bc4
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 35 deletions.
16 changes: 11 additions & 5 deletions projects/auth0-angular/src/lib/auth.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ import { InjectionToken } from '@angular/core';
*
* - an object of type HttpInterceptorConfig
* - a string
* - a regular expression
*/
export type ApiRouteDefinition = HttpInterceptorRouteConfig | string | RegExp;
export type ApiRouteDefinition = HttpInterceptorRouteConfig | string;

/**
* A custom type guard to help identify route definitions that are actually HttpInterceptorRouteConfig types.
Expand All @@ -32,14 +31,21 @@ export interface HttpInterceptorConfig {
*/
export interface HttpInterceptorRouteConfig {
/**
* The URL to test, either by using a regex or by supplying the whole URL to match.
* If `test` is a match for the current request URL from the HTTP client, then
* The URL to test, by supplying the URL to match.
* If `test` is a match for the current request path from the HTTP client, then
* an access token is attached to the request in the
* ["Authorization" header](https://tools.ietf.org/html/draft-ietf-oauth-v2-bearer-20#section-2.1).
*
* If the test does not pass, the request proceeds without the access token attached.
*
* A wildcard character can be used to match only the start of the URL.
*
* @usagenotes
*
* '/api' - exactly match the route /api
* '/api/*' - match any route that starts with /api/
*/
uri: string | RegExp;
uri: string;

/**
* The options that are passed to the SDK when retrieving the
Expand Down
44 changes: 22 additions & 22 deletions projects/auth0-angular/src/lib/auth.interceptor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@ describe('The Auth HTTP Interceptor', () => {
'',
'/api/photos',
'/api/people*',
/^\/basic-api-regex/,
'https://my-api.com/orders',
{ uri: '/api/orders' },
{ uri: /^\/regex-api/ },
{
uri: '/api/addresses',
tokenOptions: {
Expand Down Expand Up @@ -107,39 +106,33 @@ describe('The Auth HTTP Interceptor', () => {
assertAuthorizedApiCallTo('/api/photos', done);
}));

it('attach the access token when the configuration uri is a regex', fakeAsync((
done
) => {
assertAuthorizedApiCallTo('/basic-api-regex?value=123', done);
}));

it('attach the access token when the configuration uri is a string with a wildcard', fakeAsync((
done
) => {
// Testing /api/people* (wildcard match)
assertAuthorizedApiCallTo('/api/people/profile', done);
}));
});

describe('Requests that are configured using a complex object', () => {
it('attach the access token when the uri is configured using a string', fakeAsync((
done
) => {
// Testing { uri: /api/addresses } (exact match)
assertAuthorizedApiCallTo('/api/addresses', done);
it('matches a full url to an API', fakeAsync((done) => {
// Testing 'https://my-api.com/orders' (exact)
assertAuthorizedApiCallTo('https://my-api.com/orders', done);
}));

it('attach the access token when the configuration uri is a string with a wildcard', fakeAsync((
done
) => {
// Testing { uri: /api/calendar* } (wildcard match)
assertAuthorizedApiCallTo('/api/calendar/events', done);
it('matches a URL that contains a query string', fakeAsync((done) => {
assertAuthorizedApiCallTo('/api/people?name=test', done);
}));

it('attach the access token when the uri is configured using a regex', fakeAsync((
it('matches a URL that contains a hash fragment', fakeAsync((done) => {
assertAuthorizedApiCallTo('/api/people#hash-fragment', done);
}));
});

describe('Requests that are configured using a complex object', () => {
it('attach the access token when the uri is configured using a string', fakeAsync((
done
) => {
assertAuthorizedApiCallTo('/regex-api?my-param=42', done);
// Testing { uri: /api/orders } (exact match)
assertAuthorizedApiCallTo('/api/orders', done);
}));

it('pass through the route options to getTokenSilently, without additional properties', fakeAsync((
Expand All @@ -153,5 +146,12 @@ describe('The Auth HTTP Interceptor', () => {
scope: 'scope',
});
}));

it('attach the access token when the configuration uri is a string with a wildcard', fakeAsync((
done
) => {
// Testing { uri: /api/calendar* } (wildcard match)
assertAuthorizedApiCallTo('/api/calendar/events', done);
}));
});
});
33 changes: 25 additions & 8 deletions projects/auth0-angular/src/lib/auth.interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,22 @@ export class AuthHttpInterceptor implements HttpInterceptor {
);
}

/**
* Strips the query and fragment from the given uri
* @param uri The uri to remove the query and fragment from
*/
private stripQueryFrom(uri: string): string {
if (uri.indexOf('?') > -1) {
uri = uri.substr(0, uri.indexOf('?'));
}

if (uri.indexOf('#') > -1) {
uri = uri.substr(0, uri.indexOf('#'));
}

return uri;
}

/**
* Determines whether the specified route can have an access token attached to it, based on matching the HTTP request against
* the interceptor route configuration.
Expand All @@ -72,34 +88,35 @@ export class AuthHttpInterceptor implements HttpInterceptor {
route: ApiRouteDefinition,
request: HttpRequest<any>
): boolean {
const testPrimitive = (value: string | RegExp) => {
const testPrimitive = (value: string) => {
if (value) {
value.trim();
}

if (!value) {
return false;
}

if (value === request.url) {
const requestPath = this.stripQueryFrom(request.url);

if (value === requestPath) {
return true;
}

// If the URL ends with an asterisk, match using startsWith.
if (
typeof value === 'string' &&
value.indexOf('*') === value.length - 1 &&
request.url.startsWith(value.substr(0, value.length - 1))
) {
return true;
}

if (value instanceof RegExp && value.test(request.url)) {
return true;
}
};

if (isHttpInterceptorRouteConfig(route)) {
return testPrimitive(route.uri);
}

return testPrimitive(route as string | RegExp);
return testPrimitive(route);
}

/**
Expand Down

0 comments on commit 0b86bc4

Please sign in to comment.