Search code examples
angularrestauthenticationkerberoshttp-authentication

Handling authentication errors in response


From an Angular 4 app, I am calling REST services deployed on Tomcat. For Authentication, I am using Kerberos and it is working as expected for positive cases.

I am facing an issue in handling errors in Angular when Kerberos authentication fails (let's say due to user not existing in AD).

Here is my Angular code

this.restService.executeGET(url)
      .subscribe(
      (response: Response) => {
        let httpResponseStatus = response.status;
        console.log('httpResponseStatus: '+httpResponseStatus+', httpResponseAuthHeader: '+httpResponseAuthHeader)
        //Do something with the Response
      }
      ,
      (error) => {
        //Do something with the Error
        console.log('Authenication Failed' + error); 

      }
      )

 executeGET(url: string) {
    let reqHeaders = new Headers({ 'Content-Type': 'application/json' });
    reqHeaders.append('Accept', 'application/json');
    return this.http.get(url, { headers: reqHeaders });  
  }   

When Authentication succeeds and 200 is returned by the server, '(response: Response) => {}' gets executed as expected. When the response is 401 code with WWW-Authenticate: Negotiate header, neither the 'response' block nor the 'error' block gets executed and browser shows a 'Page can't be displayed' message.

When I look at IE 11 Network tab, it shows that Response has been returned as 401/Negotiate but for some reason it is evading the angular code.

Response Header 1

Response Header 2

It seems that browser is showing the 'Page can't be displayed' message even before the Angular code get a chance to load.

How can I ensure that some code block gets executed even when authentication fails, so that I can take appropriate action like redirecting user to login page.


Solution

  • Just add this check to the service http call

    import 'rxjs/add/operator/catch';
    .catch(e => {
                if (e.status === 401) {
                    return Observable.throw('Not authorized');
                }
                // do other stuff
            });
    

    And in the Component Subscribe

        this.your service.methodname()
            .subscribe(data => {
                // your data
            }, (err) => {
                if (err === 'Not Authorized') { 
    // Do your stuff here
            });
    

    And if you want a global 401 handler for your application service you can check this answer that uses http xhr in Angular Interceptor