Auth0 JWT plugin and ionic2 - No header send


#1

Hello. I have problem with integrating JWT token plugin from Auth0 with least Ionic2. I have absolutly no error but request is send without authorization header. My code:
app.module

import { NgModule } from '@angular/core';
import { IonicApp, IonicModule } from 'ionic-angular';
import { MyApp } from './app.component';
import { AboutPage } from '../pages/about/about';
import { ContactPage } from '../pages/contact/contact';
import { HomePage } from '../pages/home/home';
import { TabsPage } from '../pages/tabs/tabs';
import { LoginPage } from '../pages/login/login';
import { AuthHttp, AuthConfig } from 'angular2-jwt';
import { Storage } from '@ionic/storage';
import { Http } from '@angular/http';

import { AuthService } from '../services/auth.service';
import { NoteService } from '../services/note.service';

let storage: Storage = new Storage();

export function getAuthHttp(http) {
  return new AuthHttp(new AuthConfig({
    headerPrefix: 'JWT',
    noJwtError: true,
    globalHeaders: [{'Accept': 'application/json'}],
    tokenGetter: (() => storage.get('id_token')),
  }), http);
}

@NgModule({
  declarations: [
    MyApp,
    AboutPage,
    ContactPage,
    HomePage,
    TabsPage,
    LoginPage
  ],
  imports: [
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    AboutPage,
    ContactPage,
    HomePage,
    TabsPage,
    LoginPage
  ],
  providers: [
    AuthService,
    AuthHttp,
     {
      provide: AuthHttp,
      useFactory: getAuthHttp,
      deps: [Http]
    },
    Storage,
    NoteService,
  ]
})
export class AppModule {}

My service:

import { Injectable } from '@angular/core';
import { Headers, Http } from '@angular/http';
import { AuthHttp } from 'angular2-jwt';
import { AppParameters } from '../parameters';
import { AuthFormModel } from '../models/authForm.model';

import 'rxjs/add/operator/toPromise';

@Injectable()
export class NoteService {
    private headers = new Headers({ 'Content-Type': 'application/json' });
    private note_url: string = AppParameters.ENDPOINT_URL + '/notes/';

    private notes: any;
    constructor(private authHttp: AuthHttp) {}

    getUserNotes(){
        return this.authHttp.get(this.note_url);
    }

}

And at least my component:

import { Component } from '@angular/core';
import { NoteService } from '../../services/note.service';

import { NavController } from 'ionic-angular';



@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  notes: any;

  constructor(
    public navCtrl: NavController,
    public noteService: NoteService
    ) {}

  ngOnInit(){
    this.noteService.getUserNotes().subscribe(
            data => this.notes = data,
            err => console.log(err),
            () => {
              console.log('request complete');
              console.log(this.notes);
            }
        );
  }

}

My package.json:

{
  "name": "ionic-hello-world",
  "author": "Ionic Framework",
  "homepage": "http://ionicframework.com/",
  "private": true,
  "scripts": {
    "ionic:build": "ionic-app-scripts build",
    "ionic:serve": "ionic-app-scripts serve"
  },
  "dependencies": {
    "@angular/common": "2.1.1",
    "@angular/compiler": "2.1.1",
    "@angular/compiler-cli": "2.1.1",
    "@angular/core": "2.1.1",
    "@angular/forms": "2.1.1",
    "@angular/http": "2.1.1",
    "@angular/platform-browser": "2.1.1",
    "@angular/platform-browser-dynamic": "2.1.1",
    "@angular/platform-server": "2.1.1",
    "@ionic/storage": "1.1.6",
    "angular2-jwt": "^0.1.25",
    "ionic-angular": "2.0.0-rc.3",
    "ionic-native": "2.2.3",
    "ionicons": "3.0.0",
    "rxjs": "5.0.0-beta.12",
    "zone.js": "0.6.26"
  },
  "devDependencies": {
    "@ionic/app-scripts": "0.0.45",
    "typescript": "2.0.6"
  },
  "cordovaPlugins": [
    "cordova-plugin-whitelist",
    "cordova-plugin-console",
    "cordova-plugin-statusbar",
    "cordova-plugin-device",
    "cordova-plugin-splashscreen",
    "ionic-plugin-keyboard"
  ],
  "cordovaPlatforms": [],
  "description": "noteman_js: An Ionic project"
}

Everything work, absolutly no error in console but header is still missing. Maybe i forget something?
Btw. Sorry for my terrible english :wink:


#2

Were you able to solve this? I have the same issue for 2 months now. I know the issue is with asynchronous storage, but whatever I do it doesn’t send header. Right now I am hardcoding token and it works and hoping somebody finds solution.


#3

When you storage key don’t use stroage.set how in documentation but use it async

Storage.set(‘JWT’).then(() => {
Your code
})

I report this about two months ago… And they don’t fix the documentation :frowning:


#4

Hmmm, I don’t think I understand.

when you set the code will look like this?

Storage.set(‘JWT’, token).then(()=>{
this.rootPage = TabsPage;
})

and

