Keycloak Policy Enforcing for nodejs REST Api

48
May 15, 2019, at 10:20 PM

It's the first time asking something here, so excuse if I forget to provide some information or any other mistakes .. Sorry for the text wall.

Shortly what I try to do

(maybe I got something completely wrong): I create a backend (node.js Bearer Only) which shall offer an REST api. Partially it is used via a frontend (keycloak-clients) or directly by some devices. In general I try to create an application with a lot of CRUD. User Management is done in keycloak and only I forward these requests to the admin REST Api. Other stuff like the devices ... I store in a separate database. So the backend is the abstraction layer for frontend and other use-cases.

So far so good, but for the beginning it was enough to check weather the request comes from an authenticated person or not, so all handled via keycloak.protect() The Token from the authenticated person was passed But now I'd want to offer different authorization level (can differ due to reasons of multitenancy, why I want to solve this via policies and co in admin-console inside the client configuariton) because the normal user shall have access to only some routes and the management shall have full access to the api, but of course don't need the keycloak admin access. So I enabled the service account for my backend client and gave this one the realm-admin role so the client has access to everything and I can handle the authorization inside the backend client it self (using policies, permissions, .. inside the admin-console). (Just in case no one gets what I'm talking about. Fixing should help me fixing my issue I guess)

Setup

  • node.js application using express
  • registered as single client in keycloak admin-console (confidential, but config inside the code is bearer-only)
  • Keycloak is running in a docker-container (version 4.5)
  • all services are running in a docker-compose network and are behind a reverse proxy for common uri
  • enabled Authorization in client and changed the default policy to Negative to always deny => to see if it is enforced)

My Code


app.js
const express = require('express');
const app = express();
const Keycloak = require('keycloak-connect');
const session = require('express-session');
const routes = require('./routes/index');

const kcConfig = {
    'realm': 'master',
    'bearer-only': true,
    'auth-server-url': `https://DOMAIN/auth`,
    'ssl-required': 'all',
    'resource': 'fm-backend',
    'credentials': {
        secret: 'SOME_SECRET',
    },
    'confidential-port': 0,
    'policy-enforcer': {   //tried with an without this, changed nothing
        'enforcement-mode': 'ENFORCING',
    },
};
const memoryStore = new session.MemoryStore();
const keycloak = new Keycloak({ memoryStore }, kcConfig);
app.use(keycloak.middleware({ logout: '/api/logout', protected: '/api/gates' }));
// used before, worked for well for authentication
app.use('/api', keycloak.protect(), routes);
// now unfortunately I don't understand how to use keycloak.enforcer() middleware
app.use('/api', keycloak.enforcer({WHAT_COMES_HERE}), routes);
module.exports = app;

My Problem

I don't understand how to use the policies, permissions and Co I created in the admin-console inside the backend it self. How do I enforce that these are used? I tried to check different examples and documentation, but could get it working. The last thing I found was that the entitlement api was removed, but a policy-enforcer was added to the nodejs adapter. In the documentation for the policy-enforcer I couldn't find a documentation of the middleware (keycloak.enforcer({})) Link1 Link2.

Any Help is appreciated :)

READ ALSO
Sum of n number inside array is x number and create subset of result

Sum of n number inside array is x number and create subset of result

For example, if you have an array [20, 6, 7, 8, 50] and if I pass value 21 it should return [6,7,8] this sub arrayNote: the sum of number should be in sequence

13
Initializing multiple dbs with async await at the top level in node

Initializing multiple dbs with async await at the top level in node

I understand from a couple of similar questions that to use async await at the top level, it is necessary to wrap up anonymous functions

9
Connection refused between Node and MongoDB

Connection refused between Node and MongoDB

Getting this error when I try to connect my Node to my MongoDB

21
What claims do refresh token contain?

What claims do refresh token contain?

I am implementing JWT in one of my node appsI am wondering, if there is any definite format/ structure in which a refresh token should be generated?

27