Contributed by akoserwal

Vue.js

Secure a Vue.js single-page application with Keycloak

Before you start

Install Vue-Cli

npm install -g @vue/cli
# OR
yarn global add @vue/cli

Addon init plugin

npm install -g @vue/cli-init
# OR
yarn global add @vue/cli-init

Using runtime build for Content Security Policy (CSP) compliant

Code Repository

git clone https://github.com/keycloak/keycloak-quickstarts.git
cd applications/app-vue/
npm install

Start Keycloak

From a terminal open the directory keycloak-11.0.2, then to start Keycloak run the following command.

On Linux run:

bin/standalone.sh

On Windows run:

bin/standalone.bat

Standard Auth Flow

Sequence: Delegation of Authentication/Authorization i.e core principle behind OpenID-Connect

Vue App Auth Sequence

Behind the scene, the client is sending a post request to the Keycloak API endpoint with credentials. After validation & verification returns a promise object & redirects to client applications. Access token can be retrieved from the return object. Which can be passed to backend resource for accessing it.

Keycloak Setup & Client Configuration:

Creating a realm: “keycloak-demo” as shown in the following steps:

Login to the admin console

Go to the Keycloak Admin Console and login with the username and password you created earlier.

Create a realm

A realm in Keycloak is the equivalent of a tenant. It allows creating isolated groups of applications and users. By default there is a single realm in Keycloak called master. This is dedicated to manage Keycloak and should not be used for your own applications.

Let’s create our first realm.

  1. Open the Keycloak Admin Console

  2. Hover the mouse over the dropdown in the top-left corner where it says Master, then click on Add realm

  3. Fill in the form with the following values:

    • Name: myrealm

  4. Click Create

Add Realm

Create a user

Initially there are no users in a new realm, so let’s create one:

  1. Open the Keycloak Admin Console

  2. Click Users (left-hand menu)

    • Click Add user (top-right corner of table)

  3. Fill in the form with the following values:

    • Username: myuser

    • First Name: Your first name

    • Last Name: Your last name

  4. Click Save

Add User

The user will need an initial password set to be able to login. To do this:

  1. Click Credentials (top of the page)

  2. Fill in the Set Password form with a password

  3. Click ON next to Temporary to prevent having to update password on first login

Set Password

Client Configuration:

Clients tab allows you to manage your allow application clients

  1. Adding a Client: It is simple to add a client, the same process works for any type of application.

    • Client ID: You can give any suitable name for your application

    • Protocol: ‘OpenID-Connect/SAML’

    • Root Url: Application Hostname

Vue App Client Config

Configure these two fields are important:

  • Valid Redirect Url: After Authentication where should keycloak redirect? (dependent upon Web Origin config, otherwise you will see an error: Invalid request URI)

  • Web Origin: * or + ( * for wildcard redirection and + for domain-specific(validate all sub-domains): eg: *.redhat.com)

Create a Vue App

Let’s create a simple Vue application using Vue-CLI

vue init webpack-simple app-vue

Adding official keycloak js adapter

npm i keycloak-js --save

Adding logging library

npm i vuejs-logger --save

InitOptions: You can use a JSON file or an object with properties

Using the standard keycloak APIs init method call which returns a promise. On success, Render Vue application within that success method to prevent exposing any Vue resource before authentication is completed.

Add this below snippet in your src/main.js

let initOptions = {
  url: 'http://127.0.0.1:8080/auth', realm: 'keycloak-demo', clientId: 'app-vue', onLoad: 'login-required'
}

let keycloak = Keycloak(initOptions);

keycloak.init({ onLoad: initOptions.onLoad }).then((auth) => {
  if (!auth) {
    window.location.reload();
  } else {
    Vue.$log.info("Authenticated");

    new Vue({
      el: '#app',
      render: h => h(App, { props: { keycloak: keycloak } })
    })
  }


//Token Refresh
  setInterval(() => {
    keycloak.updateToken(70).then((refreshed) => {
      if (refreshed) {
        Vue.$log.info('Token refreshed' + refreshed);
      } else {
        Vue.$log.warn('Token not refreshed, valid for '
          + Math.round(keycloak.tokenParsed.exp + keycloak.timeSkew - new Date().getTime() / 1000) + ' seconds');
      }
    }).catch(() => {
      Vue.$log.error('Failed to refresh token');
    });
  }, 6000)

}).catch(() => {
  Vue.$log.error("Authenticated Failed");
});
Note
I am passing keycloak instance as prop to the App component. Which can be used to retrive token.

Run the Vue app:

# launch app:http://127.0.0.1:3000
npm run dev
Vue App