Skip to content

Replace black and whitelist references #668

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const isExpired = helper.isTokenExpired(myRawToken);

## Usage: Injection

Import the `JwtModule` module and add it to your imports list. Call the `forRoot` method and provide a `tokenGetter` function. You must also whitelist any domains that you want to make requests to by specifying a `whitelistedDomains` array.
Import the `JwtModule` module and add it to your imports list. Call the `forRoot` method and provide a `tokenGetter` function. You must also add any domains to the `allowedDomains`, that you want to make requests to by specifying an `allowedDomains` array.

Be sure to import the `HttpClientModule` as well.

Expand All @@ -60,8 +60,8 @@ export function tokenGetter() {
JwtModule.forRoot({
config: {
tokenGetter: tokenGetter,
whitelistedDomains: ["example.com"],
blacklistedRoutes: ["http://example.com/examplebadroute/"],
allowedDomains: ["example.com"],
disallowedRoutes: ["http://example.com/examplebadroute/"],
},
}),
],
Expand Down Expand Up @@ -122,33 +122,33 @@ JwtModule.forRoot({
});
```

### `whitelistedDomains: array`
### `allowedDomains: array`

Authenticated requests should only be sent to domains you know and trust. Many applications make requests to APIs from multiple domains, some of which are not controlled by the developer. Since there is no way to know what the API being called will do with the information contained in the request, it is best to not send the user's token to all APIs in a blind fashion.

List any domains you wish to allow authenticated requests to be sent to by specifying them in the `whitelistedDomains` array. **Note that standard http port 80 and https port 443 requests don't require a port to be specified. A port is only required in the whitelisted host name if you are authenticating against a non-standard port e.g. localhost:3001**
List any domains you wish to allow authenticated requests to be sent to by specifying them in the `allowedDomains` array. **Note that standard http port 80 and https port 443 requests don't require a port to be specified. A port is only required in the allowed domains host name if you are authenticating against a non-standard port e.g. localhost:3001**

```ts
// ...
JwtModule.forRoot({
config: {
// ...
whitelistedDomains: ["localhost:3001", "foo.com", "bar.com"],
allowedDomains: ["localhost:3001", "foo.com", "bar.com"],
},
});
```

### `blacklistedRoutes: array`
### `disallowedRoutes: array`

If you do not want to replace the authorization headers for specific routes, list them here. This can be useful if your
initial auth route(s) are on a whitelisted domain and take basic auth headers. These routes need to be prefixed with the correct protocol (`http://`, `https://`). If you want to blacklist the route regardless of the protocol, you can prefix it with `//`.
initial auth route(s) are on an allowed domain and take basic auth headers. These routes need to be prefixed with the correct protocol (`http://`, `https://`). If you want to add a route to the list of disallowed routes regardless of the protocol, you can prefix it with `//`.

```ts
// ...
JwtModule.forRoot({
config: {
// ...
blacklistedRoutes: [
disallowedRoutes: [
"http://localhost:3001/auth/",
"https://foo.com/bar/",
"//foo.com/bar/baz",
Expand All @@ -158,21 +158,21 @@ JwtModule.forRoot({
});
```

**Note:** If requests are sent to the same domain that is serving your Angular application, you do not need to add that domain to the `whitelistedDomains` array. However, this is only the case if you don't specify the domain in the `Http` request.
**Note:** If requests are sent to the same domain that is serving your Angular application, you do not need to add that domain to the `allowedDomains` array. However, this is only the case if you don't specify the domain in the `Http` request.

For example, the following request assumes that the domain is the same as the one serving your app. It doesn't need to be whitelisted in this case.
For example, the following request assumes that the domain is the same as the one serving your app. It doesn't need to be allowed in this case.

```ts
this.http.get('/api/things')
.subscribe(...)
```

However, if you are serving your API at the same domain as that which is serving your Angular app **and** you are specifying that domain in `Http` requests, then it **does** need to be whitelisted.
However, if you are serving your API at the same domain as that which is serving your Angular app **and** you are specifying that domain in `Http` requests, then it **does** need to be explicitely allowed.

