I am building an ionic app using AWS as a backend (has been challenging!), and for some reason on my user sign-in page, I got this nasty bug that wasn’t there when I was using firebase as the backend. In a nutshell, my side menu has items that should appear based on whether the user is logged in or not. If the user is logged in, the menu should have a logout item. If the user is not logged in, the menu should either not have any options, or a redundant sign-in option.
I got the hard part down, which was setting up AWS Cognito to work the sign-in logic, and setting the correct root page, however, after a user logs in, the menu does not show the logout option.
Funny thing, if I reload the app, the menu does show the logout option. Not sure why. Also weird, after I reload the app and I click the logout button, the correct options for a user that is not logged in do appear in the menu. If someone can take a look and tell me why the menu options only render correctly when I log out and if I log in only after I reload the app, I would be very grateful! Thank you in advance for your time! Code below…
app.component.ts:
import { Component } from ‘@angular/core’;
import { Platform, NavController, MenuController } from ‘ionic-angular’;
import { StatusBar } from ‘@ionic-native/status-bar’;
import { SplashScreen } from ‘@ionic-native/splash-screen’;
import { TabsPage } from ‘…/pages/tabs/tabs’;
import { SignInPage } from ‘…/pages/sign-in/sign-in’;
import { AuthService } from ‘…/services/auth’;
@Component({
templateUrl: ‘app.html’
})
export class MyApp {
rootPage: any;
isLoggedIn //this variable holds the status of the user and determines the menu items;
constructor(platform: Platform,
statusBar: StatusBar,
splashScreen: SplashScreen,
private menuCtrl: MenuController,
private authService: AuthService) {
this.verifyUserstate(); //method to check if a user is logged in
console.log(this.isLoggedIn); //debug line
console.log(this.menuCtrl.get()); //debug line
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
statusBar.styleDefault();
splashScreen.hide();
});
}
onLoad(page: any) {
console.log(“onLoad”);
this.nav.setRoot(page);
this.menuCtrl.close();
}
onLogout() {
this.authService.logout();
this.verifyUserstate();
this.menuCtrl.close();
}
verifyUserstate() {
console.log(“in verify userstate”);
this.authService.isAuthenticated()
.then(() => {
this.isLoggedIn = true; //if a user is logged in = true
this.rootPage = TabsPage;
console.log(this.isLoggedIn); // more debug
})
.catch((error) => {
this.isLoggedIn = false; //if user is not logged in = false
this.rootPage = SignInPage;
console.log(this.isLoggedIn); //more debug
});
}
}
app.html:
<ion-menu [content]=“nav”>
Menu
<button ion-item icon-left (click)=“onLoad(signinPage)” *ngIf="!isLoggedIn">
Sign In
<button ion-item icon-left (click)=“onLogout()” *ngIf=“isLoggedIn”>
Log Out
auth.ts:
import { Injectable } from “@angular/core”;
import { AlertController } from “ionic-angular”;
import { CognitoUserPool, AuthenticationDetails, CognitoUser, CognitoUserSession } from “amazon-cognito-identity-js”;
const POOL_DATA = {
UserPoolId: “xx-xxxx-X_XXXX”,
ClientId: “You do not need to know :)”
}
const userPool = new CognitoUserPool(POOL_DATA);
export class AuthService {
signin(email: string, password: string) {
let message: string;
var authenticationData = {
Username : email,
Password : password,
};
var authDetails = new AuthenticationDetails(authenticationData);
let userData = {
Username: email,
Pool: userPool
}
let cognitoUser = new CognitoUser(userData);
return new Promise((resolve, reject) => {
cognitoUser.authenticateUser(authDetails, {
onSuccess(result: CognitoUserSession) {
console.log(result)
resolve("Success!")
},
onFailure(error) {
let message: string = error.message;
reject(message);
}
}
logout() {
this.getAuthenticatedUser().signOut();
}
isAuthenticated() {
return new Promise((resolve, reject) => {
let user = this.getAuthenticatedUser();
if (user) {
user.getSession((err, session) => {
if(session.isValid()) {
resolve(true);
} else if (err) {
reject(err.message);
}
})
} else {
reject("Not authenticated");
}
});
}
}
Finally, the sign-in.ts file (where the magic of login in happens):
import { Component } from ‘@angular/core’;
import { NgForm } from ‘@angular/forms’;
import { LoadingController, AlertController } from ‘ionic-angular’;
import { AuthService } from ‘…/…/services/auth’;
import { NavController } from ‘ionic-angular/navigation/nav-controller’;
import { MyApp } from ‘…/…/app/app.component’;
@Component({
selector: ‘page-sign-in’,
templateUrl: ‘sign-in.html’,
})
export class SignInPage {
constructor(private authService: AuthService,
private loadingCtrl: LoadingController,
private alertCtrl: AlertController,
private navCtrl: NavController) {
}
onSignin(form: NgForm) {
const loading = this.loadingCtrl.create({
content: “Signing you in…”
});
loading.present();
this.authService.signin(form.value.email, form.value.password)
.then(data => {
this.navCtrl.setRoot(MyApp); /*navigate to myApp again to reverify the
*login status. This sets the right rootPage,
*but I have a feeling here also lies the menu problem.
*/
console.log(data);
})
.catch(error => {
console.log(error);
let alert = this.alertCtrl.create({
title: “Oops”,
message: error,
buttons: [“Ok”]
});
alert.present();
})
loading.dismiss();
}
}