Hi Pedro,
thanks for the quick reply. So I got it working now, that the resource I
created is enforcing the one policy. For a single resource this is great.
Later on I would like to have an multi tenant solution, short
explanation what I mean:
Different companies have the same functionality but maybe want to change
the restriction for there self. But still with only one backend
application running. So each company should get one realm with the
backend application registered as a client. When they call the api the
backend should enforce the policies of the company specific client.
Therefore I have 2 questions:
1. Is it possible to configure the enforcer to enforce all policies for
all resources only depending on the requested on the path. So I only to
have to add the middleware once before the express router. So for
example we have a route /api/devices and /api/users (GET,POST,DELETE
each). Both are represented by a resource in the keycloak admin console.
I would like to have something like this:
router.js
****
const express = require('express');
const router = express.Router();
const users = require('../controllers/users.controller');
const devices = require('../controllers/devices.controller');
router.post('/users/', users.create);
router.delete('/users/', users.deleteAll);
router.get('/users/', users.findAll);
router.post('/devices/', devies.create);
router.delete('/devices/', devicese.deleteAll);
router.get('/devices/', devices.findAll);
module.exports = router;
****
app.js
****
.... //all from before
app.use('/api', keycloak.enforcer(__SOME_CONFIG__), routes);
****
I dont want to write keycloak.enforcer(...) to each line of users or
devices...
Maybe this can done by the claims and the context information? But if
yes I don't get how.
2. For now the solution is only single tenant, but If I want to have it
multi tenant and have realm per company with similar clients (only
different in policies and permissions). Do you have an idea how I can
solve the problem that the keycloak object is configured realm specific?
I would probably build a middleware which checks for a custom HTTP
header or looks for a subdomain for referencing the company. Depending
on the company I would set the keycloak object.
Do you think this can work ? Or do you have a better idea?
Some suggestions for your documentation:
- Could you somewhere describe what the middleware option protected is
doing? The Logout, ... options are explained, but the protected I
couldn't find.
- Your default resource is called 'Default Resource' but in the example
the resource is renamed to 'resource' the rest is untouched and default
config. Maybe a comment or adjustment of the example might be helpful.
Regards,
Lasse
On 14.05.19 20:33, Pedro Igor Silva wrote:
Hi,
We've added more docs to NodeJS PEP recently [1]. They should be
available in the next release. Please, let me know if that is enough
or if we need to add more information.
In your case, this code:
app.use('/api', keycloak.enforcer({WHAT_COMES_HERE}), routes);
Would be:
app.use('/api', keycloak.enforcer('{resource_name}:{resource_scope}'),
routes);
If you have a resource in Keycloak called "foo" and a scope associated
with this resource called "bar", the code would be:
app.use('/api', keycloak.enforcer('foo:bar'), routes);
Hope it helps.
[1]
https://github.com/keycloak/keycloak-documentation/pull/654
On Tue, May 14, 2019 at 1:25 PM Jahn, Lasse wrote:
Hello,
It's the first time writing to keycloak mailing list (I hope this
is the correct one?) 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 [1]
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 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 [2] I couldn't find a
documentation of the middleware (keycloak.enforcer({}) [3][4]).
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<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;
*****
[1]
https://stackoverflow.com/questions/53722033/how-to-enable-policy-enforci...
[2]
https://keycloak-docs.github.io/deploy-docs/dev/master/authorization_serv...
[3]
https://github.com/keycloak/keycloak-documentation/blob/master/securing_a...
[4]
https://github.com/keycloak/keycloak-nodejs-connect/blob/master/example/i...
Any Help is appreciated :)
With kind regards
Lasse
_______________________________________________
keycloak-user mailing list
keycloak-user(a)lists.jboss.org <mailto:keycloak-user@lists.jboss.org>
https://lists.jboss.org/mailman/listinfo/keycloak-user