User authentication using BehaviorSubject


#1

Hi,

I am new to Ionic and looking to implement authentication.
Once the user logs in I want to redirect him to Dashboard and on every page change, I want to call login silently and check for any role change so that I can handle UI accordingly.

Below is what I have tried


* loign.html

<form novalidate #loginForm="ngForm" (ngSubmit)="onLogin(loginForm)">
</form>

login.ts

onLogin(form: NgForm) {
	console.log(form);
	this.auth.doLogin(this.login);
}

* auth.ts

public activeUser = new BehaviorSubject(null);

doLogin(params) {
	this.api.login(params).then(data => {
		this.activeUser.next(data);
	});
}

* api.ts

login(params: any) {
	return this.doRequest('login', 'POST', '', params.username, params.password);
}

doRequest(action: string, method: string, postData: any, username ?  : string, password ?  : string) {
	return new Promise((resolve, reject) => {
		if (method == 'GET') {
			this.http.get('/api/' + action, {
				headers: new HttpHeaders().set('Content-Type', 'application/json')
			}).subscribe((data) => {
				resolve(data);
			}, (error) => {
				reject(error);
			});
		} else if (method == 'POST') {
			this.http.post('/api/' + action, postData, {
				headers: new HttpHeaders().set('Content-Type', 'application/json')
			}).subscribe((data) => {
				resolve(data);
			}, (error) => {
				reject(error);
			});
		}
	});
}

* app.component.ts

this.inProess = true;
DB.initDB().then(() => {
	this.localStorage.get('userDetails', false, true).then((data) => {
		if (data) {
			this.rootPage = 'DashboardPage';
		} else {
			this.rootPage = 'LoginPage';
		}
	}).then(() => {
		auth.activeUser.subscribe((data) => {
			console.log('data from subscriber => ', data);
			if (data) {
				if (data.userId > 0)
					auth.setUserDetails(data);

				this.redirectPage();

				if (this.inProess != true)
					this.nav.setRoot('DashboardPage');
			} else {
				if (this.inProess != true)
					this.nav.setRoot('LoginPage');
			}
		});
	});
	this.inProess = false;
});

In this Login page is called and then redirected to Dashboard, I want the user to directly redirected to Dashboard.
Can someone help me achieve the same?


#2

Some tips:

in exactly one place in your code, put

export const enum RootPageOptions {
   START_PAGE = 'nameOfStartPage',
   LOGIN_PAGE  = 'nameofLoginPage',
  // any other pages
}

Then where needed, put this.nav.setRoot(RootPageOptions.START_PAGE) and so on. This way, you never have any typos, and can control your routing by changing the string enums whenever you change your page names in your code.

Put your BehaviorSubject in your auth provider. (Though actually a ReplaySubject is probably better, take a look at that.) Put in your auth provider

logout() {
   this.activeUser.next(null);
   // logout from server
}
getActiveUser(): Observable<typeOfUser> {
   return this.activeUser.asObservable()
}

Then in each page’s ionViewWillEnter, or in ionViewCanEnter, test the value of getActiveUser, and render the page appropriately.

Your code in doRequest commits the explicit-construction promise antipattern and needs to be rewritten.

Hope this helps.


#3

But how do I handle it in app.component.ts?
I am confused with that piece


#4

Modify the sample code in the NavController API.