Angular2 auth token in header request CORS/Preflight issue - apache

I'm trying to request a HTTP GET call to my local REST REST http://demosite.com/mage_auth/api/rest it needs an authorization token to let a user call an endpoint.
So in my request I passed headers.set('Authorization', token) and content-type JSON, however it doesn't seems to be passing the header in the Request's Header when I check the network response.
I've created a httpClient Service to pass the auth token: --
createAuthorizationHeader(headers: Headers) {
var sample3Results = (new OAuthSimple()).sign({
path: 'http://www.demosites.com/mage_auth/',
signatures: {
'consumer_key': key,
'shared_secret': secret,
'access_token': token,
'access_secret': tokensecret
}
});
try {
console.debug('Sample 3', sample3Results);
} catch (e) { };
let headerAuth = sample3Results.header;
headers.set('Authorization', headerAuth);
headers.set('Content-Type', 'application/json; charset=UTF-8' );
}
get(url) {
let headers = new Headers();
this.createAuthorizationHeader(headers);
return this.http.get(url, {
headers: headers
});
}
My component request look like this: --
this.httClient.get('http://www.demosites.com/mage_auth/api/rest/products')
.map(res => res.json())
.subscribe(data => {
console.log('data: ', data);
})
The REST API is running on WAMP server, so I've also added some CORS values in httpd.conf
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "origin, content-type"
Header set Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"
</IfModule>
And I'm still getting this Error.
XMLHttpRequest cannot load http://www.demosites.com/mage_auth/api/rest/products. Response for preflight has invalid HTTP status code 400
Just in case, I also added a proxy.config.json from Angular-cli as thought that'd fix it because the request is coming from localhost:4200. But seems wasn't the case, I'm out of idea why it still giving a preflight error.
Can someone point out what's wrong with this request?

That can be a misconfiguration of the CORS filter server side.
As for me, even if my CORS filter was well configured server side, I still faced the same issue. I used the RequestOptions of Angular for the headers. This is how I soved it within my angular service
Angular 2
header.append("Content-Type", "application/json");
header.append("X-Auth-Token", token);
let options = new RequestOptions({headers: header})
return this.http.get(url, options)
.toPromise()
.then(response => response.json())
.catch(this.handleError);
Angular 4.3
Define an interceptor
import {Injectable} from '#angular/core';
import {HttpRequest, HttpHandler, HttpEvent, HttpInterceptor} from '#angular/common/http';
import {Observable} from 'rxjs/Observable';
import {AppService} from '../app.service';
#Injectable()
export class Interceptor implements HttpInterceptor {
constructor() {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
request = request.clone({
setHeaders: {
token: `Bearer token`
}
});
return next.handle(request);
}
}
HttpRequests are immutable objects. So we need to copy them and then modidfy the copy.
Import the interceptor in app.module.ts
...
imports: [
BrowserModule,
HttpClientModule,
...
],
providers: [
{provide: HTTP_INTERCEPTORS, useClass: Interceptor, multi: true},
AppService
...
]
Use the interceptor in app.service.ts
import { Injectable } from '#angular/core';
import {Http, RequestOptions} from '#angular/http';
import 'rxjs/add/operator/map';
import {Observable} from 'rxjs/Observable';
import {HttpClient} from '#angular/common/http';
#Injectable()
export class AppService {
constructor(public http: HttpClient) { }
connectServer() {
return this.http.get('url')
.map(response => response);
}
}

Related

Axios may ignore default headers

I'm using axios in my nuxt project.
When I make a request by setting headers config in the request config, the default headers are ignored on node.js.
When I run the following code on node.js
import axios from "axios";
axios.defaults.headers.common["default-header"] = "default-header";
axios.get("https://jsonplaceholder.typicode.com/todos/1", {
headers: { header1: "header1" },
})
.then((response) => {
console.error(response.config);
});
The response config headers is as follows
headers: {
header1: 'header1'
}
The expected response config headers is as follows
headers: {
default-header: "default-header"
header1: "header1"
}
When I run the following code on browser (like Chrome), response config headers is as expected.
Is this a bug in axios?
I created a repository for verification
https://github.com/mimi6612/nuxt-axios-request-config-sample
I think you are missing the axios.create methode.
import axios from 'axios'
const requestHandler = config => {
config.headers = {
'defaultHeader': 'myDefaultHeaderString'
}
config.crossDomain = true
return config
}
const requester = axios.create()
requester.interceptors.request.use(requestHandler)
export requester

HttpErrorResponse Unauthorized (401) Angular 8 With Laravel 5.8 and Passport Authintication

I have create API on laravel 5.8 using passport Auth.
I have the following API routes on laravel :
// private routes
Route::middleware('auth:api')->group(function () {
Route::get('/getUser', 'Api\AuthController#getUser')->name('getUser');
});
// public routes
Route::post('/login', 'Api\AuthController#login')->name('login.api');
Route::post('/register', 'Api\AuthController#register')->name('register.api');
I test my routes using postman and that works!
but when I have call the routing from angular 8, the public routes works, but the private route return the error 401 (Unauthorized).
The error from console
GET http://localhost:8000/api/getUser 401 (Unauthorized) zone-evergreen.js:2952
ERROR HttpErrorResponse {headers: HttpHeaders, status: 401, statusText: "Unauthorized", url: "http://localhost:8000/api/getUser",
ok: false, …} core.js:6014
the following code for call the routes in angular:
import { Headers, RequestOptions } from '#angular/http';
import { HttpClient } from '#angular/common/http';
headers: Headers = new Headers();
constructor(private http: HttpClient) {}
getUser(accessToken) {
this.headers.append('Accept','application/json');
this.headers.append('Authorization', 'Bearer ' + accessToken);
this.options = new RequestOptions({headers: this.headers});
return this.http.get(this.urlServer, this.options);
}
I have tried a lot of way to solve this problem and see all tickets here,
but the issue not solved yet.
Finally I found the way to solve this problem...
I change my way of request by import the old Http from angular/http
instead of HttpClient from angular/common/http..
so the new code of angular is :
import { Headers, RequestOptions, Http } from '#angular/http';
constructor(private http: Http) {}
getUser(accessToken) {
return this.http.get(this.server + 'getUser', this.options).pipe( map(res => res.json()));
}

Angular 6 Http client custom url and header

