Home > Mobile >  How to handle properly error response to preflighted request in Angular
How to handle properly error response to preflighted request in Angular

Time:01-28

I want to:

  • use "Authorization: Bearer token" header in my angular app, to control access to data served by backend server, and
  • display error messages sent by server in angular app, in case user is not authorized to access data.

What I do:

  • I send request from angular app (client) to backend server (php).
  • Request includes "Authorization: Bearer token" header so it is preflighted.
  • When server sends response with 200 response code there is no problem.
  • When server sends response with error response code (eg. 401 or 403) Angular client doesn't receive server response, All I see in console is error:
Access to XMLHttpRequest at 'http://localhost/index.php' 
from origin 'http://localhost:4200' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: 
No 'Access-Control-Allow-Origin' header is present on the requested resource.

I have checked, that when I use simple request (without "Authorization: Bearer token" header) and server responds with error code, angular client receives full response with error code, like in example below:

HTTP/1.1 401 Unauthorized
Date: Thu, 27 Jan 2022 23:24:29 GMT
Server: Apache/2.4.46 (Win64) OpenSSL/1.1.1g PHP/7.4.11
X-Powered-By: PHP/7.4.11
Access-Control-Allow-Origin: http://localhost:4200
Access-Control-Allow-Methods: HEAD, GET, POST, PATCH, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token, Authorization
Content-Length: 47
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8

{"code":401,"message":"unauthorised: no token"}

Below two cases:

  1. angular client code without "Authorization: Bearer token" header - it is working fine
  login(login:any){
    console.debug("login",login);
    let params = new HttpParams({fromObject:{"login":login}});
    console.debug("params",params);
    const observable = this.HTTP.post( this.path, params ); // <===== simple request, no problem
    observable.subscribe((response:any)=>{
      console.debug("response",response);
      if(response.code == 200) {
        let token = JSON.parse(response.message);
        this.userToken = token;
        this.loginErrorMessage = "";
      } else {
        this.userToken = "";
        this.loginErrorMessage = "(" response.code ") " response.message
      }
    })
  }
  1. angular client code WITH "Authorization: Bearer token" header - here a I have a problem
  login(login:any){
    console.debug("login",login);
    let params = new HttpParams({fromObject:{"login":login}});
    console.debug("params",params);
    const observable = this.HTTP.post( this.path, params ,{ headers: {"Authorization":"Bearer "   this.appToken}});
    // const observable = this.HTTP.post( this.path, params ,{ headers: {"MyHeader":"my-header-value"}});
    // const observable = this.HTTP.post( this.path, params );
    observable.subscribe({
      next:(response:any)=>{
        console.debug("response",response);
        if(response.code == 200) {
          let token = JSON.parse(response.message);
          this.userToken = token;
          this.loginErrorMessage = "";
        } else {
          this.userToken = "";
          this.loginErrorMessage = "(" response.code ") " response.message
        }
      },
      error:(error:any)=>{
        console.debug("error",error);
        this.userToken = "";
        
        this.loginErrorMessage = error.statusText   ": "   error.message;
        // "Http failure response for http://localhost/index.php: 0 Unknown Error"
        // this is response from browser I think, and for sure it is not response from server
        // in addition to that I don't see any response headers in browser developer panel
      }
    })
  }

server side (php) headers

$http_origin = $_SERVER['HTTP_ORIGIN'];
header("Access-Control-Allow-Origin: $http_origin");
header('Access-Control-Allow-Methods: HEAD, GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token, Authorization');

Is it possible to use "Authorization: Bearer token" header in Angular client request and read response from server with response code other than 200?

CodePudding user response:

I have a server which authenticates similarly. My request looks a little like this:

import {HttpClient, HttpHeaders} from "@angular/common/http";

//...

const body = {
    "username": form.username,
    "password": form.password
}
this.http.post<any>(
    '/login',
    body, 
    {headers: new HttpHeaders({"Authorization": token})}).subscribe({
        next: data => {
            switch (data.status) {
                case 'ok':
                    //Do stuff
                default:
                    //Error
            }
        },
        error: error => {
            //ERROR!
        }
    });

CodePudding user response:

You'll need to handle the error. Right now in the above code, you are only passing in the success handler function. You need to also pass in the error handler function and pass it the error object parameter.

Here is a link you might find useful on this topic. RxJs Error Handling

  •  Tags:  
  • Related