Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 Token: Response for preflight has invalid HTTP status code 400

I have an Angular2/TypeScript application running i Visual Studio Code.

An API running in VS 2015. This is the API project: http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api

I can use the API and create new users, but when I try to login(Use the Token function), then I get the following error: XMLHttpRequest cannot load https://localhost:44305/Token. Response for preflight has invalid HTTP status code 400

The header looks like this:

Request URL:https://localhost:44305/Token
Request Method:OPTIONS
Status Code:400 
Remote Address:[::1]:44305
Response Headers
cache-control:no-cache
content-length:34
content-type:application/json;charset=UTF-8
date:Wed, 10 Aug 2016 19:12:57 GMT
expires:-1
pragma:no-cache
server:Microsoft-IIS/10.0
status:400
x-powered-by:ASP.NET
x-sourcefiles:=?UTF-8?B?QzpcQ2hlY2tvdXRcQVBJXzJ2czJcQVBJXEFQSVxUb2tlbg==?=
Request Headers
:authority:localhost:44305
:method:OPTIONS
:path:/Token
:scheme:https
accept:*/*
accept-encoding:gzip, deflate, sdch, br
accept-language:en-US,en;q=0.8,da;q=0.6,nb;q=0.4
access-control-request-headers:authorization
access-control-request-method:POST
cache-control:no-cache
origin:http://evil.com/
pragma:no-cache
referer:http://localhost:3000/signin
user-agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36

My angular service looks like this:

 loginAccount(account: Account): Observable<string> {        
    var obj = { Email: account.Email, Password: account.Password, grant_type: 'password' };
        let headers = new Headers({ 'Content-Type': 'application/json' });
        let options = new RequestOptions( {method: RequestMethod.Post, headers: headers });

        let body = JSON.stringify(obj);
        console.log('loginAccount with:' + body);

         return this._http.post('https://localhost:44305/Token',  body, options)
                             .map(this.extractData)
                             .catch(this.handleError);
}

When I use the AJAX funtions that a in the API project: http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api then it works fine ?? What am I doing wrong in the Angular POST request ?

like image 785
Benjamin Avatar asked Aug 10 '16 19:08

Benjamin


2 Answers

I found the solution. Thanks to the comments on the API site: http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api

I had to set the correct header for application/x-www-form-urlencoded; charset=UTF-8 and serialize the object i posted. I can´t find an Angular serializer method, so I made my own(copy from another stackoverflow site) in JavaScript.

Here is the final call when the user login on the API and request a token, when using Angular2 & TypeScript:

 loginAccount(account: Account): Observable<string> {        
    var obj = { UserName: account.Email, Password: account.Password, grant_type: 'password' };

        let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' });
        let options = new RequestOptions( {method: RequestMethod.Post, headers: headers });

        let body = this.serializeObj(obj);

         return this._http.post('https://localhost:44305/Token',  body, options)
                             .map(this.extractData)
                             .catch(this.handleError);
}

private serializeObj(obj) {
    var result = [];
    for (var property in obj)
        result.push(encodeURIComponent(property) + "=" + encodeURIComponent(obj[property]));

    return result.join("&");
}
like image 200
Benjamin Avatar answered Oct 05 '22 23:10

Benjamin


I was also facing same issue from last week and searched on google and stack overflow but all solutions in vein. but after lot of reading and investigation we have found below solution, we were facing issue in only POST method,GET called successfully.

Instead of directly passing Options we need to first stringify option object like JSON.stringify(options)

CreateUser(user:IUser): Observable<void> {
        let headers = new Headers();
        headers.append('Content-Type', 'application/json');
        headers.append('Accept', 'application/json');
        let options = new RequestOptions({ headers: headers });
        return this._http.post('http://localhost:22736/api/Employee/Create', **JSON.stringify(options)**)
            .map((res: Response) => {
                return res.json();
            })
            .catch(this.handleError);
    }

It worked for me, Hope it will help others too.

like image 26
Bhushan Laddha Avatar answered Oct 06 '22 00:10

Bhushan Laddha