Hi Everyone,
I’ve tried for many hours now and seem to have hit a wall. Any advice/help would be appreciated.
Goal: I want to authorize the express rest-api (ex client-id: “my-rest-api”) routes (example resource: “WeatherForecast”) across various HTTP methods mapped to client scopes (examples: “create”/“read”/“update”/“delete”). I want to control those permissions through policies (For example - “Read - WeatherForecast - Permission” will be granted if policy “Admin Group Only” (user belongs to admin group) is satisfied.
Rest-api will not log users in (will be done from front end talking directly to keycloak and then they will use that token to talk with rest-api).
Environment:
- Keycloak 15.1.1 running in its own container, port 8080, on docker locally (w/ shared network with rest-api)
- “my-rest-api”: Nodejs 16.14.x w/ express 4.17.x server running on its own container on docker locally. Using keycloak-connect 15.1.1 and express-session 1.17.2.
- Currently hitting “my-rest-api” through postman following this guide: Kecloak in Docker #7 – How to authorize requests via Postman
What Happens: I can login from keycloak login page through postman and get an access token. However when I hit any endpoint that uses keycloak.protect() or keycloak.enforce() (with or without specifying resource permissions) I can’t get through. In the following code the delete endpoint returns back 200 + the HTML of the keycloak login page in postman and the Get returns back 403 + “Access Denied”.
Current State of Realm
- Test User (who I login with in Postman) has group “Admin”.
- Client “my-rest-api” with access-type: Confidential with Authorization enabled.
- Authorization set up:
- Policy Enforcement Mode: Enforcing, Decision Strategy: Unanimous
- “WeatherForecast” resource with uri “/api/WeatherForecast” and create/read/update/delete client scopes applied.
- “Only Admins Policy” for anyone in group admin. Logic positive.
- Permission for each of the client scopes for “WeatherForecast” resource with “Only Admins Policy” selected, Decision Strategy: “Affirmative”.
Current State of Nodejs Code:
import express from 'express';
import bodyParser from 'body-parser';
import session from "express-session";
import KeycloakConnect from 'keycloak-connect';
const app = express();
app.use(bodyParser.json());
const memoryStore = new session.MemoryStore();
app.use(session({
secret: 'some secret',
resave: false,
saveUninitialized: true,
store: memoryStore
}));
const kcConfig: any = {
clientId: 'my-rest-api',
bearerOnly: true,
serverUrl: 'http://localhost:8080/auth',
realm: 'my-realm',
};
const keycloak = new KeycloakConnect({ store: memoryStore }, kcConfig);
app.use(keycloak.middleware({
logout: '/logout',
admin: '/',
}));
app.get('/api/WeatherForecast', keycloak.enforcer(['WeatherForecast:read'],{ resource_server_id: "my-rest-api"}), function (req, res) {
res.json("GET worked")
});
app.delete('/api/WeatherForecast', keycloak.protect(), function (req, res) {
res.json("DELETE worked")
});
app.listen(8081, () => {
console.log(`server running on port 8081`);
});
A Few Other Things Tried:
- I tried calling RPT endpoint with curl using token gotten from postman and got the RPT token perfectly fine, saw permissions as expected.
- I tried calling keycloak.checkPermissions({permissions: [{id: “WeatherForecast”, scopes: [“read”]}]}, req).then(grant => res.json(grant.access_token)); from inside an unsecured endpoint and got “Connection refused 127.0.0.1:8080”.
- I tried just disabling Policy Enforcement Mode just to see, still got Access Denied/403.
- I tried using keycloak.json config instead of object method above - same exact results either way.
- I tried openid-client (from another tutorial) and also got connected refused issues.
- I’ve tried using docker host ip, host.docker.internal, the container name, etc. to no avail (even though I don’t think it is an issue as I obviously can hit the auth service and get the first access token).
I really want to use Keycloak and I feel like my team is so close to being able to do so but need some assistance getting past this part. Thank you!