Adding "Authorization" header in get request


#1

I’m developing Ionic application with Spring framework back-end. Application is simple, check specified URI to check user is authenticated and valid user and then return token. So application using that token to get some JSON from Basic Authentication required URI.

The problem is angular/http is not sending “Authorization” header.

httpclient.ts

import { Injectable } from '@angular/core';
import { Http, Headers } from '@angular/http';
import { Storage } from '@ionic/storage';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/map';

@Injectable()
export class HttpClient {

  constructor(private http: Http, private storage: Storage) {
  }

  buildHeaders(){
    let headers = new Headers({
      'Content-Type': 'application/json',
      'withCredentials': 'true'
    });

    return this.storage.get("user").then((user) => {
        if(user){
          let info = JSON.parse(user);
          console.log(info.token);
          headers.append('Authorization', 'Basic ' + info.token);
          return headers;
        }
      }
    )
  }

  get(url) {
    return Observable
      .fromPromise(this.buildHeaders())
      .switchMap((headers) => this.http.get(url, { headers: headers }));
  }

}

used like this

import { Component } from '@angular/core';
import { AuthProvider } from "../../providers/auth/auth";
import { Storage } from "@ionic/storage";
import { SERVER_URL } from "../../config";
import { HttpClient } from "../../providers/httpclient/httpclient";

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

  user: string;
  message: string;
  list: any;
  posts: any;

  constructor(private authProvider: AuthProvider,
              private storage: Storage,
              private http: HttpClient) {
    });

  }

  ionViewWillEnter() {
    this.storage.get('user').then(user => {
       this.http
         .get(`${SERVER_URL}/content/find.json`).subscribe(
         response => this.message = response.json(),
         err => alert(err)
       );
    });
  }

  logout() {
    this.authProvider.logout();
  }

}

How can i send request with Authorization header?
Ive tried many ways but no help.

ionic info :
global packages:

@ionic/cli-utils : 1.1.2
Cordova CLI      : 7.0.1 
Ionic CLI        : 3.1.2

local packages:

@ionic/app-scripts              : 1.3.7
@ionic/cli-plugin-cordova       : 1.1.2
@ionic/cli-plugin-ionic-angular : 1.1.2
Ionic Framework                 : ionic-angular 3.2.1

System:

Node       : v7.9.0
OS         : Linux 4.4
Xcode      : not installed
ios-deploy : not installed
ios-sim    : not installed

package.json deps :


"dependencies": {
        "@angular/common": "4.1.0",
        "@angular/compiler": "4.1.0",
        "@angular/compiler-cli": "4.1.0",
        "@angular/core": "4.1.0",
        "@angular/forms": "4.1.0",
        "@angular/http": "4.1.0",
        "@angular/platform-browser": "4.1.0",
        "@angular/platform-browser-dynamic": "4.1.0",
        "@ionic-native/core": "3.7.0",
        "@ionic-native/splash-screen": "3.7.0",
        "@ionic-native/status-bar": "3.7.0",
        "@ionic/storage": "2.0.0",
        "cordova-android": "^6.2.3",
        "cordova-plugin-console": "^1.0.5",
        "cordova-plugin-device": "^1.1.4",
        "cordova-plugin-splashscreen": "^4.0.3",
        "cordova-plugin-statusbar": "^2.2.2",
        "cordova-plugin-whitelist": "^1.3.1",
        "cordova-sqlite-storage": "^2.0.4",
        "ionic-angular": "3.2.1",
        "ionic-plugin-keyboard": "^2.2.1",
        "ionicons": "3.0.0",
        "ng2-validation": "^4.2.0",
        "rxjs": "5.1.1",
        "sw-toolbox": "3.6.0",
        "zone.js": "0.8.10"
    },
    "devDependencies": {
        "@ionic/app-scripts": "1.3.7",
        "@ionic/cli-plugin-cordova": "1.1.2",
        "@ionic/cli-plugin-ionic-angular": "1.1.2",
        "typescript": "2.2.1"
    },

#2

I’m probably missing something really obvious, but I see a function building headers and then another function calling http.get() without them.


#3

Thanks for reply. I forgot to mention "import"s. Updated the post.


#4

http.get function 2. parameter, http.post function 3. parameter is RequestOptions. You can set headers to request options and use the parameter like this.

let headers = new Headers();
    headers.append('Content-Type', 'application/x-www-form-urlencoded');
    headers.append('Accept', 'application/json');
    headers.append('Authorization', 'Bearer ' + token);

    let options = new RequestOptions({ headers: headers });

this.http.get("url", options)
      .map(response => response)

#5

I just realized my mistake. Angular/http send request with “OPTIONS” method first. I wonder why i thought that’s the server response. But it wasn’t. Http preflight request checks server have CORS enabled or not. Then i permited “OPTIONS” method in my requested URI. That’s gone well.


#6

