feat: add Keycloak authentication integration and guard
This commit is contained in:
parent
aff058a29e
commit
fe8b1a1399
7 changed files with 95 additions and 3 deletions
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
|
@ -19,6 +19,7 @@
|
|||
"@angular/platform-browser-dynamic": "^18.2.0",
|
||||
"@angular/router": "^18.2.0",
|
||||
"bootstrap": "^5.3.3",
|
||||
"keycloak-angular": "^16.1.0",
|
||||
"rxjs": "~7.8.0",
|
||||
"tslib": "^2.3.0",
|
||||
"zone.js": "~0.14.10"
|
||||
|
|
3
public/silent-check-sso.html
Normal file
3
public/silent-check-sso.html
Normal file
|
@ -0,0 +1,3 @@
|
|||
<html><body>
|
||||
<h1>balls</h1>
|
||||
<script>parent.postMessage(location.href, location.origin)</script></body></html>
|
|
@ -1,8 +1,47 @@
|
|||
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
|
||||
import { APP_INITIALIZER, ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
|
||||
import { provideRouter } from '@angular/router';
|
||||
|
||||
import { routes } from './app.routes';
|
||||
import {KeycloakAngularModule, KeycloakBearerInterceptor, KeycloakService} from "keycloak-angular";
|
||||
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
|
||||
|
||||
export const initializeKeycloak = (keycloak: KeycloakService) => async () =>
|
||||
keycloak.init({
|
||||
config: {
|
||||
url: 'https://keycloak.szut.dev/auth',
|
||||
realm: 'szut',
|
||||
clientId: 'employee-management-service-frontend',
|
||||
},
|
||||
loadUserProfileAtStartUp: true,
|
||||
initOptions: {
|
||||
onLoad: 'check-sso',
|
||||
silentCheckSsoRedirectUri:
|
||||
window.location.origin + '/silent-check-sso.html',
|
||||
checkLoginIframe: false,
|
||||
redirectUri: 'http://localhost:4200',
|
||||
},
|
||||
});
|
||||
|
||||
function initializeApp(keycloak: KeycloakService): () => Promise<boolean> {
|
||||
return () => initializeKeycloak(keycloak)();
|
||||
}
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes)]
|
||||
providers: [
|
||||
provideRouter(routes),
|
||||
KeycloakAngularModule,
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: initializeApp,
|
||||
multi: true,
|
||||
deps: [KeycloakService]
|
||||
},
|
||||
KeycloakService,
|
||||
provideHttpClient(withInterceptorsFromDi()),
|
||||
{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
useClass: KeycloakBearerInterceptor,
|
||||
multi: true
|
||||
}
|
||||
]
|
||||
};
|
||||
|
|
|
@ -3,6 +3,8 @@ import { LoginViewComponent } from './components/login-view/login-view.component
|
|||
import { MitarbeiterverwaltungViewComponent } from './components/mitarbeiterverwaltung-view/mitarbeiterverwaltung-view.component';
|
||||
import { EmployeeDetailComponent } from './components/employee-detail/employee-detail.component';
|
||||
import { QualifikatonBearbeitenViewComponent } from './components/qualifikaton-bearbeiten-view/qualifikaton-bearbeiten-view.component';
|
||||
import { KeycloakAuthGuard } from 'keycloak-angular';
|
||||
import { AuthGuard } from './service/auth.service';
|
||||
|
||||
export const routes: Routes = [
|
||||
{
|
||||
|
@ -12,6 +14,7 @@ export const routes: Routes = [
|
|||
{
|
||||
path: "mitarbeiter",
|
||||
component: MitarbeiterverwaltungViewComponent,
|
||||
canActivate: [AuthGuard],
|
||||
},
|
||||
{
|
||||
path: "mitarbeiterdetails",
|
||||
|
@ -20,5 +23,9 @@ export const routes: Routes = [
|
|||
{
|
||||
path: "qualifikationbearbeiten",
|
||||
component: QualifikatonBearbeitenViewComponent,
|
||||
},
|
||||
{
|
||||
path: "**",
|
||||
redirectTo: '',
|
||||
}
|
||||
];
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-login-view',
|
||||
|
@ -8,5 +9,4 @@ import { Component } from '@angular/core';
|
|||
styleUrl: './login-view.component.css'
|
||||
})
|
||||
export class LoginViewComponent {
|
||||
|
||||
}
|
||||
|
|
42
src/app/service/auth.service.ts
Normal file
42
src/app/service/auth.service.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import {
|
||||
ActivatedRouteSnapshot,
|
||||
Router,
|
||||
RouterStateSnapshot
|
||||
} from '@angular/router';
|
||||
import { KeycloakAuthGuard, KeycloakService } from 'keycloak-angular';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AuthGuard extends KeycloakAuthGuard {
|
||||
constructor(
|
||||
protected override readonly router: Router,
|
||||
protected readonly keycloak: KeycloakService
|
||||
) {
|
||||
super(router, keycloak);
|
||||
}
|
||||
|
||||
public async isAccessAllowed(
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
) {
|
||||
// Force the user to log in if currently unauthenticated.
|
||||
if (!this.authenticated) {
|
||||
await this.keycloak.login({
|
||||
redirectUri: window.location.origin + state.url
|
||||
});
|
||||
}
|
||||
|
||||
// Get the roles required from the route.
|
||||
const requiredRoles = route.data['roles'];
|
||||
|
||||
// Allow the user to proceed if no additional roles are required to access the route.
|
||||
if (!Array.isArray(requiredRoles) || requiredRoles.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Allow the user to proceed if all the required roles are present.
|
||||
return requiredRoles.every((role) => this.roles.includes(role));
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue