I've just created a new angular application (v17). AppComponent is a standalone component and main.ts
looks like
bootstrapApplication(AppComponent, appConfig)
.catch((err) => console.error(err));
When the app boots I want (if not done yet) keycloak to kick to authenticate and redirect to the keycloak login page.
So I modified appConfig
:
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
{
provide: APP_INITIALIZER,
useFactory: initializeKeycloak,
multi: true,
deps: [KeycloakService],
}
]
};
The problem here is that KeycloakService
is never provided. If you google you see examples which use NgModule
in which KeycloakAngularModule
is added to the imports
array, which I don't have (everything is standalone components.
So my question is, should I create an app.module.ts
file an do
@NgModule({
imports: [ KeycloakAngularModule, ...],
...
})
export class AppModule { }
or is there an other way to do this with angular 17?
Simply add the KeycloakService
as provider.
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
{
provide: APP_INITIALIZER,
useFactory: initializeKeycloak,
multi: true,
deps: [KeycloakService]
},
KeycloakService // <-- add your missing provider here
]
};
UPDATE
This answer specifically fixes the following error:
NullInjectorError: No provider for _KeycloakService!
Here is a more complete version of the app.config.ts
file with a factory function from Keycloak Angular#Setup:
import { APP_INITIALIZER, ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { KeycloakService } from 'keycloak-angular';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
{
provide: APP_INITIALIZER,
useFactory: initKeycloak,
multi: true,
deps: [KeycloakService]
},
KeycloakService
]
};
function initKeycloak(keycloak: KeycloakService) {
return () => keycloak.init({
config: {
url: 'http://localhost:8080',
realm: 'your-realm',
clientId: 'your-client-id'
},
initOptions: {
onLoad: 'check-sso',
silentCheckSsoRedirectUri: window.location.origin
+ '/assets/silent-check-sso.html'
},
});
}
Your standalone components should also import KeycloakAngularModule
if needed:
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { KeycloakAngularModule } from 'keycloak-angular';
@Component({
selector: 'app-root',
standalone: true,
imports: [
RouterOutlet,
KeycloakAngularModule,
],
templateUrl: './app.component.html',
styleUrl: './app.component.scss'
})
export class AppComponent {
title = 'keycloak';
}