Redirect to login page if response status 401


#1

I want to redirect the user to login page if the status of the response from the api is 401

I’m trying to handle the case of the expired token, the api will respond with 401 response status to the ionic app, the problem is that I can’t get the the json object of this response to check for the status so that I can redirect to the login page.


#2

@EmanShaaban Try to map the response before subscribing to it. Try something like this :

.map((response: Response) => {
         
        if (response.status < 200 || response.status >= 300) {
            throw new Error("Your custom Error, You will catch this later");
        }
        
       else   {
         //successfull logic here
      })

Then you can subscribe to this observable and handle errors.


#3

I need to Globally handle 401 status not just for one route.


#4

@EmanShaaban Why not create this globally in your http service class, for example in your http service for sending post requests u can implement something similar to this :

 doPost(String jsonBody): Observable<any> {

    let headers = new Headers({ 'Content-Type': 'application/json' });
    let options = new RequestOptions({ headers: headers });
    return this.http.post('http://localhost:8080/api', jsonBody, options)
      .map((response: Response) => {
      
        if (response.status < 200 || response.status >= 300) {
          ///your logic here
        }
        
       else {
        
       }
      });
  }

#5

Here is how I handle user authentication. If you follow this pattern, all you have to do is inject the authentication service in whatever service is doing HTTP requests, and call next(false) on its authentication notifier whenever a 401 is encountered. The subscription in the app component will handle all interaction with the navigation system.


#6

I solved this by extending the http service, but now I can’t redirect to login page using NavController from the service!


#7

hey, can you paste your code here? i’m having the same problem


#8

This is not my solution i found it on the internet

at first you should put this file extended-http.service.ts in the providers

import { Injectable, Injector } from '@angular/core';
import { Request, XHRBackend, RequestOptions, Response, Http, RequestOptionsArgs, Headers } from '@angular/http';
import { Observable } from 'rxjs/Observable';
//import { NavController} from 'ionic-angular';
import { Login } from '../pages/login/login';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
import { Events } from 'ionic-angular';




@Injectable()
export class ExtendedHttpService extends Http {
    private router;
    private authService;

    constructor(backend: XHRBackend, defaultOptions: RequestOptions, private injector: Injector, public events: Events) {
        super(backend, defaultOptions);
    }

    request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {

        if (typeof url === 'string') {
            if (!options) {
                options = { headers: new Headers() };
            }
            this.setHeaders(options);
        } else {
            this.setHeaders(url);
        }
        console.log("url: " + JSON.stringify(url) + ", Options:" + options);

        return super.request(url, options).catch(this.catchErrors());
    }



    private catchErrors() {

        return (res: Response) => {

            if (res.status === 401 || res.status === 403) {
                //handle authorization errors
                //in this example I am navigating to login.
                console.log("Error_Token_Expired: redirecting to login.");

                localStorage.removeItem("token");
                this.events.publish('user:logout');
            }
            return Observable.throw(res);
        };
    }

    private setHeaders(objectToSetHeadersTo: Request | RequestOptionsArgs) {

        // if (this.authService == null) {
        //     // this.authService = this.injector.get(AuthService);
        // }
        //add whatever header that you need to every request
        //in this example I could set the header token by using authService that I've created
        //objectToSetHeadersTo.headers.set('token', this.authService.getToken());
        let token = localStorage.getItem("token");
        let head = new Headers({
            'Content-Type': 'application/json',
            'X-Access-Token': token,
        });
        //let options = new RequestOptions({ headers: head });
        if(token){
            objectToSetHeadersTo.headers.set('Content-Type', 'application/json');
            objectToSetHeadersTo.headers.set('X-Access-Token', token);
        }
        
    }
}

and in app.module.ts

import { Http, XHRBackend, RequestOptions } from '@angular/http';
import { ExtendedHttpService } from '../providers/extended-http.service';

and in providers put

  providers: [
    StatusBar,
    yourservice,
    SplashScreen,
    Toast,
    {provide: ErrorHandler, useClass: IonicErrorHandler},
    {provide: Http, useClass: ExtendedHttpService },
  ]

and in app.component.ts constructor subscribe to theses events:

    events.subscribe('user:logout', () => {
      this.rootPage = Login;
    });


    events.subscribe('user:login', (token) => {

      localStorage.setItem('token', token);


    });

#9

thanks!! this worked for me!!