Upgraded from beta9 to 1.1.0 because #477 is fixed but, now something else seems to be broken.
I can't see the authorisation Bearer part anywhere in the header. I tried adding localhost to the whitelist, but that didn't help as well. Is something else changed?
+1
Repeating from #481 - If you leave the whitelist empty the isWhitelistedDomain method will _always_ return false. It will never match anything, and hence never send the authorization headers. (This is contrary to the documentation, which implies that having an empty whitelist will match local domain requests.) Furthermore, adding localhost won't work, because the domain for a domain-less request is null.
Workaround - If you use domain-less routes, the workaround is to add the null domain to the whitelist, which you can do through a RegExp. In other words, do this:
whitelistedDomains: [ /^null$/ ]
Got it to work. My main problem was importing multiple HttpClient instances over different lazy loaded modules...
@Starofall how did you work around the lazy loading of HttpClient?
As HttpClient is just loading a service and does not offer any components, we just have to import it once.
So I now load it only in the app.module.ts and searched through the project that no other instance was loaded. Then it worked
Is it me or the injection example in the documentation no longer works?
I'm importing the HttpClientModule in my app.module and the HttpClient in my services, I don't understand why are you importing it in the app.module.
@PartyArk whitelistedDomains: [ /^null$/ ] is a great workaround, but it only works with JiT-mode, AoT fails with 'Expression form not supported.' BTW, [new RegExp('^null$')] doesn't work as well.
@chenkie the possible solution for this is to return true for 'null' domain in isWhitelistedDomain method
(Sorry left an erroneous comment about using ngtools/webpack before)
@rt-gavrilov - it works for me using AOT, but that's because I'm using the jwtOptionsProvider and useFactory for my options factory - you're right injecting a literal array of RegExps directly into the config won't work through AOT.
However - you can try to declare both the Array and RegExp via initialization -
whitelistedDomains: new Array(new RegExp('^null$'))
It certainly compiles for me in AOT; perhaps you can confirm if it works as expected.
@PartyArk thanks, finally it works. you saved a lot of my time
Thanks both @PartyArk & @Starofall. These fixes are just what I needed!
@KarmaCop213 - I think @Starofall means import just a single instance of the HttpClientModule in the app.module (not the HttpClient), and then the HttpClient in the services. That's works for me anyway.
+1 Hope it will be fixed soon
same problem, added "whitelistedDomains: [ /^null$/ ]" and set every settings, doesnt add to headers Bearer access token:
export function tokenGetter() {
const tokens = JSON.parse(localStorage.getItem('auth-tokens'));
if (tokens) {
return tokens.access_token;
}
}
...
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
ReactiveFormsModule,
JwtModule.forRoot({
config: {
tokenGetter: tokenGetter,
whitelistedDomains: [ /^null$/ ]
}
}),
whitelistedDomains: new Array(new RegExp('^null$')) compiles but it doesn't work for me either (using serverless domains, serving Angular app from Spring Boot).
@borabilgin I have the same problem, I'm also using Spring Boot
I have same problem on v1.1.0 and none of provided solutions worked for me. Here is what I've done and still is not working for me:
...
import { JwtModule, JWT_OPTIONS } from '@auth0/angular-jwt';
...
export function jwtOptionsFactory() {
return {
tokenGetter: () => {
return localStorage.getItem('access_token');
},
whitelistedDomains: [ /^null$/ ]
}
}
...
@NgModule({
...
imports: [
...
JwtModule.forRoot({
jwtOptionsProvider: {
provide: JWT_OPTIONS,
useFactory: jwtOptionsFactory
}
}),
...
]
})
...
I have commited a pull request (#506) for this issue. Until it is merged, AOT users can use a jwtOptionsProvider with a null RegExp as workaround (see @SamAriafar's comment)
@SamAriafar Are you sure your problem is related to the whitelist? I cannot reproduce the error with your code.
Does my pull request fix your problem?
npm remove @auth0/angular-jwtnpm install --save @auth0/angular-jwt@git+https://github.com/flx-l/angular2-jwt.gitIf not, you could try to find the cause for your problem by adding some console.log calls to the JwtInterceptor.
@flx-l Your npm install command seems not installing the package at all. Anyways, I've put some console.log inside JwtInterceptor.prototype.isWhitelistedDomain function and it seems this function is not being called at all.
@flx-l your code does not work, typescript complains of missing files.
I have tried the following setups
1.
export function tokenGetter() {
return localStorage.getItem('rawJWT');
}
...
JwtModule.forRoot({
config: {
tokenGetter: tokenGetter,
whitelistedDomains: new Array(new RegExp('^null$'))
}
I have also tried this method with:
whitelistedDomains: [/^null$/]
I have also tried this setup:
2.
export function jwtOptionsFactory() {
return {
tokenGetter: () => {
return localStorage.getItem('rawJWT');
},
whitelistedDomains: new Array(new RegExp('^null$'))
};
}
...
JwtModule.forRoot({
jwtOptionsProvider: {
provide: JWT_OPTIONS,
useFactory: jwtOptionsFactory
}
}),
I have also tried this method with:
whitelistedDomains: [/^null$/]
I tried down grading to 1.0.9-beta9 and this isn't working either, this is how I am constructing a request ..
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { SetScheduleSummary } from '../_models/index';
import { API_URL } from '../app.const';
@Injectable()
export class ScheduleService {
private summaryURL = API_URL + '/planning/set_scheudle_summary';
constructor (private http: HttpClient) {}
getSummary (planningDate) {
return this.http.post<SetScheduleSummary[]>(this.summaryURL,
JSON.stringify({ planningDate: planningDate}));
}
}
This is what my request headers look like:
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en;q=0.5
Connection: keep-alive
Content-Length: 49
Content-Type: text/plain
Host: localhost:6543
Origin: http://localhost:4200
Referer: http://localhost:4200/view_schedule
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0
Note, I do have this working with other projects, but not sure what is different here.
UPDATE: If I remove the domain from my request and just do like the below (e.g. pretend to fetch a local API call on the same location as the angular app, it submits the JWT, so it is obviously a whitelisting issue, however none of the aforementioned solutions seem to work.
Using the config:
export function tokenGetter() {
return localStorage.getItem('rawJWT');
}
...
JwtModule.forRoot({
config: {
tokenGetter: tokenGetter,
whitelistedDomains: [/^null$/]
}
}),
```typescript
@Injectable()
export class ScheduleService {
private summaryURL = '/planning/set_scheudle_summary';
constructor (private http: HttpClient) {}
getSummary (planningDate) {
return this.http.post
}
}
Seeing as how this library can sometimes be buggy, I decided to write my own HTTP_INTERCEPTOR, very easy, simply replace 'rawJWT' with the location of your JWT from local storage.:
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class JwtHttpInterceptor implements HttpInterceptor {
constructor() {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const token = localStorage.getItem('rawJWT');
let clone: HttpRequest<any>;
if (token) {
clone = request.clone({
setHeaders: {
Accept: `application/json`,
'Content-Type': `application/json`,
Authorization: `Bearer ${token}`
}
});
} else {
clone = request.clone({
setHeaders: {
Accept: `application/json`,
'Content-Type': `application/json`
}
});
}
return next.handle(clone);
}
}
Then in app.module.ts (note you have to import the above first as normal)
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: JwtHttpInterceptor, multi: true },
This library is great for decoding JWT's but this is not the first time an update has broken the code, so with this easy code I can control how and where my JWT gets sent
Is somebody fixes this issue, I have the same problem :(
@vozgorkov see my above example, this will add your JWT to every request if present, simply extend it to only offer to certain domains if you require this feature.
Thank you. Your example works perfectly.
Thanx @crooksey your code fixed the issue!
Ill send a pull request to add this code to the documentation, as it is useful if you do not want to use the library to manage your JWT sending.
for anyone needing an ionic-storage (which needs to fetch the stored token from a promise) compatible fix:
jwt-interceptor.ts
import { Storage } from '@ionic/storage';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/fromPromise';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';
@Injectable()
export class JwtHttpInterceptor implements HttpInterceptor {
constructor(public storage: Storage) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return Observable.fromPromise(this.storage.get('access_token')).mergeMap(token => {
console.log('TOKEN -> ', token)
let clone: HttpRequest<any>;
if (token) {
clone = request.clone({
setHeaders: {
Accept: `application/json`,
'Content-Type': `application/json`,
'X-Access-Token': token
}
});
} else {
clone = request.clone({
setHeaders: {
Accept: `application/json`,
'Content-Type': `application/json`
}
});
}
return next.handle(clone);
})
}
}
app.module.ts
```
import { JwtHttpInterceptor } from './../interceptors/jwt-interceptor';
import { HttpClient, HttpClientModule, HttpInterceptor, HTTP_INTERCEPTORS } from '@angular/common/http';
...
providers: [
...
{ provide: HTTP_INTERCEPTORS, useClass: JwtHttpInterceptor, multi: true },
...
]
````
Note: I'm using X-Access-Token instead of Authorization: Bearer TOKEN just FYI
I had the same problem and solved this with whitelistedDomains:
I was using:
whitelistedDomains: ["https://api.mydomain.com/api/v1"] and it was not working
I changed it to
whitelistedDomains: ["api.mydomain.com"] *without "https://" and "/api/ v1" * that way it works!
I too had the same problem and @rafaelzmt solution worked for me. I was managed to get it work for localhost.
Earlier :
whitelistedDomains: ['http://localhost:8080/api']
Now:
whitelistedDomains: ['localhost:8080']
Even though it works for something like whitelistedDomains: ['localhost:8080'], it does not help when the HTTP calls are made to URLs like '/api/resources'. This is usually the case when self-contained-sytems UIs call their very own backend. My wish would be that the access token would be provided on any HTTP call if the whitelistedDomains are undefined (or an empty array)
@badre429 Auth0 provide and maintain this code for free, if you don't like it, roll your own version. Your attitude towards open source software is disgusting.
I have posted a working fix/workaround above.
I don't understand why simple and critical bugs are not fixed after weeks.... this makes this library unusable.
A simple fix would be sth like that:
JwtInterceptor.prototype.isWhitelistedDomain = function (request) {
var requestUrl = URL.parse(request.url, false, true);
return (this.whitelistedDomains.findIndex(function (domain) {
if (typeof domain === 'string' || domain === null) {
if (domain === 'localhost' && requestUrl.host === null) {
return true;
} else {
return domain === requestUrl.host;
}
} else if (domain instanceof RegExp) {
return domain.test(requestUrl.host);
} else {
return false
}
}) > -1);
};
so whitelistedDomains: ['localhost', ...]orwhitelistedDomains: [null, ...]would be valid for requests with relative urls.
@crooksey You're my hero!!!
la configuracion de la documentacion no se ejecuta. alguien tiene un ejemplo implementado
@crooksey I can control how and where my JWT gets sent
I was wondering how you are controlling "where" the JWT is getting sent? How can i whitelist domains?
@crooksey your solution works on my PC but fails on AWS, maybe AWS doesn't allow local storage?
For some reason I had to restart the CLI...
@chenkie or @joshcanhelp please update the documentation, I really had to use { provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true } for this to work, spent to much time and almost dropped the library for giving such a hard time on integrating this (if this project is still maintained anyway). Also make the whitelistedDomains option is optional, as it is unclear if this causes the library not to provide the bearer token with each request. The idea is nice when I would be targeting multiple endpoints but for the sake of 'getting started' it's really annoying (include protocol or not, specific sub urls, etc.)
@crooksey
Did your implementation, worked like a charm, I also had the same problem, it did not have any issues with my other project but did not worked on my new projects, could this be an Angular version problem?
same issue with patch request
Most helpful comment
Seeing as how this library can sometimes be buggy, I decided to write my own HTTP_INTERCEPTOR, very easy, simply replace 'rawJWT' with the location of your JWT from local storage.:
Then in app.module.ts (note you have to import the above first as normal)
This library is great for decoding JWT's but this is not the first time an update has broken the code, so with this easy code I can control how and where my JWT gets sent