I am working in an Angular 6 application and I was wondering what should be the best practice when customizing the url while sending requests to the server.
Here is the scenario:
- In my Angular project I have the environment.ts and environment.prod.ts where I added a "host" which contains the url:port of the http server (project with the controllers).
- I am creating Services to be injected in my components which will be responsible for sending requests (GETs and POSTs) to the server to retrieve data or to send updates.
- I want to use the "host" from the environment.ts as part of the request url. So ALL my requests will have the "host" as the base url and then i can concatenate to the desired path.
I already checked a few solutions and I already implemented one of them, but I am not sure this is the right practice. I will write below what i implemented so far and then i will write some ideas, please help me understand what is the best solution (I am new at angular)
Currently implemented:
-> In my feature services, like LoginService, I inject the angular HttpClient. Then I simply call:
return this.httpService.post("/login/", creds).pipe(
map((data: any) => {
this.manager = data;
return this.manager;
}));
I created an interceptor to make changes to the url: InterceptService implements HttpInterceptor where I create a new instance of the HttpRequest and customize the request.url using environment.host. I also needed the interceptor to add a Header for the authentication (still not fully implemented)
const httpRequest = new HttpRequest(<any>request.method, environment.host + request.url, request.body);
request = Object.assign(request, httpRequest);
const headers = new HttpHeaders({
'Authorization': 'Bearer token 123',
'Content-Type': 'application/json'
});
Questions:
1) This works, all my requests are changed in the interceptor as I
wanted, but it doesn't look like the best practice in my first look. I
don't like to create a new HeepRequest to be able to do this (i did it
to keep it immutable, I guess that's the correct way). Do you think
this looks good?
2) What about the Authentication being added to the Header in the interceptor? Is it ok? Most of the references I checked did this
Other solutions:
1) I saw some examples where a HttpClientService extends Http and each of the methods such as get and post edit the url and headers before calling super methods. But I believe this is not Angular 6 and is probably not preferrable
2) I could also create a service that receives an angular HttpClient (angular 6 HttpClientModule) instance by injection and I could implement the methods like get or post.
Well, as I didn't get any answers I will add my solution. i believe it's the best solution based on my researches.
I used an interceptor for adding information to the header such as the
token bearer authentication.
import { Injectable } from '#angular/core';
import {
HttpEvent,
HttpInterceptor,
HttpHandler,
HttpRequest,
HttpResponse,
HttpHeaders,
HttpErrorResponse
} from '#angular/common/http'
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { environment } from "../../../environments/environment";
import { Router } from "#angular/router";
export class HttpClientInterceptor implements HttpInterceptor {
constructor(private router: Router) { }
// intercept request to add information to the headers such as the token
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
//I decided to remove this logic from the interceptor to add the host url on the HttpClientService I created
//const httpRequest = new HttpRequest(<any>request.method, environment.host + request.url, request.body);
//request = Object.assign(request, httpRequest);
var token = localStorage.getItem("bearerToken");
if (token) {
const newReq = request.clone(
{
headers: request.headers.set('Authorization',
'Bearer ' + token)
});
return next.handle(newReq).pipe(
tap(event => {
if (event instanceof HttpResponse) {
console.log("Interceptor - HttpResponse = " + event.status); // http response status code
}
}, error => {
// http response status code
if (error instanceof HttpErrorResponse) {
console.log("----response----");
console.error("status code:");
console.error(error.status);
console.error(error.message);
console.log("--- end of response---");
if (error.status === 401 || error.status === 403) //check if the token expired and redirect to login
this.router.navigate(['login']);
}
})
)
}
else {
return next.handle(request);
}
};
For changing the url, I created a service on file
http-client.service.ts and got the host url from environment.ts
import { Injectable } from "#angular/core";
import { HttpClient } from '#angular/common/http';
import { Observable } from "rxjs";
import { environment } from "../../../environments/environment";
#Injectable({ providedIn:'root' })
export class HttpClientService {
constructor(private http: HttpClient) { }
get(url: string, options?: any): Observable<ArrayBuffer> {
url = this.updateUrl(url);
return this.http.get(url, options);
}
post(url: string, body: string, options?: any): Observable<ArrayBuffer> {
url = this.updateUrl(url);
return this.http.post(url, body, options);
}
put(url: string, body: string, options?: any): Observable<ArrayBuffer> {
url = this.updateUrl(url);
return this.http.put(url, body, options);
}
delete(url: string, options?: any): Observable<ArrayBuffer> {
url = this.updateUrl(url);
return this.http.delete(url,options);
}
private updateUrl(req: string) {
return environment.host + req;
}
}
As i said, I believe this is the best approach, but feel free to add information to my question/answer.

Unable to send data in headers to authorize the request in php

I am getting the error message in cli like :
Type 'Headers' has no properties in common with type 'RequestOptionsArgs'
. However, the code executes. The version I am using is 5, as it shows in package.json. I am unable to find a good http example, which suit my need. I want to send some parameters in headers section, and authorize it in php. Here is the service code:
user.service.ts
import { Observable } from 'rxjs/Observable';
import { Customer } from './../models/customer';
import { Injectable } from "#angular/core";
import { Http, Response, Headers, RequestOptions } from "#angular/http";
import "rxjs/add/operator/map";
import { apiServicesURL,appServicesURL } from "../constants/globals";
import { HttpClient, HttpHeaders } from "#angular/common/http";
#Injectable()
export class UserService {
//headers : Headers ;
constructor(private http: Http) {
}
getCustomerInfoo(custId): Observable<Customer> {
//cust.push({token : localStorage.getItem('token')});
console.log(apiServicesURL + 'getCustomers');
let token = localStorage.getItem('token');
let api_token = localStorage.getItem('api_token');
let email = localStorage.getItem('email');
let headers = new Headers({ 'Content-Type': 'application/json' });
// let options: RequestOptions = new RequestOptions({ headers: headers });
return this.http.post(apiServicesURL + 'getCustomers', JSON.stringify({ customer_id: custId, token: api_token, email: email }), headers ).map((response: Response) => {
// login successful if there's a jwt token in the response
return <Customer>response.json();
});
}
}
Any help, appreciated!!!
If you are using angular 5 then try it this below code and write RequestOptionsProvider to module.ts file
import { Injectable } from '#angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HTTP_INTERCEPTORS } from '#angular/common/http';
import { AuthService } from '#app/core/services/auth.service';
import { Observable } from 'rxjs/Observable';
#Injectable()
export class DefaultRequestOptionsService implements HttpInterceptor {
constructor(private auth: AuthService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// Get the auth header from the service.
// const authHeader = this.auth.getAuthorizationHeader();
// Clone the request to add the new header.
// const authReq = req.clone({headers: req.headers.set('Authorization', authHeader)});
const authReq = req.clone({ headers: req.headers.set('Content-Type', 'application/json') });
// Pass on the cloned request instead of the original request.
return next.handle(authReq);
}
}
export const RequestOptionsProvider = { provide: HTTP_INTERCEPTORS, useClass: DefaultRequestOptionsService, multi: true };

Adding headers via HttpInterceptor Angular 5

I want to add headers to post request from Angular 5 web app.
I've created the following Injectable class, registered in my app module:
#Injectable()
export class headerInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// Clone the request to add the new header
const authReq = req.clone({
headers: new HttpHeaders({
'Content-Type': 'application/json; charset=utf-8',
})
});
return next.handle(authReq);
}
}
I have network communication service and Im adding body parameters as below.
#Injectable()
export class NetworkService {
Root:string = 'some valid url';
results:Object[];
loading:boolean;
// inject Http client to our client service.
constructor(private httpClient: HttpClient ) {
}
login(loginParams : URLSearchParams){
let baseURL = `${this.Root}/login`;
this.httpClient.post(baseURL, JSON.stringify({'UserName':'123','Password':'123'} ))
.subscribe(data => {
console.log();
},
err => {
console.log('Error: ' + err.error);
});
when I put breakpoint after the clone method inside headerInterceptor class I can see the request body.
the problem is when I switch to network tab in chrome, I get 405 error and I can't see the body and the new headers. when I return the original request 'req'
the body sent ok but no new headers of course.
App Module,
import { HttpClientModule, HTTP_INTERCEPTORS } from '#angular/common/http';
import { headerInterceptor } from './httpinterceptor'
Add it to providers,
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: headerInterceptor,
multi: true
}
],
Now change the intereptor to, I have changed the way headers are added
#Injectable()
export class headerInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const authReq = req.clone({
headers:req.headers.set("Content-Type", "application/json; charset=utf-8")
});
return next.handle(authReq);
}
}
}
You can also use setHeaders:
#Injectable()
export class headerInterceptor implements HttpInterceptor {
constructor() {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {y
req = req.clone({
setHeaders: {
"Content-Type": "application/json; charset=utf-8"
}
});
return next.handle(req);
}
}
My problem was on server side I'm using ASP.net and wcf.
it seems that the server must implement CORS support when working with Angular 5 project (works ok with jQuery and cross domain tag).
this post helped me to add support in CORS:
http://blogs.microsoft.co.il/idof/2011/07/02/cross-origin-resource-sharing-cors-and-wcf/