Reponse Preflight and Request header not allowed in Angular 2 - wcf

I am Working on Angular 2 for getting data from WCF service.
I am calling Login method that returns a token.
For fetching Project Data i am using GET method and in that request we need to pass token in header.
But it gives Error:
XMLHttpRequest cannot load http://192.168.0.149/API/Service1.svc/Datalist. Response for preflight is invalid (redirect). Request header field token is not allowed by Access-Control-Allow-Headers in preflight response.
This are my Headers:-
General:
Request URL:http://pct149/ITM_API/Service1.svc/BHL/Projects
Request Method:OPTIONS
Status Code:200 OK
Remote Address:192.168.0.149:80
Here is my Angular Service in which i am calling WCF Service:-
import {Injectable} from "#angular/core"
import { Http, Response, RequestOptions, Headers } from "#angular/http"
import { Observable } from 'rxjs/Rx';
import {HttpClient } from "#service/http-client";
#Injectable()
export class AppService {
Hero = [];
baseUrl = "http://pct149/ITM_API/Service1.svc/BHL/";
constructor(private _http: Http, private httpClient: HttpClient) {
}
Authentication() {
return this._http.get(this.baseUrl + "Login/harshad.bhola#server1.com/1")
.map((response: Response) => {
let dataToken = response.json();
let Token = dataToken.Token;
if (Token != null & dataToken != null) {
return Token;
}
else {
return '';
}
})
.catch(this.handleError);
}
loadProjects(Token) {
return this._http.get(this.baseUrl + "Projects", { headers: { 'token': Token.trim() } })
.map((responseData: Response) => {
let appData = responseData.json();
console.log(appData);
return appData;
});
}
private handleError(error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}
Here is my Component from where i am calling service method:-
import {Component} from "#angular/core";
import { RouterOutlet, RouterLink, RouterModule, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from "#angular/router";
import { HTTP_PROVIDERS, HTTP_BINDINGS } from '#angular/http';
import {AppService } from "#service/app.service";
#Component({
selector: 'app',
templateUrl: 'htmls/app.html',
directives: [ROUTER_DIRECTIVES],
providers: [AppService]
})
export class ProjectListComponent {
Projects = [];
result = '';
constructor(private _appService: AppService) {
this.GetProject();
}
GetProject() {
this._appService.Authentication().subscribe(result => {this._appService.loadProjects(result).subscribe(newProject => this.Projects = newProject); });
}
}
Below Code i put in Global.asax of My WCF Service:-
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.Flush();
}
}
Please Help me if i am Wrong.

You need to add options to your list of supported methods in your CORS enablement. I'm using webapi 2 so I do this:
from webApiConfig.cs:
var cors = new EnableCorsAttribute("*", "*", "GET,PUT,POST,PATCH,DELETE,OPTIONS");
I also had to trap the preflight request and add the required header:
from global.asax.cs:
protected void Application_BeginRequest()
{
var req = HttpContext.Current.Request;
var res = HttpContext.Current.Response;
var val = res.Headers.GetValues("Access-Control-Allow-Origin");
if (val == null)
{
if (!req.Url.ToString().ToLower().Contains("token") || (req.Url.ToString().ToLower().Contains("token") && req.HttpMethod == "OPTIONS"))
{
res.AppendHeader("Access-Control-Allow-Origin", "http://localhost:4200");
}
}
if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
{
res.AppendHeader("Access-Control-Allow-Credentials", "true");
res.AppendHeader("Access-Control-Allow-Headers", "Content-Type, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name");
res.AppendHeader("Access-Control-Allow-Methods", "POST,GET,PUT,PATCH,DELETE,OPTIONS");
res.StatusCode = 200;
res.End();
}
}
Hope this helps.

Related

"Response is not defined" when using ngrx effects with HttpClient

