Reset app on logout. Pop pages from nav stack and delete services data

When a user logs out of my app and another user logs in I want it to act like it hasn’t been used before.
Currently all the pages that have been opened by the first user are still in memory and the same with the injected services. This mean user 2 sees user 1 data.
This is a security concern.

I read that I could use this.navCtrl.navigateRoot(’/login’); to deal with the pages by popping them from the nav stack. Not sure if this works yet as I need to sort the services.

How can I remove all the instantiated/injected services?
I am storing a variable in the services (tenantId) and it is causing havoc as it is not reset at logout.

This is a very uncommon case for the app to have two users on the same device. But I need to deal with it and it is messing up my testing.

Basically I just want to reset the whole app to its initial state on log out.

I’m assuming you V5 or the latest release of ionic/angular?

If so, this really wont be possible since we’re dealing with browser history.

You could use a mix of both replaceUrl and navigation guards in your app to prevent any unintended navigation.

Your logout action should call upon services to reset state and content, including clearing tenantid etc

Dont try to solve this by trying to mess with internals of the framework such as deleting services or the likes of it

Basically u need to manage the full lifecycle of data, not just creation change but also full removal and wire it up to all user actions

Yes Ionic and Ionic/Angular v5. Should have stated that.
Ok I will look into replaceUrl. I haven’t used that before.

Someone suggested I just call window.location.reload(true); on logout so I will try that too.

Thanks, I will look into manually resetting the state myself.

Someone suggested I just call window.location.reload(true); on logout so I will try that too.
It might be a quick hack I can use for an uncommon scenario.

That is quite horrible advice to implement. It basically says: I have no clue what is happening, lets reload.

I suspect you really need to grasp the angular thinking with state patterns, because if you set this right now, you won’t have other issues down the road other users seeing strange states, components not updated and other related matters.

1 Like

Yes I agree.
Hence the word “hack”.

I will do some more research. Any links to good resources appreciated.

1 Like

It all depends on how u implemented getting and setting data from your components to your service

U use page lifecycle hooks? BehaviorSubject?

Either way, the logout action is fairly distinct method in your code and the. U just need to call a setter in all services that clears the variables

I am actually changing it to have a single service that contains the state and all the other services simply subscribe to observables (BehaviorSubject) from this central state service.

This will may make it easier to reset the services and they may actually not need to be reset at all.

Still not sure how I will do the page variables yet.

Put in state or let it subscribe to a state provider

Like User state or LoginStatus state.

1 Like

Apologies if you’ve seen this a million times, but your situation here (multiple users logging in and out on the same device) is the precise reason I developed this idiom. If you combine it with the route guards suggested by @mhartington, I think you’re done. You shouldn’t have to care about unwanted things in the browser history, because attempts to revisit those pages would get caught by a CanActivate guard and can be redirected to the login page.

1 Like

Nice. I had not seen before. Thanks, I will look at your post in more detail.

it’s legendary. Don’t forget to like it

1 Like

Ah, yes this is pretty similar to what I am doing now with my “state service” (except you have better naming :wink: ).
I just had not implemented it for everything as I only added it recently. So I still had local variables in the pages.

I have been slowly moving to a fully managed state service but had just not got there yet.
I am now starting to see some more of the advantages.

I don’t think there’s anything wrong with that; I do it too. The post was too long as it is, but ProfileEditPage doesn’t have to peek - it can watch as well:

@UntilDestroy()
class ProfileEditPage {
  profile?: Profile;
  constructor(private profiler: ProfileService) {
    this.profiler.watchProfile().pipe(untilDestroy(this))
      .subscribe(profile => this.profile = profile);
  }
}

If the user logs out from anywhere, even if this page is still cached somewhere in the DOM, the local variable goes undefined immediately, as it is still receiving updates until torn down by ngOnDestroy.

Ok that makes sense for something like profile or current tenant data.

How about if I am doing pagination or a search from the page?
Currently I have it reloading every time the page is entered which is not particularly efficient.
Originally I had this loading the data in ngOnInit() which was causing the problems with users logging in and out.
Would I just store all this in the service or in the single state service and access as an observable?

I understand state management is a big topic. Still learning I’m afraid.

e.g.

async ionViewWillEnter() {
    this.getNewsItems(true);
  }

getNewsItems(resetList: boolean = false) {
    this.isLoading = true;

    if (resetList) {
      this.newsItems = [];
      this.lastNewsItem = null;
    }

    this.newsFeedService.getNewsItems(this.pageSize, this.lastNewsItem).then(newsItems => {
      this.newsItems = this.newsItems.concat(newsItems);
      if (newsItems.length === this.pageSize) {
        this.lastNewsItem = this.newsItems[this.newsItems.length - 1];
      } else {
        this.lastNewsItem = null;
      }
      this.isLoading = false;
    });
  }

I would say yes. Anything you fetched before and which is relevant for the user, keep it in the state. Save the user’s bandwidth, time and battery.

And in that case, you may not want to get the items at ionViewWillEnter, but in ngOninit (get rid of the then, if possible)

1 Like

I can think of two possible approaches here, and nothing immediately suggests one over the other:

A. Keep newsItems in the user profile object.
B. Have them separate, but also have whatever page you quoted watch the user profile and blank newsItems when the user profile changes.