Skip to main content
Version: 3.x

Auth Connect Angular

This tutorial follows on from the Installation and auth provider guides (Auth0, AWS Cognito, Azure AD B2C or Okta) and integrates functionality for login, logout and the user's authenticated state in your Ionic Angular application.

Build Time Options

The configuration settings (such as redirectUri) of your auth provider will change depending on your target environment (e.g. production, staging or development). Settings should not be hard coded in your application and a good practice is to use Angular's Environment files to allow these settings to be set at build time.

Revisiting our AuthenticationService class, the IonicAuth object has been moved to environment.ts:


_10
import { IonicAuth, IonicAuthOptions } from '@ionic-enterprise/auth';
_10
import { authOptions } from '../../environments/environment';
_10
_10
export class AuthenticationService extends IonicAuth {
_10
_10
constructor() {
_10
super(authOptions);
_10
}
_10
}

In the projects environment.ts file we add:


_12
import { IonicAuthOptions } from "@ionic-enterprise/auth";
_12
_12
export const authOptions: IonicAuthOptions = {
_12
authConfig: 'FILL_IN',
_12
platform: 'FILL_IN',
_12
clientID: 'FILL_IN',
_12
discoveryUrl: 'FILL_IN',
_12
redirectUri: 'FILL_IN',
_12
scope: 'FILL_IN',
_12
logoutUrl: 'FILL_IN',
_12
iosWebView: 'FILL_IN'
_12
};

To keep development settings separate from production you should apply similar code to your environment.prod.ts file using the settings for the production instance of your auth provider.

Run Time Options

Authentication options will also change at runtime depending on where your application is run (eg Native vs Web). In the AuthenticationService class we can dynamically initialize options in the constructor:


_10
import { Platform } from '@ionic/angular';
_10
import { nativeIonicAuthOptions, webIonicAuthOptions } from '../../environments/environment';
_10
...
_10
constructor(platform: Platform) {
_10
super(platform.is('hybrid') ? nativeIonicAuthOptions : webIonicAuthOptions);
_10
}

Here we have taken our authOptions object and refactored to provide 2 objects for native and web.

Login

Your application is now ready to trigger a login flow. Lets create a button for this:


_10
<ion-button (click)="login()">Sign In</ion-button>

And call the login method of IonicAuth:


_10
import { AuthenticationService } from '../authentication/authentication.service';
_10
...
_10
constructor(private authenticationService: AuthenticationService) { }
_10
_10
async login(): Promise<void> {
_10
await this.authenticationService.login();
_10
}

You can now run your application and test the login flow. It is worth noting that the login page for your auth provider will open in its own window (and if already logged in will open and close immediately) and once a successful login is achieved will return a token using the redirectUri property back to your application.

note

A common mistake is an incorrectly set redirectUri so be sure to test for development (such as when run via ionic serve) and production (where Auth Connect depends on the deep linking setup in your project) to ensure the login page closes successfully.

Logout

Similar to login, test your logout flow by adding a button:


_10
<ion-button (click)="logout()">Sign Out</ion-button>

Followed by calling the logout method of IonicAuth:


_10
async logout(): Promise<void> {
_10
this.authenticationService.logout();
_10
}

Authenticated?

Whilst Auth Connect provides a isAuthenticated method to determine whether a user is authenticated or not, your application will likely have multiple places that need to reactively change based on this state. We can extend our authenticationService to emit events whenever the authentication state changes:


_33
import { Injectable, NgZone } from '@angular/core';
_33
import { IonicAuth } from '@ionic-enterprise/auth';
_33
import { Platform } from '@ionic/angular';
_33
import { BehaviorSubject, Observable } from 'rxjs';
_33
import { nativeIonicAuthOptions, webIonicAuthOptions } from '../../environments/environment';
_33
_33
@Injectable({
_33
providedIn: 'root'
_33
})
_33
export class AuthenticationService extends IonicAuth {
_33
private authenticationChange: BehaviorSubject<boolean> = new BehaviorSubject(false);
_33
public authenticationChange$: Observable<boolean>;
_33
_33
constructor(platform: Platform, private ngZone: NgZone) {
_33
super(platform.is('hybrid') ? nativeIonicAuthOptions : webIonicAuthOptions);
_33
this.authenticationChange$ = this.authenticationChange.asObservable();
_33
this.isAuthenticated().then((authenticated) => { this.onAuthChange(authenticated); });
_33
}
_33
_33
public async onLoginSuccess(): Promise<void> {
_33
this.onAuthChange(true);
_33
}
_33
_33
public async onLogout(): Promise<void> {
_33
this.onAuthChange(false);
_33
}
_33
_33
private async onAuthChange(isAuthenticated: boolean): Promise<void> {
_33
this.ngZone.run(() => {
_33
this.authenticationChange.next(isAuthenticated);
_33
});
_33
}
_33
}

note

The events from IonicAuth run outside of Angular's change detection system so to get correct behavior when binding to a view we need to ensure that NgZone is run.

We can now update our buttons to show/hide based on our authenticated state:


_10
<ion-button [hidden]="(authenticationChange$ | async)" (click)="login()">Sign In</ion-button>
_10
<ion-button [hidden]="!(authenticationChange$ | async)" (click)="logout()">Sign Out</ion-button>

In the code behind the view:


_10
import { Observable } from 'rxjs';
_10
...
_10
public authenticationChange$: Observable<boolean>;
_10
_10
constructor(private authenticationService: AuthenticationService) {
_10
this.authenticationChange$ = authenticationService.authenticationChange$;
_10
}

Next Steps

Your application is now functional but there are some recommended next steps such as: