Quarkus + Angular with Keycloak — Pt1
Discover more on YouTube: If you’re looking for video content on technology, programming, and other topics, check out my YouTube channel! Subscribe to stay updated and learn more about these subjects.
This article aims to delve into the authentication mechanism of Keycloak, and the creation of a daily-quotes application using Angular + Quarkus. The article is divided into three parts.
- In the first part, we will begin by starting Keycloak in a container and creating the frontend project using Angular.
- The second part will involve the creation of our backend in Quarkus.
- Finally, in the third and final part, we will make adjustments to the frontend to enable communication with the backend.
Daily Quotes Application
The primary goal of this application is to create and display motivational messages. Access to these messages will be restricted to logged-in users only. Additionally, only users with admin privileges will be able to create new messages.
What is Keycloak?
Keycloak is an open source identity and access management solution. It uses open protocol standards like OpenID Connect or SAML 2.0 to secure your applications. The WebApps redirect the user to the Keycloak authentication server where the authentication control is carried out, isolating this entire process in a single point.
Setting up a Keycloak server
Let’s launch our local Keycloak instance by running the docker-compose up
command.
- Here's an example
docker-compose.yml
file that you can use:
services:
daily-quote-keycloak:
image: quay.io/keycloak/keycloak
ports:
- "8188:8080"
environment:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
command:
- start-dev
- --import-realm
volumes:
- /home/keycloak/realm.json:/opt/keycloak/data/import/realm.json
- Now, just run on the terminal:
$ docker-compose up -d
Great! If everything goes as planned, our container should now be up and running:
Accessing Keycloak console
Type http://localhost:8188/admin
in your web browser and use admin/admin
as the username and password to sign in to the Keycloak console:
Creating Realm
A realm manages a set of users, credentials, roles, and groups.
- Let’s define the name of our realm with the name of our application daily-quotes:
Creating Client
Clients are applications and services that can request authentication of a user. Let’s define the name of our client as frontend.
- The configuration must be like this:
Creating the users
Users are the users in the current realm.
- Let’s create ricas and pedro users and define a password for them:
Creating realm roles
Realm roles are the roles that you define for use in the current realm.
- At this point, we’ll create an admin role:
Setting role to user
- Now, lets assign admin role just to ricas user:
Excellent 😻 !! With Keycloak now set up, we have created a realm, client, users, and an admin role, and assigned the admin role to the
ricas
user.
Angular application
In this section, we will begin by creating an Angular application and adding necessary components to it. Later on, we will modify these components to integrate them with the Keycloak security mechanism.
Hands On
- Lets create our project and components:
$ mkdir daily-quotes
$ cd daily-quotes
$ ng new frontend
$ ng add @angular/material
- Adding a nav-bar component:
$ ng g c navbar
Excellent!😻 With our application structure in place, the next step is to initialize Keycloak within our application.
Configuring Keycloak
- First of all, let's add a Keycloak dependency:
$ sudo npm install keycloak-angular keycloak-js
Now, inside app.module.ts
, we will create an initializeKeycloak
function and provide the necessary information. Within the keycloak.init
function, we will define the Keycloak URL, realm, and client ID that we created previously.
- Here is an example of what our file might look like:
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { KeycloakAngularModule, KeycloakService } from 'keycloak-angular';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { QuotesComponent } from './quotes/quotes.component';
import { NavbarComponent } from './navbar/navbar.component';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatButtonModule } from '@angular/material/button';
import { MatMenuModule} from '@angular/material/menu';
import { MatIconModule } from '@angular/material/icon';
export function initializeKeycloak(keycloak: KeycloakService) {
return () =>
keycloak.init({
config: {
url: 'http://localhost:8188',
realm: 'daily-quotes',
clientId: 'frontend'
},
initOptions: {
onLoad: 'login-required',
silentCheckSsoRedirectUri:
window.location.origin + '/assets/silent-check-sso.html'
}
});
}
@NgModule({
declarations: [
AppComponent,
NavbarComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
MatToolbarModule,
MatButtonModule,
MatMenuModule,
MatIconModule,
KeycloakAngularModule,
],
providers: [
{
provide: APP_INITIALIZER,
useFactory: initializeKeycloak,
multi: true,
deps: [KeycloakService],
}
],
bootstrap: [AppComponent]
})
export class AppModule { }
- Next, let’s create a new file called
silent-check-sso.html
inside the assets folder:
<html>
<body>
<script>
parent.postMessage(location.href, location.origin);
</script>
</body>
</html>
All ready! Our configuration is done! Let’s start our serve and see the results on http://localhost:4200/
Admin access
As per our application design, we aim to restrict access to the admin menu item to users with admin privileges. To accomplish this, we will follow these steps:
- Modify the navbar.component.ts file as follows:
import { Component, OnInit } from '@angular/core';
import { KeycloakService } from 'keycloak-angular';
@Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.scss']
})
export class NavbarComponent implements OnInit {
constructor(private readonly keycloak: KeycloakService) { }
public hasAdminRole: boolean = false;
ngOnInit(): void {
this.hasAdminRole = this.keycloak.getUserRoles().includes('admin');
}
public async logout() {
this.keycloak.logout();
}
}
In the previous steps, we obtained all the roles for the current user and checked if they have the admin role.
- Modify the navbar.component.html file as follows:
<mat-toolbar color="primary">
Daily Quotes
<a mat-button href="/">Home</a>
<a mat-button href="/quotes">Quotes</a>
<div *ngIf="hasAdminRole">
<button mat-button [matMenuTriggerFor]="afterMenu">Admin</button>
<mat-menu #afterMenu="matMenu" xPosition="after">
<button mat-menu-item onclick="new()">Add new Quote</button>
</mat-menu>
</div>
<a mat-button (click)="logout()">Logout</a>
</mat-toolbar>
Conclusion
In this article, we have learned how to configure and apply authentication with Keycloak in an Angular application. In the next article, we will implement the backend with Quarkus.
Please feel free to suggest, comment, and contribute to this project. You can find the complete source code on my GitHub page.
Thank you ❤️