Quarkus + Angular with Keycloak — Pt1
Published: 2023-03-23 01:50:15

The purpose of this article is to explore the authentication mechanism of _**Keycloak**_. We are going to create a **daily-quotes** application using **_Angular_** + **_Quarkus_** to achieve this goal. This article is divided into 3 parts.

1.The first part, we 'll start the Keycloak in a container and create the frontend project using Angular.

2.The [second](https://dev.to/ricardohsmello/quarkus-angular-with-keycloak-pt2-1903) part, we 'll create our backend in Quarkus.

3.The [third](https://dev.to/ricardohsmello/quarkus-angular-with-keycloak-pt3-lkp) and final part, we 'll adjust the frontend to communicate with the backend.

---

## Daily Quotes Application

The goal of this application is to create and list motivating messages. Only logged users will be able to see the messages. However, only users with admin role will be able to generate new messages.



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fjx37a4xcz81we221zon.gif)

---

## 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 using docker-compose up. Here we have a docker-compose.yml example:

```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 
```

```$ docker-compose up -d```

If all goes well, we 'll have our container running:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/omayyh2rpaljsj118kq6.png)

## Accessing Keycloak console

Type -> http://localhost:8188/admin and use admin/admin to sig in console.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ni77jnbw7nk7xofi3gg4.png)

## 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:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iq0w4mzgnuxpx41nwmzp.png)

## 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:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z1i64w3pghv5a90g133o.png)

## Creating the users

Users are the users in the current realm. Let’s create ricas and pedro users and define a password for them:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/00icfmozrm693m539mwa.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5n8jtdnmugrkrnjtmx8z.png)

## 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:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1nsutjqwx9dfuojp1qc1.png)

## Setting role to user
Now, lets assign admin role just to ricas user:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rrtxk76990k2oqnzqxw8.png)

> Very good 😻, our Keycloak is set. We’ve created our realm, client, users, and an admin role.

---


## Angular application

In this topic, we 'll create our Angular application and add some components to it. Later, we 'll change our components to adapt them with the Keycloak security mechanism.

- 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

```

> Very good 😻, we have our structure created and now we have to initialize Keycloak on 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’ll create a initializeKeycloak function and provides some informations. Inside keycloak.init we define keycloak url, realm and clientId that we’v created before. Our file must be like this:

```
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 { }
```

- Now, inside assets folder, let's create a silent-check-sso.html file:

```
<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/


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2qurl97bbcxx669jafp1.gif)

## Admin access

As our application was designed, we want to allow access to admin menu item only to users with admin role. For this, we will do the following steps:

- The navbar.component.ts should be like this:

```
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 these above step, we get all roles of the current user and check if he has the admin role

- The navbar.component.html must be like this:

```
<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

On this article, we saw how to configure and apply authentication with Keycloak in an Angular application. On the [next](https://dev.to/ricardohsmello/quarkus-angular-with-keycloak-pt2-1903) article, we 'll implement the backend with Quarkus.

Feel comfortable to suggest, comment and contribute with this project. You can find the complete source [here](https://github.com/ricardohsmello/daily-quotes) on my GitHub.

Thanks ❤️