I'm currently rewriting old request service to use HttpClient instead of Http. My app makes use of ngrx store and after I rewrote request service, it stopped working.
here's my request service:
import { Injectable } from '#angular/core';
import {HttpClient, HttpHeaders} from '#angular/common/http';
import { ToastController } from 'ionic-angular';
import { ReplaySubject } from 'rxjs/ReplaySubject';
import { Config } from '../app/app.config';
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { Version } from '#angular/compiler';
export enum HttpStatus {
UNAUTHORIZED,
WRONGVERSION,
UNVERIFIED,
NONETWORK,
}
export interface HttpNotifierData {
status: HttpStatus
}
#Injectable()
export class HttpClientService {
private httpNotifier: ReplaySubject<HttpNotifierData>;
constructor(
public toastCtrl: ToastController,
private _http: HttpClient,
) {
this.httpNotifier = new ReplaySubject();
}
createHeaders(contentType?: string) {
var headers = new HttpHeaders();
let token = localStorage.getItem('auth_token');
let expires = localStorage.getItem('auth_expires');
let appVersion = Config.version+'';
if(token)
headers = headers.set( 'Authorization', 'Bearer ' + token);
if(expires)
headers = headers.set( 'TokenExpiration', expires);
if(appVersion)
headers = headers.set( 'App-Version', appVersion);
if(contentType === 'form')
headers = headers.set('Content-Type','application/x-www-form-urlencoded');
return headers;
}
createAppVersionHeader(headers: Headers) {
let appVersion = Config.version+'';
headers.append('App-Version', appVersion);
}
getHttpNotifier(): ReplaySubject<HttpNotifierData> {
return this.httpNotifier;
}
request(verb: string, url: string, data?: any, contentType?: string) {
let headers = this.createHeaders(contentType);
return this._http.request(verb, url, {
body: data,
headers: headers
}).catch(err => {
if (err.status == 0) {
this.httpNotifier.next({status: HttpStatus.NONETWORK});
err._body = 'Kunne ikke kontakte baksystem';
} else if (err.status == 401) {
this.httpNotifier.next({status: HttpStatus.UNAUTHORIZED});
} else if (err.status == 403) {
this.httpNotifier.next({status: HttpStatus.UNVERIFIED});
} else if (err.status == 412) {
this.httpNotifier.next({status: HttpStatus.WRONGVERSION});
} else {
// TODO: Convert API error to user friendly error
this.toastCtrl.create({
message: err._body,
duration: 3000,
showCloseButton: true,
closeButtonText: "Lukk",
cssClass: 'error',
}).present();
}
throw err;
});
}
get(url) {
let cache = '?cache=' + Math.ceil(Math.random() * 100000);
return this.request('GET', url + cache);
}
post(url, data, contentType = 'json') {
return this.request('POST', url, data, contentType);
}
put(url, data) {
return this.request('PUT', url, data);
}
delete(url) {
return this.request('DELETE', url);
}
}
my user auth service:
import { Injectable } from '#angular/core';
import { Config } from '../app/app.config';
import { HttpClientService } from "./http.service";
#Injectable()
export class UserService {
constructor(
private _http: HttpClientService
) { }
login(username: string, password: string) {
var data = "grant_type=password&username=" + username + "&password=" + password + "&deviceId=test";
return this._http.post(Config.apiUrl + 'Token', data, 'form');
}
getPin(phone: string) {
return this._http.post(Config.apiUrl + 'api/account/forgotPassword', {phoneNumber: phone})
}
}
my ngrx effect for authenticating user:
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/observable/of';
import { Injectable } from '#angular/core';
import { Effect, Actions } from '#ngrx/effects';
import { Observable } from 'rxjs/Observable';
import { UserService } from '../services/user.service';
import * as UserActions from '../actions/user.actions';
#Injectable()
export class UserEffects {
constructor(
private actions: Actions,
private userService: UserService
) {}
#Effect()
login:Observable<any> = this.actions
.ofType(UserActions.LOGIN)
.map((action: UserActions.Login) => action.payload)
.switchMap(payload => {
return this.userService.login(payload.username, payload.password)
.map((response:any) => new UserActions.LoginSuccess(JSON.parse(response._body)))
.catch((error) => Observable.of(new UserActions.LoginFailed(error._body)))
});
#Effect()
getPin:Observable<any> = this.actions
.ofType(UserActions.GET_PIN)
.map((action: UserActions.GetPin) => action.payload)
.switchMap(payload => {
return this.userService.getPin(payload)
.map((response: any) => new UserActions.GetPinSuccess())
.catch((error) => Observable.of(new UserActions.GetPinFailed(error._body)))
});
}
when debugging, I have this error appearing in effect module:
however, in network section I can see that request is completed successfully:
what can be wrong with my service?
ok, so I figured out the solution.
effects for login should have pipe and no json parsing:
#Effect()
login:Observable<any> = this.actions
.ofType(UserActions.LOGIN)
.map((action: UserActions.Login) => action.payload)
.switchMap(payload => {
return this.userService.login(payload.username, payload.password).pipe()
.map((response:any) => new UserActions.LoginSuccess(response))
.catch((error) => Observable.of(new UserActions.LoginFailed(error._body)))
});

