我已经试了好几个小时了,似乎遇到了麻烦.如有任何建议/帮助,将不胜感激.
Goal:我想授权express rest api(ex client id:"我的rest api")跨映射到客户端范围的各种HTTP方法路由(示例资源:"WeatherForecast")(示例:"创建"/"读取"/"更新"/"删除").我想通过策略来控制这些权限(例如,如果满足策略"仅管理组"(用户属于管理组),将授予"Read-WeatherForecast-Permission".
Rest api不会让用户登录(将从前端直接与KeyClope对话,然后他们将使用该令牌与Rest api对话).
Environment:
- Key斗篷15.1.1在docker本地的自己的容器端口8080中运行(带有rest api的共享网络)
- "我的rest api":Nodejs 16.14.x w/express 4.17.x服务器运行在docker本地上自己的容器上.使用KeyClope connect 15.1.1和express session 1.17.2.
- 目前通过postman 点击"我的rest api",遵循以下指南:https://keepgrowing.in/tools/kecloak-in-docker-7-how-to-authorize-requests-via-postman/
What Happens:我可以通过postman 从Keyclope登录页面登录,并获得访问令牌.然而,当我点击任何使用KeyClope的端点时.保护()或 keys 斗篷.enforce()(有或没有指定资源权限)我无法通过.在下面的代码中,delete端点返回200+postman中KeyClope登录页面的HTML,Get返回403+"拒绝访问".
Current State of Realm
- 测试用户(我在Postman中与他一起登录)拥有组"Admin".
- 客户端"我的rest api",访问类型:机密,启用授权.
- 授权设置:
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:
- 我试着用从postman 那里得到的令牌用curl调用RPT端点,结果RPT令牌非常好,看到了预期的权限.
- 我试着打电话给Keyclope.判断权限({permissions:[{id:"WeatherForecast",作用域:["read"]}]},请求).然后(grant=>;res.json(grant.access_token));从一个不安全的端点内部获得"连接被拒绝127.0.0.1:8080".
- 我试着禁用策略执行模式只是为了看看,仍然被拒绝访问/403.
- 我试着用 keys 斗篷.json配置,而不是上面的对象方法——无论哪种方式,结果都是一样的.
- 我try 了openid客户端(来自另一个教程),也遇到了一些问题.
- 我试过使用docker主机ip,主机.docker .内部、容器名称等都没有用(尽管我不认为这是一个问题,因为我显然可以点击auth服务并获得第一个访问令牌).
我真的很想使用KeyClope,我觉得我的团队很快就能做到这一点,但需要一些帮助才能通过这一部分.非常感谢.
------------------- END ORIGINAL QUESTION ------------------------
EDIT/UPDATE #1:
'{"protocol":"http:","slashes":true,"auth":null,"host":"localhost:8080","port":"8080","hostname":"localhost","hash":null,"search":null,"query":null,"pathname":"/auth/realms/my-realm/protocol/openid-connect/token","path":"/auth/realms/my-realm/protocol/openid-connect/token","href":"http://localhost:8080/auth/realms/my-realm/protocol/openid-connect/token","headers":{"Content-Type":"application/x-www-form-urlencoded","X-Client":"keycloak-nodejs-connect","Authorization":"Basic YW(etc...)Z2dP","Content-Length":1498},"method":"POST"}'
它似乎没有进入fetch/http包装器的回调.我将NODE_DEBUG=http添加到我的启动命令中,并且能够找到被吞没的错误,看起来我回到了起点:
HTTP 31: SOCKET ERROR: connect ECONNREFUSED 127.0.0.1:8080 Error: connect ECONNREFUSED 127.0.0.1:8080
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1157:16)
at TCPConnectWrap.callbackTrampoline (node:internal/async_hooks:130:17)
然后,我看到了一些我认为可能与docker网络设置(Keycloak and Spring Boot web app in dockerized environment)有关的东西,并try 更改主机名dns,以便使用本地主机以外的其他主机,但也不起作用(甚至添加到重定向uri等).
UPDATE #2:
const kcConfig: any = {
clientId: 'my-rest-api',
bearerOnly: true,
serverUrl: 'http://localhost:8080/auth',
realm: 'my-realm',
realmPublicKey : "MIIBIjANBgk (...etc) uQIDAQAB",
};