I have an issue in angular 4 when I post a request API with Authorization header?
addPost(body): Observable<any>{
const url = 'https://xxxxxx';
return this.http.post(URL, body, this.options)
.map((res:Response) => {
this.data = res.json();
})
}
token comes from firebase auth
afAuth.auth.currentUser.getIdToken()
.then(token => {
this.headers = new Headers({
'Authorization': 'Bearer '+token
});
this.headers.append('Content-Type', 'application/json');
this.options = new RequestOptions({ headers: this.headers });
});
this.headers.append('Content-Type', 'application/json');
this.options = new RequestOptions({ headers: this.headers });
I call post by this
return this.getJob.addPost(body).subscribe((data) => {
console.log(data);
});
Response 403!!!
Request URL:https://us-central1-xxxxxx-prod.cloudfunctions.net/api/post
Request Method:OPTIONS
Status Code:403
Remote Address:216.58.198.51:443
Referrer Policy:no-referrer-when-downgrade
Response Headers
access-control-allow-methods:GET, POST
access-control-allow-origin:
cache-control:private
content-encoding:gzip
content-length:32
content-type:text/html; charset=utf-8
date:Tue, 08 Aug 2017 12:23:55 GMT
etag:W/"c-dAuDFQrdjS3hezqxDTNgW7AOlYk"
function-execution-id:d0la00v58w7p
server:Google Frontend
status:403
vary:Accept-Encoding
x-cloud-trace-context:d1b6ff9d729f7e250193a70aea16cac1;o=1
x-cloud-trace-context:d1b6ff9d729f7e250193a70aea16cac1
x-powered-by:Express
Request Headers
:authority:us-central1-xxxxxx-prod.cloudfunctions.net
:method:OPTIONS
:path:/api/post
:scheme:https
accept:/*
accept-encoding:gzip, deflate, br
accept-language:en-US,en;q=0.8,ar;q=0.6
access-control-request-headers:authorization,content-type
access-control-request-method:POST
alexatoolbar-alx_ns_ph:AlexaToolbar/alx-4.0.1
cache-control:no-cache
origin:http://localhost:8080
pragma:no-cache
referer:http://localhost:8080/extras/addjobpost
user-agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like
Gecko) Chrome/59.0.3071.115 Safari/537.36
The better way to do this would be to create a interceptor that extends the default http module
Create a interceptor.ts
import {
Http,
Request,
RequestOptionsArgs,
Response,
RequestOptions,
ConnectionBackend,
Headers
}
from '@angular/http';
import { Router } from '@angular/router';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class HttpInterceptor extends Http {
constructor(private backend: ConnectionBackend, private defaultOptions: RequestOptions, private router: Router) {
super(backend, defaultOptions);
}
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.request(url, this.getRequestOptionArgs(options)));
}
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.get(url, this.getRequestOptionArgs(options)));
}
post(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.post(url, body, this.getRequestOptionArgs(options)));
}
put(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.put(url, body, this.getRequestOptionArgs(options)));
}
delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.delete(url, this.getRequestOptionArgs(options)));
}
getRequestOptionArgs(options?: RequestOptionsArgs): RequestOptionsArgs {
if (options === null) {
options = new RequestOptions();
}
if (options === undefined) {
options = new RequestOptions();
}
let headers = new Headers();
let key = 'auth.jwt.token';
let item = localStorage.getItem(key) ? localStorage.getItem(key) : null;
let parsedToken = JSON.parse(item);
headers.append('Authorization', 'Bearer ' + parsedToken.token);
if(options.headers) {
headers.append('Content-Type', 'multipart/form-data');
headers.append('accept', 'application/json');
} else {
headers.append('Content-Type', 'application/json');
}
//Clearing the headers and appending the token + content type every request.
options.headers = new Headers();
options.headers = headers;
return options;
}
intercept(observable: Observable<Response>): Observable<Response> {
return observable.catch((err, source) => {
if (err.status === 401 && !err.endsWith(err.url, 'api/auth/login')) {
this.router.navigate(['/login']);
return Observable.empty();
} else {
return Observable.throw(err);
}
});
}
}
Inside your app.module.ts
:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { APP_BASE_HREF } from '@angular/common';
import { XHRBackend, RequestOptions, Http, HttpModule } from '@angular/http';
import { Router } from '@angular/router';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { HttpInterceptor } from 'interceptor.ts';
export function httpInterceptorFactory(xhrBackend: XHRBackend, requestOptions: RequestOptions, router: Router) {
return new HttpInterceptor(xhrBackend, requestOptions, router);
}
@NgModule({
imports: [BrowserModule, AppRoutingModule, HttpModule, SharedModule.forRoot()],
declarations: [AppComponent],
providers: [{
provide: APP_BASE_HREF,
useValue: '<%= APP_BASE %>'
}, SomeService, AnotherService,
{
provide: Http,
useFactory: httpInterceptorFactory,
deps: [XHRBackend, RequestOptions, Router]
}],
bootstrap: [AppComponent]
})
export class AppModule { }
Then just call http
as per usual, for example this._http.get().map()
and the interceptor will append the token for you.
EDIT:
Updated answer to include a basic app.module.ts
Please use the code below.
let headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
headers.append('Authorization', 'Bearer ' + 'token');
let order = 'order=foobar';
console.log("data");
return this.http.post(url, body, { headers: headers })
.map((res: any) => res.json());
I replace header to params
getTokenHeader() {
return this.afAuth.auth.currentUser.getIdToken()
.then(token => {
let params = new URLSearchParams();
params.set('tsid', `Bearer ${token}`);
return params;
});
}
and call getTokenHeader in this function
addPost(body): Observable<any>{//
// const url = 'https://us-central1-talentdraw-prod.cloudfunctions.net/api/post';
let url = this.api.URL['main']+this.api.URL['afterAuth'];
return new Observable(observer => {
this.getTokenHeader()
.then(tokenOptions => {
// console.log(tokenOptions);
return this.http.get(url, {
search: tokenOptions
})
.map((res:Response) => {
// this.data = res.json().data;
observer.next(res);
observer.complete();
})
.subscribe((data) => {
observer.complete();
})
})
.catch(( error: any ) => {
observer.error(error);
observer.complete();
});
})
}