tokenGetter: () => storage.get(‘JWT’)

Is this correct since this code doesn’t work for me. It logs me in, but when I refresh the page it doesn’t authorize me.


#5

Change you getAuthHttp like this to use localStorage instead of ionic storage:

export function getAuthHttp(http) {
  return new AuthHttp(new AuthConfig({
    globalHeaders: [{'Accept': 'application/json'}],
    //tokenGetter: (() => storage.get('id_token').then((val)=>{return val}) ),
    tokenGetter: (() => JSON.parse(window.localStorage.getItem("id_token"))),
    noJwtError: true,
    headerPrefix: "JWT",
  }), http);
}

As far as I can tell, the auth0 sdk is not using Ionic storage to store the id_token anyway… it’s just using window.localStorage, so you might as well just use that too and its a synchronous method so avoids this promise stuff.


#6

Hi chazwoza,

I too am not getting the token into the headers. I have tried adding your getAuthHttp above and added to providers like so, with no luck:

{
      provide: AuthHttp,
      useFactory: getAuthHttp,
      deps:[Http]
    }

Can I ask how you are sending it?
I am using the following:

let json = JSON.stringify({});
      let headers: Headers = new Headers
      headers.append('Content-type', 'application/json');
      headers.append('Authorization', 'Bearer ' + this.token);
      let options = new RequestOptions({ headers: headers });
      this.boxes = this.authHttp.post(this.appURL, json, options)
      return this.boxes
        .map(res => res.json())
        .catch(this.handleError);
    }

#7

Hi andjelicnikola,

How are you hard coding the token in?


#8

Token needs to be inserted when you call function for authHttp in app.module. After that, token will be automatically inserted


export function getAuthHttp(http: Http, options: RequestOptions, storage) {  
  return new AuthHttp(new AuthConfig({
    noJwtError: true,
    globalHeaders: [{'Content-Type': 'application/json'}],
    tokenGetter: (() => storage.get('id_token'))
 }), http, options);
}

This is straight forward from documentation. My issue was that I needed one more variable in the header that is stored in the storage.


#9

Thanks but that gives me an error: Cannot read property ‘get’ of undefined

Are you setting ‘storage’ elsewhere?
Also, are you using IonicStorageModule?

You mentioned hard coding it in, I assumed to skip the storage issue temporarily - how did you do that?
Something like tokenGetter: (() => “theactualtokenstringhere…”.

If what you provided above works for you - what is your Ionic info?
Mine is:
Ionic Framework Version: 3.3.0
Ionic CLI Version: 2.2.3
Ionic App Lib Version: 2.2.1
Ionic App Scripts Version: 1.3.7


#10

It sounds like that you haven’t imported storage in app.module.

import { IonicStorageModule, Storage } from '@ionic/storage';  <--- this
...

imports: [
    BrowserModule,
    HttpModule,
    IonicModule.forRoot(MyApp), 
    IonicStorageModule.forRoot(),   <---- this
    ...
  ],bootstrap: [IonicApp],
  entryComponents: [
    ...
  ],
  providers: [
    {
      provide: ErrorHandler, 
      useClass: IonicErrorHandler
    },
    {
      provide: AuthHttp, 
      useFactory: getAuthHttp, 
      deps: [Http, RequestOptions, Storage]    <---- this is for authHttp
    },
    ...
  ]

#11

In Ionic 2/3 it would rather look like that, your code definitely looks like Ionic V1, not V2/3.


getAuthHttp(http) {
return new AuthHttp(new AuthConfig({
headerPrefix: ‘JWT’,
noJwtError: true,
globalHeaders: [{‘Accept’: ‘application/json’}],
tokenGetter: (() => storage.get(‘id_token’)),
}), http);
}

Also this tokenGetter is a big concern, this code should directly throw an error message.

try something closer to this:

getAuthHttp(http) {
  return new AuthHttp(new AuthConfig({
    headerPrefix: 'JWT',
    noJwtError: true,}), http);
}
    globalHeaders: [{'Accept': 'application/json'}],
    tokenGetter: ((data) => storage.get('id_token')),
  }), http);
}

Before constructor, make sure data is never blank stale by a simple empty declaration.

data: any = '';

Then start debugging with

console.log(data);


#12

In my service that calls APIs:

import { Http } from '@angular/http';
import { AuthHttp } from 'angular2-jwt';

*****

  constructor( public http: Http, public authHttp: AuthHttp, public storage: Storage) {
    console.log('Initiated');
  }

  
  // STATUS API
 status(){
        var url = API_BASE + '/status';
        var response = this.authHttp.get(url).map(res => res.json());
        return response;
    }

*****

In app.module.ts


  imports: [  
    BrowserModule,
    HttpModule,
    IonicModule.forRoot(MyApp),
    IonicStorageModule.forRoot()
  ],

  providers: [
              StatusBar,
              SplashScreen,
              {provide: ErrorHandler, useClass: IonicErrorHandler},
              { provide: AuthHttp, useFactory: getAuthHttp,deps: [Http]}
              ]