globox
globox

Reputation: 13

Angular2-jwt, getting empty errors in GET/POST responses when there is no JWT Token

I'm implementing the following tutorial in order to get some Angular basics: http://jasonwatmore.com/post/2016/08/16/angular-2-jwt-authentication-example-tutorial

And in addition I actually want to use "angular2-jwt" library. But every GET or POST request I send with authHttp is failing with just an empty error in console if there is no JWT saved locally.
"Error: Error in login.component.html caused by:"

There is no "No JWT present or has expired" error text, nothing.
By the way, standard Http Class is working normally. And so is "tokenNotExpired()" method.
Also tried adding

'js-base64':'npm:js-base64/base64.js',
'buffer':'@empty'

to mapping information of my systemsjs.config.js, but still no result.

Got any ideas what am I doing wrong? :(

Angular 2.1.0 + angular2-jwt 0.1.25

app.module.ts

import {NgModule} from "@angular/core";
import {BrowserModule} from "@angular/platform-browser";
import {FormsModule} from "@angular/forms";
import {HttpModule} from "@angular/http";
import {AppComponent} from "./app.component";
import {AppRoutingModule} from "./app-routing.module";
import {LoginComponent} from "./login/login.component";
import {MainComponent} from "./main/main.component";
import {AuthService} from "./services/auth.service";
import {AUTH_PROVIDERS} from "angular2-jwt";

@NgModule({
    imports: [
        BrowserModule,
        AppRoutingModule,
        FormsModule,
        HttpModule
    ],
    declarations: [
        AppComponent,
        LoginComponent,
        MainComponent
    ],
    providers: [
        AuthService,
        AUTH_PROVIDERS
    ],
    bootstrap: [AppComponent]
})
export class AppModule
{
}

login.component.ts

import { Component } from '@angular/core';
import { AuthService } from "../services/auth.service";

@Component({
    moduleId: module.id,
    templateUrl: 'login.component.html'
})

export class LoginComponent {

    user: any = {
        login: 'defaultLogin',
        password: 'defaultPassword'
    };
    errorMsg = '';

    constructor(
        private authService: AuthService) { }


    login() {
        this.authService.login(this.user.name, this.user.password)
            .subscribe(result => {

            });
    }
}

auth.service.ts

import {Injectable} from "@angular/core";
import {Response} from "@angular/http";
import "rxjs/add/operator/map";
import "rxjs/add/operator/toPromise";
import {AuthHttp} from "angular2-jwt";

@Injectable()
export class AuthService
{
    constructor(private authHttp: AuthHttp)
    {
    }

    login(username: string, password: string)
    {
        return this.authHttp.post('/api/login', JSON.stringify({username: username, password: password}))
            .map((response: Response) =>{
                return false;
            });
    }
}

Upvotes: 1

Views: 1750

Answers (1)

Fabio Antunes
Fabio Antunes

Reputation: 22892

That's the default behaviour of angular2-jwt

By default, if there is no valid JWT saved, AuthHttp will return an Observable error with 'Invalid JWT'. If you would like to continue with an unauthenticated request instead, you can set noJwtError to true.

You should only use AuthHttp when you want to do authenticated requests, so on your AuthService you also need to import the Http service, something like this:

import { Injectable } from "@angular/core";
import { Http, Response} from "@angular/http";
import "rxjs/add/operator/map";
import "rxjs/add/operator/toPromise";
import { AuthHttp } from "angular2-jwt";

@Injectable()
export class AuthService
{
    constructor(private http: Http, private authHttp: AuthHttp){ }

    login(username: string, password: string){
      //use this.http instead of this.authHttp
      return this.http.post('/api/login', {username: username, password: password})
        .map((response: Response) => {
          return false;
        });
    }
}

As said before Angular2-jwt checks for a valid JWT token, if by any chances there isn't a valid JWT then it doesn't even do the request.

But if you want to use authHttp for every request you can disable the JWT token validation, by overriding the configs of the provider, on your app.modute.ts add it like this:

import {NgModule} from "@angular/core";
import {BrowserModule} from "@angular/platform-browser";
import {FormsModule} from "@angular/forms";
import {HttpModule} from "@angular/http";
import {AppComponent} from "./app.component";
import {AppRoutingModule} from "./app-routing.module";
import {LoginComponent} from "./login/login.component";
import {MainComponent} from "./main/main.component";
import {AuthService} from "./services/auth.service";
import { provideAuth } from 'angular2-jwt';

@NgModule({
    imports     : [
        BrowserModule,
        AppRoutingModule,
        FormsModule,
        HttpModule
    ],
    declarations: [
        AppComponent,
        LoginComponent,
        MainComponent
    ],
    providers   : [
        AuthService,
        provideAuth({
          noJwtError: true,
        })
    ],
    bootstrap   : [AppComponent]
})
export class AppModule
{
}

more info here

EDIT:

The AuthService with the error handler:

import { Injectable } from "@angular/core";
import { Http, Response} from "@angular/http";
import "rxjs/add/operator/map";
import "rxjs/add/operator/toPromise";
import { AuthHttp, AuthHttpError } from "angular2-jwt"; //we need to import the AuthHttpError

@Injectable()
export class AuthService
{
    constructor(private http: Http, private authHttp: AuthHttp){ }

    login(username: string, password: string){
      //use this.http instead of this.authHttp
      return this.http.post('/api/login', {username: username, password: password})
        .map((response: Response) => {
          return false;
        })
        .catch(this.handleError); // we had the catch
    }

    private handleError (error: Response | any) {
        // In a real world app, we might use a remote logging infrastructure
        let errMsg: string;
        if (error instanceof AuthHttpError) {
          //here we will handle JWT errors
          console.log(error)
        } else if (error instanceof Response) {
          const body = error.json() || '';
          const err = body.error || JSON.stringify(body);
          errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
        }else {
          errMsg = error.message ? error.message : error.toString();
        }
        console.error(errMsg);
        return Observable.throw(errMsg);
    }
}

Upvotes: 4

Related Questions