How write header with nestjs

how I can write headers using way nest.js?
I'm currently using this:
import { Controller, Body, Get, Post, HttpCode, HttpStatus, Req, Res } from '#nestjs/common';
import { Request, Response } from 'express';
import { AuthService } from './auth.service';
import { Usuario } from '../usuario/usuario.entity';
import { JsonWebTokenError } from 'jsonwebtoken';
import { request } from 'http';
#Controller('auth')
export class AuthController {
constructor(private readonly authService: AuthService) { }
#Post('login')
#HttpCode(HttpStatus.OK)
async login(#Body('username') username: string, #Body('password') password: string, #Res() response: Response) {
this.authService
.validateUser(username, password)
.then((token) => {
response.setHeader('Authorization', 'Bearer ' + token);
let respuesta: any = {};
respuesta.success = true;
respuesta.token = token;
return response.send(respuesta);
});
}
}
I do not want to use response.setHeader('Authorization', 'Bearer ' + token); and return response.send(respuesta);
Thanks for your answers!
NestJS is build on top of express, so do it like in express:
async login(#Body('username') username: string, #Body('password') password: string, #Res() res: Response) {
const token = await this.authService.validateUser(username, password);
res.set('Authorization', 'Bearer ' + token);
res.send({
success: true,
token,
})
});
In latest versions you could use the #Header decorator within NestJS Core.
import { Controller, Get, Req, Header, Res } from '#nestjs/common';
import { Request, Response } from 'express';
#Controller('cookies')
export class CookiesController {
#Get('set')
// #Header('Set-Cookie', 'cookieName = 12345') // "Usin header decorator"
setCookie(#Res() response: Response): Response {
/*
* If using express approach, pass #Res as param decorator
*/
response.cookie('rememberme', '1') // Using express res object.
return response.send('Cookie has been set! :)')
}
#Get()
checkCookie(#Req() request: Request ): string {
console.log(Object.keys(request.cookies))
if(Object.keys(request.cookies).length > 0){
console.log('cookies =>', request.cookies)
return 'Cookies are set :)'
} else {
return 'Uh, oh! Cookie hasn\'t been set :\'('
}
}
}

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 };

Angular 5.2 & RxJS 5.5 HttpInterceptor retryWhen, but update request?

