I'm implementing the JWT authntication in my Angular2 web applicaiton. However no requests are being dispatched when I try testing my "secure" API (which should be only accessible for validated requests).
it only throws an empty AuthHttpErrorobject. No requests are displayed in the either network tab (in my browser) nor I could see any request on server side.
I can access the url with the Http service, although I get errors on the backed side , which is expected behavior, since the Http service isn't sending the token as part of the request.
After successful log-in the user's token is stored as token in localStorage.
angular2-jwt (version) : 0.1.28
auth.module.ts
import { NgModule } from '@angular/core';
import { Http, RequestOptions } from '@angular/http';
import { AuthHttp, AuthConfig } from 'angular2-jwt';
function authHttpServiceFactory(http: Http, options: RequestOptions) {
return new AuthHttp(new AuthConfig({
tokenName: 'token',
tokenGetter: (() => sessionStorage.getItem('token')),
globalHeaders: [{'Content-Type':'application/json'}],
}), http, options);
}
@NgModule({
providers: [
{
provide: AuthHttp,
useFactory: authHttpServiceFactory,
deps: [Http, RequestOptions]
}
]
})
export class AuthModule {}
app.module.ts
.....
@NgModule({
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
HttpModule,
AppRoutingModule,
AuthModule
],
declarations: [
AppComponent,
HomeComponent,
LoginComponent,
],
providers: [ AuthGuard ],
bootstrap: [ AppComponent ]
})
secureAPI.service.ts
import { Injectable } from '@angular/core';
import { Http, Headers, Response } from '@angular/http';
import { AuthHttp } from 'angular2-jwt';
import 'rxjs/add/operator/toPromise';
@Injectable()
export class SecureAPI {
//private headers = new Headers({'Content-Type': 'application/json'});
private baseUrl = 'http://localhost:8000';
constructor( private http: Http, private authHttp: AuthHttp ) { }
getPrivateMsg(): void {
this.authHttp.get(`${this.baseUrl}/get/private/msg`)
.subscribe(
data => console.log(data),
err => console.log(err),
() => console.log('Request Complete')
);
}
}
home.component.ts
import { Component, OnInit } from '@angular/core';
import { JwtHelper } from 'angular2-jwt';
import { SecureAPI } from '../services/secureAPI.service';
@Component({
moduleId: module.id,
selector: 'home-panel',
templateUrl: '../templates/home.component.html',
styleUrls: [ '../styles/home.component.css' ],
providers: [ JwtHelper, SecureAPI ]
})
export class HomeComponent implements OnInit {
constructor (
private secureAPI: SecureAPI,
) {}
ngOnInit(): void {
//this.sessionAuthService.start();
}
public callAnonymousApi(): void {
}
public callSecuredApi(): void {
this.secureAPI.getPrivateMsg()
}
private onError( error: any ): void{
console.log(error);
}
public logout() {
///this.sessionAuthService.stop();
}
}
Are you calling the method this.callSecuredApi() anywhere?
I'm no expert by any means, so if my reply doesn't help, please be gentle. lol
yeah it's called from within my template , Which isn't included in my exmaple above. (just wanted to keep it simple.)
I did some more digging ...and it turned out that it's still using the default configuration.. it keeps trying to access the token with tokenName = 'id_token'. Which is wrong, cause in my configuration it's just tokenName='token'The configuration used in auth.module.ts isn't applied for some reason.
edit:
Tried it with default configuration ( token is now stored as id_token in localStorage , not as token), ... and everything started working all of a sudden. But still I'd like to know why is the custom configuration not applied.
You're using session storage:
tokenGetter: (() => sessionStorage.getItem('token')),
Just remove this line, it is not necessary (you're using local storage and are passing the token name)
Ok I think I know where I've made my mistake.. I have added the AuthModule into the AppModule's imports not to the providers property. Will do q quick test and let you know the result.
Sorry, I should have been more explicit.
Your config in the initial post looks like this:
function authHttpServiceFactory(http: Http, options: RequestOptions) {
return new AuthHttp(new AuthConfig({
tokenName: 'token',
tokenGetter: (() => sessionStorage.getItem('token')),
globalHeaders: [{'Content-Type':'application/json'}],
}), http, options);
}
and should look like this:
function authHttpServiceFactory(http: Http, options: RequestOptions) {
return new AuthHttp(new AuthConfig({
tokenName: 'token',
globalHeaders: [{'Content-Type':'application/json'}],
}), http, options);
}
or this:
function authHttpServiceFactory(http: Http, options: RequestOptions) {
return new AuthHttp(new AuthConfig({
tokenGetter: (() => localStorage.getItem('token')),
globalHeaders: [{'Content-Type':'application/json'}],
}), http, options);
}
note that if you specify a tokenGetter, tokenName is not used. If you specify only a token name, we make a function that amounts to () => localStorage.getItem(tokenName)
I think it's not the configuration itself that causing the issue. It has more to do with the actual AuthModule, which is not properly included in my project. The question is, do I only need to add the AuthModule into providers?
When I do so, it reports it's missing AuthHttp, AuthConf modules. Should those be defined in the AppModule as well ? or they need to be defined in the components where I make use of the secureService?
can anyone tell me whether the way I'm implementing the AuthModule in AppModule is correct or not?
Ok so it turns out that it does't work if I just import the AuthModule and add it to the providers.
If I do , it starts complaining about AuthHttpnot being in the providers,
then it requires to add the AuthConfigto the providers as well... and this is the point where I could not get through this error _"Can't resolve all parameters for AuthConfig"._
But if I defined the
function authHttpServiceFactory(http: Http, options: RequestOptions) {
return new AuthHttp(new AuthConfig({
tokenName: 'token',
//tokenGetter: (() => sessionStorage.getItem('token')),
globalHeaders: [{'Content-Type':'application/json'}],
}), http, options);
}
right above my AppModule class and then updated the providers with:
providers: [
AuthGuard,
{
provide: AuthHttp,
useFactory: authHttpServiceFactory,
deps: [Http, RequestOptions]
}
]
it now fianlly changes the configuration and works as expected. Same result with the provideAuth function.
You may find it necessary to export your factory function if you use AoT. :)
it's now in JIT ,not tested it in AOT yet
Good evening, hope you have solved your issue.
I encountered the same issue.
I noticed that an update of angular2-jwt lib changed the key of the token stored in localStorage.
With version 0.1.23, I used to keep it with "id_token". Once an http request was sent, the angular2-jwt used to get the token in this key and it sent the request.
After an upgrade to version 0.2.3, I could sent any secure request.
Storing the token in localStorage with the key "token" instead of "id_token" solved everything
Schim'
@Schim57300 This worked for me also - i was following the Auth0 documentation and once i chagned this key, the event dispatches
Most helpful comment
@Schim57300 This worked for me also - i was following the Auth0 documentation and once i chagned this key, the event dispatches