Angular - loginWithRedirect() not working

Hello! I am having trouble with properly integrating Auth0 into my Angular application.

I followed this tutorial to integrate Auth0 into my Angular application, the one from the Auth0 docs. I made sure that I followed all of the instructions correctly.

Signing up for an account works, but after signing up, I cannot log in. When executing loginWithRedirect() after creating an account, it does not launch the login window. It instead takes me back to my app with isAuthenticated$ set to false. When I look at the client authentication history, I see this:

It says that I had a successful login, but the Identity Provider is N/A. Furthermore, when I look at the success details, Connection is also N/A and “connection_id” is blank. I do not know if this has anything to do with my problem.

I have looked through the Auth0 docs and searched on Google for answers as to why isAuthenticated$ always returns false after calling loginWithRedirect(). I have noticed that many people have encountered and solved this problem with many different solutions, but none of those solutions fix my problem.

It is worth noting, however, that if I execute loginWithPopup() with specific checks that I found online beforehand, it authenticates fine with isAuthenticated$ set to true. I provided my code at the end of this post with how loginWithPopup() successfully works for my app.

I do not understand why loginWithRedirect() always returns isAuthenticated$ as false no matter what solutions I find online. I have provided my code below.

I am currently using version 2.0.1 of auth0/auth0-angular.

environment.ts (I have MY_DOMAIN, MY_CLIENTID and MY_AUDIENCE filled in correctly in my app)

export const environment = {
  production: false,
  auth0: {
    domain: 'MY_DOMAIN',
    clientId: 'MY_CLIENTID',
    redirect_uri: window.location.origin,
    audience: 'MY_AUDIENCE'
  }
};

app.module.ts

import { AuthModule } from '@auth0/auth0-angular';
import { environment as env } from '../environments/environment';
// ...
@NgModule({
// ...
    AuthModule.forRoot({
      domain: env.auth0.domain,
      clientId: env.auth0.clientId,
      authorizationParams: {
        redirect_uri: env.auth0.redirect_uri,
        audience: env.auth0.audience
      },
      cacheLocation: 'localstorage'
    }),
// ...
})

login.component.html

<div class="container login-container">

  <div class="row">
    <h1 align="center">
      TITLE
    </h1>
  </div>

  <div class="row justify-content-center">
    <button mat-flat-button
            class="login-button"
            type="button"
            (click)="attemptLogin()">
      Login or Sign Up (Auth0)
    </button>
  </div>

  <div class="row justify-content-center">
    <button mat-flat-button
            class="login-button"
            type="button"
            (click)="logout()">
      Logout
    </button>
  </div>

</div>

login.component.ts (note that logout() works)

import { Component, OnInit, Inject } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService, User } from '@auth0/auth0-angular';
import { OnlineStatusService, OnlineStatusType } from 'ngx-online-status';
import { DOCUMENT } from '@angular/common';


@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {

  constructor(
    public auth: AuthService,
    private router: Router,
    private onlineStatusService: OnlineStatusService,
    @Inject(DOCUMENT) public document: Document
  ) {

  }

  ngOnInit(): void {
    this.auth.user$.subscribe((value: User | null | undefined) => {
      console.log("User:", value);
    });

    this.auth.isAuthenticated$.subscribe((value: boolean) => {
      console.log("Authd:", value);
    });
  }

  // attempt to login with the entered credentials
  // solution from https://community.auth0.com/t/isauthenticated-is-always-false/84794/3
  attemptLogin(): void {
    this.auth.isAuthenticated$.subscribe((value: boolean) => {
      if (!value) {
        let query: string = window.location.search;
        let shouldParseResult: boolean = query.includes("code=") && query.includes("state=");
        if (shouldParseResult) {
          try {
            this.auth.handleRedirectCallback().subscribe((value) => {
              console.log("Logged in!", value);
            });
          } catch (err: unknown) {
            console.log("Error parsing redirect:", err);
          }
          window.history.replaceState({}, this.document.title, "/");
        }
        else {
          this.auth.loginWithRedirect().subscribe((value: void) => {
            console.log("Logging in...", value);
          });
        }
      }
      else {
        this.router.navigate(['home']);
      }
    });
  }

  // log out of account and go back to login screen
  logout(): void {
    if (this.onlineStatusService.getStatus() === OnlineStatusType.OFFLINE) {
      this.router.navigate(['login']);
      return;
    }
    this.auth.logout({
      logoutParams: {
        returnTo: this.document.location.origin
      }
    });
  }
}


01/24/2023 update: I think I know what is happening. When a user is unauthenticated in both my app and on Auth0, loginWithRedirect() works. After logging in, Auth0 says that I am authenticated, taking me back to my app. However, for some reason, in my app, it says that I am not authenticated. This then causes loginWithRedirect() to execute again. However, Auth0 says that I am already authenticated, taking me back to my app. This causes an infinite loop where my app says that I am unauthenticated, launching loginWithRedirect(), while Auth0 says that I am authenticated, taking me back to my app.

Essentially, for some reason, loginWithRedirect() causes my app to never recognize a user as authenticated, while the Auth0 API does when logging in. Note that this does not happen with AuthGuard. With AuthGuard, authentication recognition works perfectly in my app.


01/25/2023 update: Getting loginWithRedirect() to work may be necessary at this point for building my app. I need my app to detect if a user is online or not, which it currently can. If a user is online, they should authenticate regularly by connecting to Auth0. If a user is offline, they should authenticate through the last retrieved access token while they were online. I do not know if I can do that with canActivate: [AuthGuard] on each screen.


01/26/2023 update: loginWithPopup() now works with this solution. Abandoned the AuthGuard solution. Unfortunately, loginWithRedirect() still does not work with any of the solutions that I have found.

Trying to delete the “management-api” tag but it won’t let me. I realized this morning that that tag is not relevant to this post.

I found an alternative solution that bypasses using loginWithRedirect(). You can use AuthGuard for each screen instead:

app-routing.module.ts

import { AuthGuard } from '@auth0/auth0-angular';

const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'sign-up', component: SignUpComponent, canActivate: [AuthGuard] },
  { path: 'home', component: HomeComponent, canActivate: [AuthGuard] },
  { path: 'profile', component: ProfileComponent, canActivate: [AuthGuard] },
  { path: 'settings', component: SettingsComponent, canActivate: [AuthGuard] }
];

I’d prefer a solution that uses loginWithRedirect(), but this works for now. Not marking this as the solution unless there is no solution involving loginWithRedirect().