I am trying to intercept a 401 response, send a refresh token request before trying request again (but with a different header). I have it working except retryWhen does not give me to modify the original request header. So I've been trying to use catchError instead but I cannot seem to execute the request again.
Here is my current retryWhen:
import {Injectable} from '#angular/core';
import {
HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpErrorResponse
}
from '#angular/common/http';
import {Observable} from 'rxjs/Observable';
import {CustomerService} from "../customer/customer.service";
import * as ApplicationSettings from "application-settings";
import {retryWhen, map} from "rxjs/operators";
import {LoginResponse} from "./LoginResponse";
/**
* This takes a request that requires an access_token and refreshes it on 401 errors.
*/
#Injectable()
export class RefreshTokenInterceptor implements HttpInterceptor {
public constructor(private customer: CustomerService) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
retryWhen(errors => {
return Observable.create(observer => {
errors.forEach((error: HttpErrorResponse) => {
if (error.status === 401) {
let refresh_token = ApplicationSettings.getString('refresh_token');
return this.customer.refreshToken(refresh_token).subscribe(
(response: LoginResponse) => {
this.customer.setToken(response);
let headers = req.headers.set('Authorization', `Bearer ${response.access_token}`);
console.log(`Bearer ${response.access_token}`);
let newReq = req.clone({headers: headers});
observer.next(next.handle(newReq));
observer.complete();
},
error2 => {
observer.error();
}
);
} else {
observer.error();
}
});
});
})
);
}
}
If I swap out retryWhen with catchError:
catchError((err, caught) => {
console.log('err: ' + JSON.stringify(err));
if (err.status === 401) {
console.log('401 !!!! REFRESH MEH!');
let newReqOb: Observable<HttpEvent<any>> = Observable.create(observer => {
console.log('going to refresh token');
let refresh_token = ApplicationSettings.getString('refresh_token');
let refresh = this.customer.refreshToken(refresh_token);
refresh.subscribe((response: LoginResponse) => {
console.log('token refreshed!');
this.customer.setToken(response);
let access_token = ApplicationSettings.getString('access_token');
let headers = req.headers.set('Authorization', `Bearer ${access_token}`);
console.log(`Bearer ${access_token}`);
let newReq = req.clone({headers: headers});
observer.next(next.handle(newReq)); // <-- HERE IT WONT FIRE
observer.complete();
});
});
return newReqOb;
}
return caught;
})
The important part is I am returning next.handle(newReq) and it doesn't seem to fire the request. If I switch it to next.handle(newReq).subscribe(), the request will fire but no callbacks are triggered.
Here is the full example with retryWhen:
import {Inject, Injectable} from '#angular/core';
import {
HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpErrorResponse, HttpClient
}
from '#angular/common/http';
import {Observable, ObservableInput} from 'rxjs/Observable';
import {CustomerService} from "../customer/customer.service";
import * as ApplicationSettings from "application-settings";
import {retryWhen, map, catchError} from "rxjs/operators";
import {LoginResponse} from "./LoginResponse";
import {APP_CONFIG, AppConfig} from "../../app.config";
/**
* This takes a request that requires an access_token and refreshes it on 401 errors.
*/
#Injectable()
export class RefreshTokenInterceptor implements HttpInterceptor {
public constructor(private customer: CustomerService, private http: HttpClient, #Inject(APP_CONFIG) private config: AppConfig) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
catchError((err, caught) => {
console.log('err: ' + JSON.stringify(err));
if (err.status === 401) {
console.log('401 !!!! REFRESH MEH!');
let newReqOb: Observable<HttpEvent<any>> = Observable.create(observer => {
console.log('going to refresh token');
let refresh_token = ApplicationSettings.getString('refresh_token');
let refresh = this.customer.refreshToken(refresh_token);
refresh.subscribe((response: LoginResponse) => {
console.log('token refreshed!');
this.customer.setToken(response);
let access_token = ApplicationSettings.getString('access_token');
let headers = req.headers.set('Authorization', `Bearer ${access_token}`);
console.log(`Bearer ${access_token}`);
let newReq = req.clone({headers: headers});
observer.next(next.handle(newReq));
observer.complete();
});
});
return newReqOb;
}
return caught;
})
);
}
}
I did find out the issue, here is the resulting code:
import {Inject, Injectable} from '#angular/core';
import {
HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpErrorResponse, HttpClient
}
from '#angular/common/http';
import {Observable, ObservableInput} from 'rxjs/Observable';
import {CustomerService} from "../customer/customer.service";
import * as ApplicationSettings from "application-settings";
import {catchError, switchMap, finalize} from "rxjs/operators";
import {LoginResponse} from "./LoginResponse";
import {APP_CONFIG, AppConfig} from "../../app.config";
import {RouterExtensions} from "nativescript-angular/router";
/**
* This takes a request that requires an access_token and refreshes it on 401 errors.
* #TODO What happens on 400 errors?
*/
#Injectable()
export class RefreshTokenInterceptor implements HttpInterceptor {
isRefreshingToken: boolean = false;
public constructor(private customer: CustomerService,
private http: HttpClient,
private router: RouterExtensions,
#Inject(APP_CONFIG) private config: AppConfig) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let validate = {
is_api_v1: req.url.indexOf('api/v1') > -1,
is_not_register_end_point: !(req.url.indexOf('api/v1/customers') > -1 && req.method === 'POST')
};
if (validate.is_api_v1 && validate.is_not_register_end_point) {
return next.handle(req).pipe(
catchError((err, caught) => {
if (err instanceof HttpErrorResponse && err.status === 401) {
console.log(req.url);
console.log('Injecting Refresh Token');
return this.handle401Error(req, next);
}
// return caught;
})
);
} else {
return next.handle(req);
}
}
handle401Error(req: HttpRequest<any>, next: HttpHandler) {
//-- Test if we are refreshing so we are not stuck in an infinite loop
if (!this.isRefreshingToken) {
this.isRefreshingToken = true;
let refresh_token = ApplicationSettings.getString('refresh_token');
let refresh = this.customer.refreshToken(refresh_token);
return refresh.pipe(
switchMap((tokenResp: LoginResponse) => {
this.customer.setToken(tokenResp);
let access_token = ApplicationSettings.getString('access_token');
let headers = req.headers.set('Authorization', `Bearer ${access_token}`);
return next.handle(req.clone({headers: headers}));
}),
catchError(error => {
ApplicationSettings.setBoolean("authenticated", false);
this.router.navigate(["/login"], { clearHistory: true, queryParams: {
error: 'Your session is no longer valid, please log in again',
}});
return Observable.throw("");
}),
finalize(() => {
this.isRefreshingToken = false;
})
)
}
}
}

