Issue with Keycloak redirection after incorrect configuration in Angular 13.3.2

503 views Asked by At

I'm facing an issue integrating my Angular application (version 13.3.2) with Keycloak, using the packages "keycloak-angular": "10.0.2" and "keycloak-js": "9.0.3". When the configuration is correct (valid URL, realm, and clientId), the redirection from my application to the Keycloak login page and back to my application works flawlessly. However, when I introduce an incorrect realm or clientId, I get redirected to the Keycloak "Page not found" page, and unfortunately, there's no return to my application.

Here are snippets of my code:

1. Component initializing Keycloak and invoking the login method:

In this component, I initialize Keycloak with the configuration and attempt to log the user in. If an error occurs, I want to redirect the user back to the main page of my application.

ngOnInit(): void {
  this.keycloakConfig = {
    url: "https://keycloak.local:{port}",
    realm: "my-real",
    clientId: "my-client-id",
  };

  this.keycloakService
    .init({
      config: this.keycloakConfig,
      initOptions: {
        pkceMethod: "S256",
        redirectUri: "http://localhost:4200/callback",
        checkLoginIframe: false,
      },
    })
    .then(() => {
      console.log("Keycloak initialized");
      this.keycloakLogin();
    })
    .catch(error => {
      console.error("[ngDoBootstrap] init Keycloak failed", error);
      this.router.navigate(["/"]);
    });
}

async keycloakLogin() {
  await this.keycloakService.login().catch(error => {
    console.error("Keycloak login failed", error);
    this.handleLoginError();
  });
}

handleLoginError(): void {
  this.router.navigate(["/"]);
}

2. Configuration in the module:

Here, I'm importing the necessary modules and providing KeycloakService as a provider for my application.

import { KeycloakAngularModule, KeycloakService } from "keycloak-angular";

@NgModule({
  declarations: [
    //...,
    KeycloakCallbackComponent,
  ],
  imports: [
    //...,
    KeycloakAngularModule,
  ],
  providers: [
    KeycloakService,
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

3. Callback component listening for the token:

After a successful login through Keycloak, the user gets redirected to this component, which tries to refresh the token and redirect the user to the main application page.

@Component({
  selector: "app-keycloak-callback",
  templateUrl: "./keycloak-callback.component.html",
  styleUrls: ["./keycloak-callback.component.scss"],
})
export class KeycloakCallbackComponent implements OnInit {
  constructor(
    private keycloakService: KeycloakService,
    private router: Router
  ) {}

  ngOnInit(): void {
    this.handleAuthentication();
  }

  async handleAuthentication() {
    try {
      await this.keycloakService.updateToken(20);
      await this.router.navigate(["/"]);
    } catch (error) {
      console.error("Error while trying to refresh token or redirect", error);
      this.router.navigate(["/"]);
    }
  }
}

Could anyone advise on how to properly handle an error in the case of incorrect Keycloak configuration, so that the user gets redirected back to my application, instead of being stuck on the Keycloak "Page not found" page? I'm keen on ensuring that for any error (not just "Page not found"), there's a redirection back to my application.

I'd greatly appreciate any guidance.

I've tried implementing a solution using a guard as per the documentation on GitHub, but to no avail. Here's a snippet of the guard and provider setup:

// Provider in AppModule
providers: [
  {
    provide: APP_INITIALIZER,
    useFactory: initializer,
    multi: true,
    deps: [KeycloakService],
  },
]

// Route Guard
@Injectable({
  providedIn: 'root',
})
export class AuthGuard implements CanActivate {
  constructor(private keycloakService: KeycloakService, private router: Router) {}

  async canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Promise<boolean> {
    if (await this.keycloakService.isLoggedIn()) {
      return true;
    }

    console.error('Authentication failed');
    await this.router.navigate(['/']);
    return false;
  }
}
0

There are 0 answers