Keycloak-angular: isLoggedIn Return False When refresh the page with F5 or the browser's Refresh button.

Created on 1 Jul 2020  路  9Comments  路  Source: mauriciovigolo/keycloak-angular

- [x] bug report -> please search for issues before submitting
- [ ] feature request

Versions.

"keycloak-angular": "^7.2.0",
"@angular/core": "~8.0.3",
Server Version 8.0.1

Repro steps.

Initially, I am correctly logged into my application.

I am trying to access a path protected by a Guard, and the state of this.authenticated variable is true, for now everything works fine.

But after accessing the page and when I refresh the entire page with F5 or with the refresh button of the browser, the variable this.authenticated is false.
It also fails when I manually type the url in the address bar.

The log given by the failure.

Desired functionality.

Should acces or allow navigate to paths that have the Guard implemented. The Guard should recognize that the variable this.authenticate its in true when refresh entire page.

1

2

3

4

Thanks!

All 9 comments

Hi @catapulveda, could you share the code you are using to initialize Keycloak Angular?

@jonkoops Thanks for answering

My app.module.ts is

import 'hammerjs';

// MODULES
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { HttpClientModule, HTTP_INTERCEPTORS, HttpClient } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { LayoutModule } from './layout/layout.module';
import { AgmCoreModule } from '@agm/core';
import { environment } from '../environments/environment';
import { PendingInterceptorModule } from '../@fury/shared/loading-indicator/pending-interceptor.module';
import { MAT_FORM_FIELD_DEFAULT_OPTIONS, MatFormFieldDefaultOptions } from '@angular/material/form-field';
import { MAT_SNACK_BAR_DEFAULT_OPTIONS, MatSnackBarConfig } from '@angular/material/snack-bar';
import { KeycloakAngularModule, KeycloakService } from 'keycloak-angular';
import { KeycloakAuthzAngularModule, KeycloakAuthorizationService } from 'keycloak-authz-angular';


// COMPONENTS
import { AppComponent } from './app.component';

// INTERCEPTORS
import { AcceptLanguageInterceptor } from './core/interceptors/accept-language.interceptor';
import { ServerErrorInterceptor } from './core/interceptors/server-error.interceptor';
import { ForbiddenAccessInterceptor } from './core/interceptors/forbidden-access.interceptor';


// i18n Internationalization
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { ServerErrorDialogModule } from './shared/server-error-display/server-error-display.module';

@NgModule({
    imports: [
        // Angular Core Module // Don't remove!
        BrowserModule,
        BrowserAnimationsModule,
        HttpClientModule,

        // Fury Core Modules
        AppRoutingModule,

        // Layout Module (Sidenav, Toolbar, Quickpanel, Content)
        LayoutModule,

        // Google Maps Module
        AgmCoreModule.forRoot({
            apiKey: environment.googleMapsApiKey
        }),

        // Displays Loading Bar when a Route Request or HTTP Request is pending
        PendingInterceptorModule,

        // Keycloak
        KeycloakAngularModule,
        KeycloakAuthzAngularModule,

        // Translate i18n
        TranslateModule.forRoot({
            loader: {
                provide: TranslateLoader,
                useFactory: (http: HttpClient) => new TranslateHttpLoader(http, 'assets/i18n/', '.json'),
                deps: [HttpClient]
            }
        }),

        // Shared
        ServerErrorDialogModule
    ],
    declarations: [AppComponent],
    bootstrap: [AppComponent],
    providers: [
        {
            provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
            useValue: {
                appearance: 'fill'
            } as MatFormFieldDefaultOptions
        },
        {
            provide: MAT_SNACK_BAR_DEFAULT_OPTIONS,
            useValue: {
                duration: 5000,
                horizontalPosition: 'end',
                verticalPosition: 'bottom'
            } as MatSnackBarConfig
        },
        {
            provide: APP_INITIALIZER,
            useFactory: initKeycloakService,
            multi: true,
            deps: [KeycloakService, KeycloakAuthorizationService]
        },
        {
            provide: HTTP_INTERCEPTORS,
            useClass: AcceptLanguageInterceptor,
            multi: true
        },
        {
            provide: HTTP_INTERCEPTORS,
            useClass: ForbiddenAccessInterceptor,
            multi: true
        },
        {
            provide: HTTP_INTERCEPTORS,
            useClass: ServerErrorInterceptor,
            multi: true
        }
    ],
})
export class AppModule {

}

export function initKeycloakService(keycloakService: KeycloakService, keycloakAuthorization: KeycloakAuthorizationService): () => Promise<any> {
    return (): Promise<any> => {
        return new Promise(async (resolve, reject) => {
            try {
                await keycloakService.init({
                    config: environment.keycloak,
                    initOptions: {
                        onLoad: 'login-required',
                        checkLoginIframe: false
                    },
                    bearerPrefix: 'Bearer',
                    bearerExcludedUrls: ['assets']
                });

                await keycloakAuthorization.init({
                    config: environment.keycloak,
                    initOptions: {
                        loadPermissionsInStartup: true,
                        defaultResourceServerId: 'gento-api'
                    }
                });

                resolve();
            }
            catch (error) {
                reject(error);
            }
        });
    };
}

I am using another implementation in my app.module, like so:

I have a problem with KeyCloak and Un Guard.
When I refresh the whole page, the Guard is executed first and then the code that is inside the ngDoBootstrap method of my app.module.ts is executed.

I am on the page _http://localhost:4200/customer/profile_, and I refresh the entire page with F5 or the browser button, and I have the following execution.

Screenshot_1

Screenshot_2

@mauriciovigolo Hello! How are you, can you help me please? 馃憤

@jonkoops Hello! How are you, can you help me please?

@catapulveda It's highly suspicious that the call to the Guard's isAccessAllowed method would happen before the application is actually boostrapped. Are you sure you're not executing some logic before the bootstrapping of your application or perhaps there is a bug in the initialisation itself?

Check out our new docs in the README and try to do the bootstrapping from scratch like that to see if you can get it to work. I cannot really see what could be going wrong in this code unfortunately.

I was working over a template named Fury, I downloaded from Themeforest.com. This template by default have in the App.routing.module File enabled the initialNavigation: 'enable' and others configurations. Only i disabled initialNavigation and work me.

@catapulveda Interesting, I had not heard of this option before but it makes sense this code would break because of this.

I confirm that initialNavigation: 'enable' causes getting always authenticated as false in AuthGuard

Was this page helpful?
0 / 5 - 0 ratings

Related issues

4javier picture 4javier  路  3Comments

nfriend picture nfriend  路  4Comments

osafi picture osafi  路  5Comments

arratejasvi picture arratejasvi  路  4Comments

samherrmann picture samherrmann  路  3Comments