My Ionic 4 app uses Firebase to authenticate, and data is stored in local storage after logging. Here’s the flow:
User A logs in
User A’s info is retrieved from Firebase, then stored locally in storage
User A logs out, and his info is cleared from storage by calling storage.clear()
User B logs in, but can still see User A’s info
How can I completely clear a user’s info after logging out, so that it doesn’t show when another user logs in???
The code that reads data from the storage to display is in the ngOnInit() function. I noticed that when logging in again as a different user, ngOnInit() isn’t called, so could that be why it’s not showing the new user’s data?
After logging, the following retrieves the user’s business info…
///home.ts
//The following code used to be in ngOnInit(), but wasn't called after relogging in as a different user, so I moved it here. It gets called each time, but .getFromLocal() doesn't call the service's constructor after the 2nd login
ionViewDidEnter()
{console.log("businessaccount ionViewDidEnter");
this.segment = 'requests';
this.businessSrv.getFromLocal().subscribe((b)=>{
this.business=b;
console.log(this.business);
if (this.business) this.getInfo();
})
}
//business.service.ts
private businessSubject:BehaviorSubject<Business> = new BehaviorSubject<Business | undefined>(undefined);
//this constructor is called after the first login, but not after logging out and logging in as a different user
constructor(private fbServ: FirebaseService, private _storage: Storage)
{
console.log("LOGGED IN USER: ",this.fbServ.getLoggedinUser());
this.fbServ.get('businesses', ['userId|==|'+this.fbServ.getLoggedinUser().email]) //gets the business info from Firebase
.subscribe((biz)=>{
if (biz == undefined) return null;
console.log(biz[0]);
this.businessSubject.next(biz[0] as Business);
return this._storage.set('business',biz[0]);
})
}
getFromLocal(): Observable<Business | undefined>
{
return this.businessSubject.asObservable();
}
setInLocal(biz: Business): void
{
this.businessSubject.next(biz);
this._storage.set('business',biz);
console.log("biz saved:", biz);
}
getFromLocal can just return this.businessSubject. asObservable isn’t necessary;
FirebaseService.get should be generic (like HttpClient.get is), which will eliminate the need for the as Business cast;
HomePage is leaking subscriptions. There are lots of ways to deal with this; I’m partial to @ngneat/until-destroy;
The good news is that you’ve already got the infrastructure in place for communicating externally-initiated changes to the active Business to places like HomePage. However, the chain seems to be broken by the fact that FirebaseService.getLoggedInUser doesn’t itself expose an Observable (that can be triggered upon logout). If you augment getLoggedInUser with a watchLoggedInUser that exposes an Observable<User>, and somehow have logoutUser cause it to emit undefined, then BusinessService can subscribe to that in its constructor, instead of simply taking a snapshot.
User A logs in
User A’s info is retrieved from Firebase, then stored locally in storage.
User A logs out, and his info is cleared from storage by calling storage.clear()
I prefer JWT to cookies for everything, because they’re stateless and are built from well-tested cryptographic blocks. As for how to store them client-side, I have yet to encounter a situation where I was tasked to worry about multiple users sharing a physical device, so I just save them using Ionic Storage. If you do care about that situation (white hat and black hat using the same Ionic app on the same device), you could look into something like NativeStorage, although I tend to simply assume that anybody with physical access to a device can get at anything stored on it.
I hope this won’t be considered hijacking @obinnae post… I’ve implemented JWT for an e-commerce ionic app am building. Is it necessary to have refresh tokens and what would necessitate them… Or what strategy would you implement
Thanks for your help, @rapropos. I’ve followed your bulleted suggestion, though yet to fix the leaking subscriptions. I’m currently unsubscribing from ngOnDestroy(). How else could you unsubscribe the subscriptions besides the until-destroy plugin?