keycloak-angular icon indicating copy to clipboard operation
keycloak-angular copied to clipboard

Readme example not working with base href different than "/"

Open 4javier opened this issue 5 years ago • 5 comments
trafficstars

Using window.location.origin in AuthGuard and in init function works just if base href is set to default "/". If the app sets a different one, redirectUri breaks everything. Native Angular i18n implementation does this kind of thing by default, changing the base href accordingly to the locale on every bundle it builds. (I.e. en-US bundle will have <base href="en-US">. window.location.origin will ignore this segment, causing app to fail on login or on initialization if using SSO.

I think I solved the problem injecting LocationStrategy inside AuthGuard and into APP_INITIALIZER, and leveraging its prepareExternalUrl() function to format an URI that take in account the whole base href.

This solves the problem for the AuthGuard only

export class AuthGuard extends KeycloakAuthGuard {
    constructor(protected readonly router: Router,
                       protected readonly keycloak: KeycloakService,
                       protected locationStrategy: LocationStrategy) { // <-------------------------------------------
            super(router, keycloak);
        }

    public async isAccessAllowed(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
        if (!this.authenticated) {
            await this.keycloak.login({
                redirectUri: `${window.location.origin}${this.locationStrategy.prepareExternalUrl(state.url)}` // <--------------------
    });
...

and in @NgModule's providers array

{provide: LocationStrategy, useClass: PathLocationStrategy}

To use SSO, I got to inject LocationStrategy as APP_INITIALIZER dependency

{
    provide: APP_INITIALIZER,
    useFactory: initializeKeycloak,
    multi: true,
    deps: [KeycloakService, LocationStrategy], // <----------------------------------
},

and use it it inside init function as well as done with AuthGuard

silentCheckSsoRedirectUri: `${window.location.origin}${locationStrategy.prepareExternalUrl('/assets/silent-check-sso.html')}`

Hope that's correct, and it can help someone else.

4javier avatar Sep 26 '20 18:09 4javier

Angular 11 defaults to ESLint instead of TSLint. This one marks as error every function export, thus I updated the example so the initialization gets exported as const. I also substituted the abstract class LocationStrategy with the Location service, as wrote in the official doc.

...
import { Location } from '@angular/common';
...
export const initializeKeycloak =
  (keycloak: KeycloakService, locationServ: Location) =>
  () => keycloak.init({
	  config: keycloakConfig,
	  initOptions: {
            enableLogging: true,
            onLoad: 'check-sso',
            silentCheckSsoRedirectUri: `${window.location.origin}${locationServ.prepareExternalUrl('/assets/silent-check-sso.html')}`,
	},
  });

4javier avatar Dec 22 '20 23:12 4javier

I'm having the same problem: my application uses a base href other than "/" and the angular-keycloak causes an infinite redirect loop.

I tried to use a solution above, but I had no success :(

Would anyone have any tips to solve this problem?

@4javier @jonkoops

tiagoaquino avatar Jan 29 '21 00:01 tiagoaquino

@tiagoaquino Better ask for support on dedicated Discord server or channel into Angular community server https://discord.com/channels/790617227853692958/790617228298551297 https://discord.com/channels/748677963142135818/790726368900022333 explaining your problem and providing your code.

4javier avatar Jan 29 '21 11:01 4javier

Stumbled upon this problem aswell. The issue is still open, maybe add explanation to the readme?

kimdah3 avatar Jun 30 '21 09:06 kimdah3

redirectUri: document.baseURI.slice(0, -1) + state.url

davidpadych avatar Dec 09 '21 09:12 davidpadych