Two API call in single sesrvices

First I'm new new to angular 2. I'm trying to call two difference API in single service. But it wont return any value second API 'getCityById' but the API 'getCities' return the value.
Here my code:
import { Injectable } from '#angular/core';
import { Http, Headers,Response} from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
import { Cities } from './cities';
#Injectable()
export class CitiesService {
private CityListUrl = "APIurl";
private CityUrl = "APIurl2";
constructor(private http: Http) {}
getCities(): Observable<Cities[]> {
const headers = new Headers();
headers.append('Access-Control-Allow-Headers', 'Content-Type');
headers.append('Access-Control-Allow-Methods', 'GET,PUT,POST,OPTIONS');
headers.append('Access-Control-Allow-Origin', '*');
return this.http.get(this.CityListUrl,{headers: headers})
.map(this.extractData)
.catch(this.handleError);
}
getCityById(CityId:Number): Observable<any> {
const headers = new Headers();
headers.append('Access-Control-Allow-Headers', 'Content-Type');
headers.append('Access-Control-Allow-Methods', 'GET,PUT,POST,OPTIONS');
headers.append('Access-Control-Allow-Origin', '*');
var params = 'cityid='+CityId;
console.log("____________"+this.CityUrl);
console.log(this.http.post(this.CityUrl,params,{headers: headers})
.map(this.extractData));
return this.http.post(this.CityUrl,params,{headers: headers})
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
console.log(res);
let Cities = res.json();
return Cities || { };
}
private handleError(error: Response) {
console.log(error);
return Observable.throw(error.json().error || "500 internal server error");
}
}
I'm not sure what I'm wrong. Please help with this.