I trying

  let headers = new Headers({ 'Authorization': 'Bearer ' + window.localStorage.getItem('token') });
    let options = new RequestOptions({ headers: headers });
    return this.http.get(this.api+'causes' , options).map( res => res.json());

but return to me the following error
ERROR Error: Cannot find a differ supporting object ‘[object Object]’ of type ‘object’. NgFor only supports binding to Iterables such as Arrays. ??
Any idea ?


#7

I could be wrong but that error message doesn’t seem to be related to code you posted.

Are you sure that code is causing the problem? Can you post the code that is using the observable?

The error message seems to be indicating that you are trying to loop over something in an template that is of type object rather than an array.


#8

@niallr son this is my code

Hi guys, I need your help
I got this code example around, I dont remenber
I dont know if this code is good

service-provider.ts

export class ServiceProvider {

  api: string = 'https://www.mydomine/api/v1/';
  isLoggedIn = false;
  AuthToken: string;

  constructor(public http: Http) {
    this.isLoggedIn = false;
    this.AuthToken = null;
  }

  // Authenticate and verify email and password of User and create TOKEN
  authenticate(user) {
    let creds = 'email=' + user.email + "&password=" + user.password;
    let headers = new Headers();
    headers.append('Content-Type', 'application/x-www-form-urlencoded');

    return new Promise(resolve => {
        this.http.post(this.api+'auth', creds, {headers: headers}).subscribe( data => {
            if(data.json().success){
                this.storeUserCredentials(data.json().success);
                resolve(true);
            }
            else
                resolve(false);
        });
    });
  }

  // Get the token and send to userCredentials method bellow
  storeUserCredentials(token) {
    window.localStorage.setItem('token', token);
    this.useCredentials(token);
  }

  useCredentials(token) {
    this.isLoggedIn = true;
    this.AuthToken = token;
  }

  loadUserCredentials() {
    let token = window.localStorage.getItem('token');
    this.useCredentials(token);
  }

  // Destroy Authentication of User
  destroyUserCredentials() {
      this.isLoggedIn = false;
      this.AuthToken = null;
      window.localStorage.clear();
  }

  createAuthorization(headers: Headers) {
    headers.append('Authorization', window.localStorage.getItem('token'));
  }

  getCauses() {
    return this.http.get(this.api+'causes').map( res => res.json());
  }

}

I’m doing login and get the token of my API, but I dont know to use TOKEN in other places, for example in getCauses method
I want resolve by steps
1 - To use TOKEN in others requests using Headers Authorization + Beares + Token
2 - To use TOKEN to call forever user logged in all pages

Im my home.ts I have:

constructor(public navCtrl: NavController, public navParams: NavParams, public service: ServiceProvider, public alertCtrl: AlertController) {
    this.getData();
    this.loading();
  }


getData() {
    this.service.getCauses()
      .subscribe(
        data => this.causes = data,
        err => console.log(err)
      );
  }

#9

@niallr you’re totally right friend, the error was in my home.ts look

 getData() {
   this.service.getCauses()
     .subscribe(
       data => this.causes = data,  <----- here is the problem
       err => console.log(err)
     );
 }

I added someone, look

  getData() {
    this.service.getCauses()
      .subscribe(
        data => this.causes = data.causas, <----- here is the solution
        err => console.log(err)
      );
  }

in my home.ts normally

<h4><strong>{{ cause.name }}</strong></h4>

now I would like to guard the user loggedin for example, edit profile yourself, how to make ?


#10

I’m using cakephp2 for rest api for ionic3 with angular 4/5
I’m setting token sent from api once user is authenticated and i am setting it in header after every request to api using interceptor. But the Authorization is not set in Request Header in Network. I’m stuck please help me:

My Interceptor
@Injectable()
export class CustomInterceptor implements HttpInterceptor {

intercept(req: HttpRequest, next: HttpHandler): Observable<HttpEvent> {
const token_id = localStorage.getItem(“token”);
req = req.clone({ headers: req.headers.set(‘Content-Type’, ‘application/x-www-form-urlencoded’) });
if (token_id != null) {
req = req.clone({
headers: req.headers.set(“Authorization”, 'token '+token_id)
});
return next.handle(req);
} else {
console.log(req);
return next.handle(req);
}
}
}

My CakePhp Headers

public function beforeFilter() {
$this->response->header(‘Access-Control-Allow-Origin’,’*’);
$this->response->header(‘Access-Control-Allow-Methods’, ‘GET,HEAD,OPTIONS,POST,PUT’);
$this->response->header(‘Access-Control-Allow-Headers’,‘Origin, X-Requested-With, Content-Type, Accept, Authorization, application/json’);

   $this->Auth->allow();
   // Avoids render() call 
   $this->autoRender = false; 
   $this->requestData = $this->getRequestData();
   $this->set('isAdmin', true);

}


#11

How did you permit options in your request uri? I have the same issue here.