Skip to content

Instantly share code, notes, and snippets.

@diyfr
Last active July 17, 2019 07:15
Show Gist options
  • Save diyfr/bc96735301080f90b83cdc259a8d312c to your computer and use it in GitHub Desktop.
Save diyfr/bc96735301080f90b83cdc259a8d312c to your computer and use it in GitHub Desktop.
Keycloak and Angular

add dependency :

npm install --save keycloak-angular@latest

edit app module add provider and replace bootstrap by entryComponents and add keycloakService.init

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

@NgModule({
  imports: [KeycloakAngularModule],
  providers: [
    {
      provide: KeycloakService,
      useValue: keycloakService
    }
  ],
  entryComponents: [AppComponent]
})

export class AppModule {
  ngDoBootstrap(app) {
    keycloakService.init({config,environment.settings.keycloakJsonUrl, 
	   enableBearerInterceptor: true,  // Activate HttpInterceptor for add Bearer all request
	   bearerExcludedUrls: ['/assets', '/api/nonesecure'] ) // Exclude bearer for this request
      .then(() => {
        console.log('[ngDoBootstrap] bootstrap app');
        app.bootstrap(AppComponent);
      })
      .catch(error => console.error('[ngDoBootstrap] init Keycloak failed', error));
  }
}

Add AuhtGuard

ng g auth auth/auth

Edit auth-guard.ts and replace by this

import { Injectable, Output } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { KeycloakAuthGuard, KeycloakService } from 'keycloak-angular';
import { Subject, Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard extends KeycloakAuthGuard implements CanActivate {
  private _roleError: Subject<any> = new Subject();//To broadcast role 
  constructor(protected router: Router, protected keycloakAngular: KeycloakService) {
    super(router, keycloakAngular);
  }

  public onRoleError(): Observable<any> {
    return this._roleError.asObservable();
  }
  isAccessAllowed(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
    return new Promise((resolve, reject) => {
      if (!this.authenticated) {
        this.keycloakAngular.login()
          .catch(e => console.error(e));
        return reject(false); // throw Error: Uncaught (in promise): An error happened during access validation. Details:false in console 
      }

      const requiredRoles: string[] = route.data.roles;
      if (!requiredRoles || requiredRoles.length === 0) {
        return resolve(true);
      } else {
        if (!this.roles || this.roles.length === 0) {
          this._roleError.next(null);
          resolve(false);
        }
        if (requiredRoles.every(role => this.roles.indexOf(role) > -1)) {
          resolve(true);
        } else {
          this._roleError.next(null);
          resolve(false);
        }

      }
    });
  }
}

Edit routing module and protect your routes :

const routes: Routes = [
  {
    path: "",
    redirectTo: "/home",
    pathMatch: 'full'
  },
  {
    path: "home",
    component: HomeComponent
  },
  {
    path: "secure",
    component: SecureComponent,
    canActivate: [AuthGuard]
  },
  {
    path: "admin",
    component: AdminComponent,
    data: {
      roles: ["ADMIN_APP"]
    },
    canActivate: [AuthGuard],
  }
];

Subscribe component toevent for an refused access by role

 this.authGuard.onRoleError().subscribe(() => {
      this.showMessage();
    })

get userProfile

this.keycloakService.loadUserProfile().then((profile) => {
  console.log(profile);
})

subscribe to keycloakEvent

this.keycloakService.keycloakEvents$.subscribe(e => {
      console.log(e);
    })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment