Listen for api auth errors in a DispatchPage


#1

Hello.

Sometimes things go wrong, and I want to listen to my Api and Auth services for authentication errors, so if authentication expires for some reason (token expired, remote logout, bugs, etc.) and in that case, push the user to LoginPage or even just show an alert. Point is, access the view layer.

In pure Angular I would use a DispatchPage, a component that contains all other page components. So, the DispatchPage is always loaded and can handle this kind of logic.

But in Ionic, even if I use create a DispatchPage for my rootPage and begin navigation from there, livereloading or accessing the page directly (ie. by url) will load a given page directly, and DispatchPage is never loaded.

So is there a way to make sure Dispatch Page is always loaded in any navigation scenario, or perhaps someone has a better solution for this kind of behavior in general?

AppComponent would seem a good place for this, but NavController, AlertController, etc. are not available from here.


#2

Are you talking about AngularJS? That approach is considered bad style in Angular. Use a provider. In the provider, set an Observable to listen to whatever changes you need and act accordingly.

Handle data in providers. Render data in pages. So for datatype X, you have a provider. In that provider, you listen to a stream from your auth provider. If the user logs out, the datatype X provider takes whatever steps it needs for datatype X. Could be erasing all the memory. Could be doing nothing.


#3

Like mentioned, I have Auth and Api services (or providers), and when I mentioned listening to them, I was already talking about Observables, and the DispatchPage was where I would listen to them from. I never used AngularJS, so this should be a pretty standard approach in Angular.

Again, the DispatchPage approach doesn’t seem meaningful in the Ionic framework, which is why I mentioned the App Component. I don’t know if the App Component is actually considered a provider, but it seems to be the only centralized place to set up App-wide code, like listening for global Auth and Api errors.

I don’t know if you’re actually rather suggesting writing up the same subscription to Auth and Api Observables from each and every page in an app.

I might just go with a @ViewChild for NavController in the App Component, that will at least be better than many others who seem to outright hack their way to the NavController from their providers, and it’s actually in the documentation http://ionicframework.com/docs/api/navigation/NavController/


#4

Why can’t you just define a BehaviorSubject that listens to and publishes your auth, and then you setRoot=Homepage if you next null in your BehaviorSubject? I guess I don’t see why this takes more than 2 lines in your auth provider. Or if you need a bit more security, 2 lines on each page inside ionViewCanEnter or something.


#5

That’s fine for a simple app with a linear navigation flow.

However, you might want to handle 401 Unauthorized responses from your Api (token expired, remote logout, etc.). At this stage you might be anywhere in your app, not just about to navigate to a page (ionViewCanEnter).

Secondly, if I remember correctly, ionViewCanEnter is not triggered if you manually access the url or (live)reload the page, meaning you might enter a page that is getting bad or no Auth data, either making it stale or throw an error if you try to access auth data. This is another scenario, where you’d want to redirect back to the root or login page.


#6

No, it’s explicitly nonlinear/reactive. For example, in the app I’m building now, each Redux slice of state listens for the logout event, and resets its data space to a default value. That can take place in any order, no matter which pages the user currently has open.

Your use case is simpler. You set a Subject to listen to Auth changes and API errors (using combineLatest or similar operator) and then anywhere you need to listen, you listen. So you only make the expensive call to the database once, and everywhere else listens to your Subject. Or you could use the Ionic Events framework if you don’t like rxjs Subjects.

If you need to rerooute someone who has an explicit URL, my advice is to wait until Ionic 4 is out, because PWA routing is still a mess. But if you need it now, just put your auth listener in ionViewWillEnter, and only render data in that page with Observables that fire only if there is auth.

authGate<T>(observableToGate: Observable<T>): Observable<T> {
   if (putAuthCheckHere) return observableToGate
  else return Observable.of();
}

You could wrap your page Observables in that if you need to ensure no data is visible unless the user is authed.


#7

This is what I’m doing already. And in case there is no auth, I get a “blank” page and no meaningful way for the user to get back to safety (where he can login again).

BehaviorSubject in Auth is also what I’m doing already.

The “nonlinear” issue here is, to expect auth to break (BehaviorSubject.next(null) if you like) at any time.
You are kind of suggesting my own solution already, App Component listening for the BehaviorSubject to turn null, and then changing the page. My original question was related to accessing the NavController to call the setRoot that you suggested yourself.

So is that your suggestion? Importing NavController into App Component via @ViewChild, like I mentioned in the beginning. Or would you do the setRoot somewhere else/differently?

Otherwise I am misunderstanding your replies.