This commit is contained in:
Constantin Simonis 2025-03-06 11:01:59 +01:00
parent 32aa753452
commit 33683f565f
No known key found for this signature in database
GPG key ID: 3878FF77C24AF4D2
11 changed files with 330 additions and 294 deletions

View file

@ -1,13 +1,12 @@
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';
import { KeycloakAngularModule } from 'keycloak-angular';
import { FooterComponent } from './shared/components/footer/footer.component';
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule, RouterOutlet, KeycloakAngularModule, FooterComponent],
imports: [CommonModule, RouterOutlet, FooterComponent],
providers: [],
templateUrl: './app.component.html',
styleUrl: './app.component.css',

View file

@ -1,59 +1,19 @@
import {
APP_INITIALIZER,
ApplicationConfig,
provideExperimentalZonelessChangeDetection,
} from '@angular/core';
import { ApplicationConfig, provideExperimentalZonelessChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { routes } from './app.routes';
import {
KeycloakAngularModule,
KeycloakBearerInterceptor,
KeycloakService,
} from 'keycloak-angular';
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { provideHttpClient } from '@angular/common/http';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
export const initializeKeycloak = (keycloak: KeycloakService) => async () =>
keycloak.init({
config: {
url: 'http://localhost:9090',
realm: 'LF12',
clientId: 'lf12',
},
loadUserProfileAtStartUp: true,
initOptions: {
onLoad: 'check-sso',
silentCheckSsoRedirectUri: window.location.origin + '/silent-check-sso.html',
checkLoginIframe: false,
redirectUri: window.location.origin + '/',
},
});
function initializeApp(keycloak: KeycloakService): () => Promise<boolean> {
return () => initializeKeycloak(keycloak)();
}
import { provideOAuthClient } from 'angular-oauth2-oidc';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
KeycloakAngularModule,
FontAwesomeModule,
{
provide: APP_INITIALIZER,
useFactory: initializeApp,
multi: true,
deps: [KeycloakService],
},
KeycloakService,
provideHttpClient(withInterceptorsFromDi()),
provideHttpClient(),
provideExperimentalZonelessChangeDetection(),
{
provide: HTTP_INTERCEPTORS,
useClass: KeycloakBearerInterceptor,
multi: true,
},
provideAnimationsAsync(),
provideOAuthClient(),
],
};

View file

@ -8,7 +8,7 @@ export const routes: Routes = [
component: LandingComponent,
},
{
path: 'login/success',
path: 'auth/callback',
loadComponent: () => import('./feature/login-success/login-success.component'),
},
{

View file

@ -1,12 +1,12 @@
import { CanActivateFn, Router } from '@angular/router';
import { inject } from '@angular/core';
import { KeycloakService } from 'keycloak-angular';
import { AuthService } from './service/auth.service';
export const authGuard: CanActivateFn = async () => {
const keycloakService = inject(KeycloakService);
const authService = inject(AuthService);
const router = inject(Router);
if (keycloakService.isLoggedIn()) {
if (authService.isLoggedIn()) {
return true;
}

View file

@ -1,7 +1,6 @@
import { ChangeDetectionStrategy, Component, inject, OnInit } from '@angular/core';
import { UserService } from '../../service/user.service';
import { KeycloakService } from 'keycloak-angular';
import { Router } from '@angular/router';
import { AuthService } from '../../service/auth.service';
@Component({
selector: 'app-login-success',
@ -12,15 +11,10 @@ import { Router } from '@angular/router';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export default class LoginSuccessComponent implements OnInit {
private userService: UserService = inject(UserService);
private keycloakService: KeycloakService = inject(KeycloakService);
private router: Router = inject(Router);
private authService: AuthService = inject(AuthService);
async ngOnInit() {
const userProfile = await this.keycloakService.loadUserProfile();
const user = await this.userService.getOrCreateUser(userProfile);
sessionStorage.setItem('user', JSON.stringify(user));
this.router.navigate(['home']);
console.log(this.authService.getAccessToken());
(this.authService.getUserInfo().then(console.log));
}
}

View file

@ -1,5 +1,5 @@
export interface User {
keycloakId: string;
authentikId: string;
username: string;
balance: number;
}

View file

@ -0,0 +1,52 @@
import { inject, Injectable } from '@angular/core';
import { Subject } from 'rxjs';
import { AuthConfig, OAuthService } from 'angular-oauth2-oidc';
@Injectable({
providedIn: 'root',
})
export class AuthService {
private readonly authConfig: AuthConfig = {
issuer: 'https://oauth.simonis.lol/application/o/casino-dev/',
clientId: 'MDqjm1kcWKuZfqHJXjxwAV20i44aT7m4VhhTL3Nm',
redirectUri: window.location.origin + '/auth/callback',
responseType: 'code',
scope: 'openid profile email',
showDebugInformation: true,
oidc: true,
requestAccessToken: true,
};
private isAuthenticated = new Subject<boolean>();
private oauthService: OAuthService = inject(OAuthService);
constructor() {
this.oauthService.configure(this.authConfig);
this.oauthService.loadDiscoveryDocumentAndTryLogin().then(() => {
this.isAuthenticated.next(this.oauthService.hasValidAccessToken());
});
}
login() {
this.oauthService.initLoginFlow();
}
logout() {
this.oauthService.logOut();
this.isAuthenticated.next(false);
}
getAccessToken() {
return this.oauthService.getAccessToken();
}
getUserInfo() {
return this.oauthService.loadUserProfile();
}
isLoggedIn() {
return this.oauthService.hasValidAccessToken();
}
}

View file

@ -1,6 +1,5 @@
import { inject, Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { KeycloakProfile } from 'keycloak-js';
import { catchError, EMPTY, Observable } from 'rxjs';
import { User } from '../model/User';
@ -20,23 +19,8 @@ export class UserService {
public createUser(id: string, username: string): Observable<User> {
return this.http.post<User>('/backend/user', {
keycloakId: id,
authentikId: id,
username: username,
});
}
public async getOrCreateUser(userProfile: KeycloakProfile) {
if (userProfile.id == null) {
return;
}
return await this.getUser(userProfile.id)
.toPromise()
.then(async (user) => {
if (user) {
return user;
}
return await this.createUser(userProfile.id ?? '', userProfile.username ?? '').toPromise();
});
}
}

View file

@ -1,9 +1,9 @@
import { ChangeDetectionStrategy, Component, inject, OnInit, signal } from '@angular/core';
import { RouterModule } from '@angular/router';
import { KeycloakService } from 'keycloak-angular';
import { UserService } from '../../../service/user.service';
import { CurrencyPipe } from '@angular/common';
import { AuthService } from '../../../service/auth.service';
@Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
@ -13,8 +13,8 @@ import { CurrencyPipe } from '@angular/common';
})
export class NavbarComponent implements OnInit {
isMenuOpen = false;
private keycloakService: KeycloakService = inject(KeycloakService);
isLoggedIn = this.keycloakService.isLoggedIn();
private authService: AuthService = inject(AuthService);
isLoggedIn = this.authService.isLoggedIn();
private userService = inject(UserService);
private user = this.userService.getCurrentUser();
@ -29,15 +29,14 @@ export class NavbarComponent implements OnInit {
login() {
try {
const baseUrl = window.location.origin;
this.keycloakService.login({ redirectUri: `${baseUrl}/login/success` });
this.authService.login();
} catch (error) {
console.error('Login failed:', error);
}
}
logout() {
this.keycloakService.logout();
this.authService.logout();
}
toggleMenu() {