🪖 Setup a production grade keycloak instance on docker
Tags: keycloak, docker, authentication, express
Published: 2021-12-18 14:23:25

---
title: 🪖 Setup a production grade keycloak instance on docker
published: true
description: Stand up keycloak using docker-compose and secure an single-page-application and expressjs server endpoint
tags: keycloak, docker, authentication, express
cover_image: https://images.unsplash.com/photo-1634224143538-ce0221abf732?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1074&q=80
---
![princess bride: begin](https://media.giphy.com/media/xT9KVdZiz6jTsWCIWk/giphy.gif)

Stand up a keycloak instance w/ username: admin, password: pa55word. With postgres as a database. And SSL forwarding (for use with like cloudflare).

Create this docker-compose file i.e. `docker-compose.yml`
```yml
version: '3'

volumes:
  postgres_data:
      driver: local

services:
  postgres:
      image: postgres
      volumes:
        - postgres_data:/var/lib/postgresql/data
      environment:
        POSTGRES_DB: keycloak
        POSTGRES_USER: keycloak
        POSTGRES_PASSWORD: password
  keycloak:
      image: quay.io/keycloak/keycloak:latest
      environment:
        DB_VENDOR: POSTGRES
        DB_ADDR: postgres
        DB_DATABASE: keycloak
        DB_USER: keycloak
        DB_SCHEMA: public
        DB_PASSWORD: password
        KEYCLOAK_USER: admin
        KEYCLOAK_PASSWORD: Pa55w0rd
        PROXY_ADDRESS_FORWARDING: 'true'
        # Uncomment the line below if you want to specify JDBC parameters. The parameter below is just an example, and it shouldn't be used in production without knowledge. It is highly recommended that you read the PostgreSQL JDBC driver documentation in order to use it.
        #JDBC_PARAMS: "ssl=true"
      ports:
        - 8010:8080
      depends_on:
        - postgres
```

Then run `docker-compose up -d`.

With that in place, you just need to
- Make a new realm
- Make a new client
- Add a valid redirect uri to the client (from the application you are wishing to secure)

Then you can add the following type of logic for authentication on your browser facing application
```js
var keycloak;
function init() {

    keycloak = new Keycloak({
        url: 'https://[key-cloak-instance]/auth',
        realm: '[your-realm]',
        clientId: '[your-client]'
    });

    keycloak.init({
        checkLoginIframe: false
    }).success(async function (auth) {
        if (auth) {
            var name;
            if (keycloak.tokenParsed['family_name'] || keycloak.tokenParsed['given_name']) {
                name = keycloak.tokenParsed['given_name'] + ' ' + keycloak.tokenParsed['family_name']
            } else {
                name = keycloak.tokenParsed.preferred_username;
            }
            hide('login')

            // Set axios header for auth
            axios.defaults.headers.common['Authorization'] = `Bearer ${keycloak.token}`;
        } else {
            console.info('Not Authenticated');
            window.location = await keycloak.login();
        }
    })
}

function show(id) {
    document.getElementById(id).classList.remove('hide');
    document.getElementById(id).classList.add('show');
}

function hide(id) {
    document.getElementById(id).classList.add('hide');
    document.getElementById(id).classList.remove('show');
}

window.onhashchange = init;
window.onload = init;
```

Then on your server (nodejs/express in this case), add the following logic:
```js
const jwt = require('express-jwt');
const { data: response } = await axios.get('https://[keycloak-instance]/auth/realms/[your-realm]');
const secret = `-----BEGIN PUBLIC KEY-----\r\n${response.public_key}\r\n-----END PUBLIC KEY-----`;
const jwtMiddleware = jwt({ secret, algorithms: ['RS256'] });
```

And then you can either add the middleware globally
```js
app.use(jwtMiddleware)
```

Or add it to a specific route
```js
app.post('/api/endpoint', jwtMiddleware, async (req, res) => {
  return 'something-secure';
});
```

Now good luck to those pesky people that were previously trying to storm your castle!

![princess bride: bye boys! have fun storming the castle](https://media.giphy.com/media/SBr9k4zOIWb5K/giphy.gif)