AWS Amplify Authenication using pre-built UI components


Having trouble setting up AWS Amplify Authenication using the pre-built UI component which automatically renders a sign in page in an Ionic / Angular app.

Having followed the guide here:

It tells you to replace the contents of app.component.html with the following:

<amplify-authenticator *ngIf="authState !== 'signedin'"></amplify-authenticator>

<div *ngIf="authState === 'signedin' && user" class="App">
    <div>Hello, {{user.username}}</div>
    <!-- This is where you application template code goes -->  

Therefore I assumed that the previous contents:


would be placed inside as below:

<amplify-authenticator *ngIf="authState !== 'signedin'"></amplify-authenticator>

<div *ngIf="authState === 'signedin' && user" class="App">
    <div>Hello, {{user.username}}</div>
    <!-- This is where you application template code goes -->  

Implementing the <amplify-authenticator> this way seems to interfere in how Ionic / Angular change detection works.

For example, a simple click function that changes some text in the template no longer automatically updates the text.

  someText: String = '';

    this.someText = 'Some text to write out';

<button (click)="getSomeText()">Get some text</button>
<p>{{ someText }}</p>

If I switch on Chrome DevTools, the text change is detected as I guess the viewport size change triggers it???

If I move the <ion-app> back outside the <div> then the someText property will change on click of the button, as expected.

So where should the be placed when using the prebuilt UI from AWS Amplify?


here is how I handled it

<amplify-authenticator username-alias="email"> </amplify-authenticator>
<div style="height: 100%" *ngIf="user">
  <ion-header [translucent]="true">
      <ion-title> Blank </ion-title>

  <ion-content class="ion-padding">
    <div>TASKS: {{ user?.attributes?.email }}</div>
      <div *ngFor="let t of ($tasks|async); let i = index">
            <p>{{ t?.title }}</p>
            <p>{{ t?.description }}</p>
            <p id="id">{{t?.id}};{{ t?.title }}</p>
<ion-footer class="ion-padding">

import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { onAuthUIStateChange } from '@aws-amplify/ui-components';
import { DataStore, Auth } from 'aws-amplify';
import { Task } from '../../models';

import { defer } from 'rxjs';
  selector: 'app-home',
  templateUrl: '',
  styleUrls: [''],
export class HomePage implements OnDestroy, OnInit {

  private unsubscribeAuth;
  private curAuthState;
  private user;

  constructor(private ref: ChangeDetectorRef) {}
  ngOnInit(): void {

    this.unsubscribeAuth = onAuthUIStateChange((authState, authData) => {
      this.curAuthState = authState;
      this.user = authData || null;

      // to update the user state

      if (this.user) {
        this.$tasks = defer(() => this.getData());

  ngOnDestroy(): void {

  async getData() {
    return await DataStore.query(Task);

Thanks for the reply Aaron.

So far I’ve tried this after finding a post in the Github pages:


import { Component, ChangeDetectorRef, NgZone } from '@angular/core';
import { onAuthUIStateChange, CognitoUserInterface, AuthState } from '@aws-amplify/ui-components';

  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss'],
export class AppComponent {

  user: CognitoUserInterface | undefined;
  authState: AuthState;

  constructor(private ref: ChangeDetectorRef, private _ngZone: NgZone) {}

  ngOnInit() {
    onAuthUIStateChange((authState, authData) => {
      this.authState = authState;
      this.user = authData as CognitoUserInterface;
      if (!this.ref['destroyed']) {
        // Added the line below as bug in AWS Amplify documentation => this.ref.detectChanges());
        // Original
        // this.ref.detectChanges();

  ngOnDestroy() {
    return onAuthUIStateChange;

Solution in Github issues page:

Adding the ngZone line appears to fix the change detection issues caused by onAuthUIStateChange().

Then in app.component.html I’ve just added the ngIf to the <ion-app> itself. Therefore if a user isnt logged in, they’ll just see the Amplify pre-built UI sign in page. Then after sign in, they’ll see the contents of <ion-app>


<amplify-authenticator *ngIf="authState !== 'signedin'"></amplify-authenticator>
<ion-app *ngIf="authState === 'signedin' && user">

I’ve raised with AWS support and they are looking into it, so I’ll see what solution they come back with.

it doesn’t make any sense to wrap the ion-router-outlet ? Where did you even get the idea that was a valid pattern to use?

The code I posted is from a working example; not sure what the issue is you are having if you use the code I provided… or you could just wait to see what you get back from amazon.

I haven’t tried your code, but assume it would be a good approach.

The code I’ve posted above is what I currently have working based on the AWS Amplify documentation and the extra line that fixes the change detection issues it causes.

The ion-router-outlet is wrapped in the ion-app component by default when you create an ionic app with the blank template.

I am saying it doesn’t make sense to wrap the router with the amplify code? But if it works for you the good for you

Yeah I thought it seemed strange too.

This documentation has the template outside of the <amplify-authenticator>

      My App

If using this approach, clicking the signout button doesnt remove / hide any of the app pages and therefore doesnt show the Amplify sign in UI in its place.

This documentation, however, shows it implemented differently:

<amplify-authenticator> is placed outside of the app ‘template’ code.

<amplify-authenticator *ngIf="authState !== 'signedin'"></amplify-authenticator>

<div *ngIf="authState === 'signedin' && user" class="App">
    <div>Hello, {{user.username}}</div>
    <!-- This is where you application template code goes -->  

I therefore presumed that the <ion-app> code should be placed in the space where the comment is.

When using this approach, clicking the sign out button does remove / hide the app pages from view and brings up the Amplify sign in UI.

I’m not sure there is any negative implications for removing / including the <ion-app> component in this way?

This is similar to how I have implemented it and it works fine… not sure why you are saying it doesn’t work. I have provided working source code, if you have code that shows it doesn’t work then you should provide it so that others arriving on this page are not confused.

@aaronksaunders - For some reason when implementing it as AWS Amplify suggest, I get issues with change detection not working. It only works after the ngZone line I mentioned earlier.