```ts
// Both the Angular app and the API are served at
// localhost:4200 but because that domain is specified
// in the request, it must be whitelisted
// in the request, it must be allowed
this.http.get('http://localhost:4200/api/things')
.subscribe(...)
```
Expand Down Expand Up @@ -213,7 +213,7 @@ JwtModule.forRoot({
config: {
// ...
authScheme: (request) => {
if (request.url.includes("foo")) {
if (request.url.includes("foo")) {
return "Basic ";
}

Expand Down Expand Up @@ -270,7 +270,7 @@ export function jwtOptionsFactory(tokenService) {
tokenGetter: () => {
return tokenService.getAsyncToken();
},
whitelistedDomains: ["example.com"]
allowedDomains: ["example.com"]
}
}

Expand Down Expand Up @@ -306,7 +306,7 @@ export function jwtOptionsFactory(storage) {
tokenGetter: () => {
return storage.get('access_token');
},
whitelistedDomains: ["example.com"]
allowedDomains: ["example.com"]
}
}

Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"release": "np",
"release:preview": "np --preview ",
"release:dry": "np --no-publish"
"release": "np --contents ./dist/angular-jwt/ --any-branch",
"release:preview": "np --preview --contents ./dist/angular-jwt/ --any-branch",
"release:dry": "np --no-publish --contents ./dist/angular-jwt/ --any-branch"
},
"private": false,
"dependencies": {
Expand Down
8 changes: 4 additions & 4 deletions projects/angular-jwt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
],
"homepage": "https://github.com/auth0/angular2-jwt",
"peerDependencies": {
"@angular/common": ">=7.1.0"
"@angular/common": ">=9.0.0"
},
"dependencies": {
"tslib": "^2.0.0"
}
"dependencies": {
"tslib": "^2.0.0"
}
}
6 changes: 3 additions & 3 deletions projects/angular-jwt/src/lib/angular-jwt.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ export interface JwtConfig {
) => string | null | Promise<string | null>;
headerName?: string;
authScheme?: string | ((request?: HttpRequest<any>) => string);
whitelistedDomains?: Array<string | RegExp>;
blacklistedRoutes?: Array<string | RegExp>;
allowedDomains?: Array<string | RegExp>;
disallowedRoutes?: Array<string | RegExp>;
throwNoTokenError?: boolean;
skipWhenExpired?: boolean;
};
}

export interface JwtModuleOptions {
jwtOptionsProvider?: Provider;
Expand Down
25 changes: 11 additions & 14 deletions projects/angular-jwt/src/lib/jwt.interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ export class JwtInterceptor implements HttpInterceptor {
) => string | null | Promise<string | null>;
headerName: string;
authScheme: string | ((request?: HttpRequest<any>) => string);
whitelistedDomains: Array<string | RegExp>;
blacklistedRoutes: Array<string | RegExp>;
allowedDomains: Array<string | RegExp>;
disallowedRoutes: Array<string | RegExp>;
throwNoTokenError: boolean;
skipWhenExpired: boolean;
standardPorts: string[] = ["80", "443"];
Expand All @@ -34,30 +34,30 @@ export class JwtInterceptor implements HttpInterceptor {
config.authScheme || config.authScheme === ""
? config.authScheme
: "Bearer ";
this.whitelistedDomains = config.whitelistedDomains || [];
this.blacklistedRoutes = config.blacklistedRoutes || [];
this.allowedDomains = config.allowedDomains || [];
this.disallowedRoutes = config.disallowedRoutes || [];
this.throwNoTokenError = config.throwNoTokenError || false;
this.skipWhenExpired = config.skipWhenExpired;
}

isWhitelistedDomain(request: HttpRequest<any>): boolean {
isAllowedDomain(request: HttpRequest<any>): boolean {
const requestUrl: URL = new URL(request.url, window.location.origin);

// If the host equals the current window origin,
// the domain is whitelisted by default
// the domain is allowed by default
if (requestUrl.host === window.location.host) {
return true;
}

// If not the current domain, check the whitelist
// If not the current domain, check the allowed list
const hostName = `${requestUrl.hostname}${
requestUrl.port && !this.standardPorts.includes(requestUrl.port)
? ":" + requestUrl.port
: ""
}`;

return (
this.whitelistedDomains.findIndex((domain) =>
this.allowedDomains.findIndex((domain) =>
typeof domain === "string"
? domain === hostName
: domain instanceof RegExp
Expand All @@ -67,11 +67,11 @@ export class JwtInterceptor implements HttpInterceptor {
);
}

isBlacklistedRoute(request: HttpRequest<any>): boolean {
isDisallowedRoute(request: HttpRequest<any>): boolean {
const requestedUrl: URL = new URL(request.url, window.location.origin);

return (
this.blacklistedRoutes.findIndex((route: string | RegExp) => {
this.disallowedRoutes.findIndex((route: string | RegExp) => {
if (typeof route === "string") {
const parsedRoute: URL = new URL(route, window.location.origin);
return (
Expand Down Expand Up @@ -121,10 +121,7 @@ export class JwtInterceptor implements HttpInterceptor {
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
if (
!this.isWhitelistedDomain(request) ||
this.isBlacklistedRoute(request)
) {
if (!this.isAllowedDomain(request) || this.isDisallowedRoute(request)) {
return next.handle(request);
}
const token = this.tokenGetter(request);
Expand Down
50 changes: 21 additions & 29 deletions src/app/services/example-http.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,20 @@ describe("Example HttpService: with simple tokken getter", () => {

const validRoutes = [
`/assets/example-resource.json`,
`http://whitelisted.com/api/`,
`http://whitelisted.com/api/test`,
`http://whitelisted.com:443/api/test`,
`http://whitelisted-regex.com/api/`,
`https://whitelisted-regex.com/api/`,
`http://allowed.com/api/`,
`http://allowed.com/api/test`,
`http://allowed.com:443/api/test`,
`http://allowed-regex.com/api/`,
`https://allowed-regex.com/api/`,
`http://localhost:3000`,
`http://localhost:3000/api`,
];
const invalidRoutes = [
`http://whitelisted.com/api/blacklisted`,
`http://whitelisted.com/api/blacklisted-protocol`,
`http://whitelisted.com:80/api/blacklisted-protocol`,
`http://whitelisted.com/api/blacklisted-regex`,
`http://whitelisted-regex.com/api/blacklisted-regex`,
`http://allowed.com/api/disallowed`,
`http://allowed.com/api/disallowed-protocol`,
`http://allowed.com:80/api/disallowed-protocol`,
`http://allowed.com/api/disallowed-regex`,
`http://allowed-regex.com/api/disallowed-regex`,
`http://foo.com/bar`,
"http://localhost/api",
"http://localhost:4000/api",
Expand All @@ -54,15 +54,11 @@ describe("Example HttpService: with simple tokken getter", () => {
JwtModule.forRoot({
config: {
tokenGetter: tokenGetter,
whitelistedDomains: [
"whitelisted.com",
/whitelisted-regex*/,
"localhost:3000",
],
blacklistedRoutes: [
"http://whitelisted.com/api/blacklisted-protocol",
"//whitelisted.com/api/blacklisted",
/blacklisted-regex*/,
allowedDomains: ["allowed.com", /allowed-regex*/, "localhost:3000"],
disallowedRoutes: [
"http://allowed.com/api/disallowed-protocol",
"//allowed.com/api/disallowed",
/disallowed-regex*/,
],
},
}),
Expand All @@ -77,7 +73,7 @@ describe("Example HttpService: with simple tokken getter", () => {
});

validRoutes.forEach((route) =>
it(`should set the correct auth token for a whitelisted domain: ${route}`, () => {
it(`should set the correct auth token for a allowed domain: ${route}`, () => {
service.testRequest(route).subscribe((response) => {
expect(response).toBeTruthy();
});
Expand All @@ -92,7 +88,7 @@ describe("Example HttpService: with simple tokken getter", () => {
);

invalidRoutes.forEach((route) =>
it(`should not set the auth token for a blacklisted route: ${route}`, () => {
it(`should not set the auth token for a disallowed route: ${route}`, () => {
service.testRequest(route).subscribe((response) => {
expect(response).toBeTruthy();
});
Expand Down Expand Up @@ -120,11 +116,7 @@ describe("Example HttpService: with request based tokken getter", () => {
JwtModule.forRoot({
config: {
tokenGetter: tokenGetterWithRequest,
whitelistedDomains: [
"example-1.com",
"example-2.com",
"example-3.com",
],
allowedDomains: ["example-1.com", "example-2.com", "example-3.com"],
},
}),
],
Expand Down Expand Up @@ -175,7 +167,7 @@ authSchemes.forEach((scheme) => {
config: {
tokenGetter: tokenGetter,
authScheme: scheme[0],
whitelistedDomains: ["whitelisted.com"],
allowedDomains: ["allowed.com"],
},
}),
],
Expand All @@ -185,11 +177,11 @@ authSchemes.forEach((scheme) => {
});

it(`should set the correct auth scheme a request (${scheme[1]})`, () => {
service.testRequest("http://whitelisted.com").subscribe((response) => {
service.testRequest("http://allowed.com").subscribe((response) => {
expect(response).toBeTruthy();
});

const httpRequest = httpMock.expectOne("http://whitelisted.com");
const httpRequest = httpMock.expectOne("http://allowed.com");
expect(httpRequest.request.headers.has("Authorization")).toEqual(true);
expect(httpRequest.request.headers.get("Authorization")).toEqual(
`${scheme[1]}${tokenGetter()}`
Expand Down