我已经试了好几个小时了,似乎遇到了麻烦.如有任何建议/帮助,将不胜感激.

Goal:我想授权express rest api(ex client id:"我的rest api")跨映射到客户端范围的各种HTTP方法路由(示例资源:"WeatherForecast")(示例:"创建"/"读取"/"更新"/"删除").我想通过策略来控制这些权限(例如,如果满足策略"仅管理组"(用户属于管理组),将授予"Read-WeatherForecast-Permission".

Rest api不会让用户登录(将从前端直接与KeyClope对话,然后他们将使用该令牌与Rest api对话).

Environment:

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",
};

推荐答案

所以我的团队最终找到了答案——解决方案分为两部分:

  1. 按照类似问题的说明回答问题,例如:https://stackoverflow.com/a/51878212/5117487
  • 为127.0.0.1 keydrope添加hosts条目(如果"keydrope"是keydrope的docker容器的名称,我将docker compose更改为指定容器名称,使其更简单)
  • 将KeyClope connect配置authServerUrl设置更改为:'http://keycloak:8080/auth/"而不是"http://localhost:8080/auth/'
  1. Postman OAuth 2.0令牌请求验证URL和访问令牌URL更改为使用现在更新的主机条目:
  • "http://localhost:8080/auth/realms/abra/protocol/openid-连接/验证"->;"http://keycloak:8080/auth/realms/abra/protocol/openid-"连接/验证"
  • "http://localhost:8080/auth/realms/abra/protocol/openid-连接/令牌"->;

Node.js相关问答推荐

NX无法使用缓存运行根级脚本

@nuxtjs/站点 map 错误提示:找不到包';NitroPack';

获取页面大小为10的所有文章,每篇文章填充一些所需的用户信息

Playwright - 无法在 img 标签中使用 file:// 访问本地文件

为什么 Cors 在 NodeJS 中不起作用

如何使用 Node.js 连接到 Cloud SQL?

将图像添加到多个产品的条带 checkout 会话中

我如何在nodejs中的路由之间交换令牌

无法关闭 node.js 中的mongoose 连接

(Mongoose) 删除 TTL 字段失败

一个非常奇怪的JavaScript heap out of memory问题

try 运行迁移时的 Typeorm:缺少必需的参数:dataSource

Socket IOFlutter 未连接

如何让should.be.false语法通过 jslint?

如何在 node 中找到引用站点 URL?

如何判断 Node.js 中是否设置了环境变量?

在 react-router v4 中使用 React IndexRoute

Express.js中的bodyParser.urlencoded({extended: true }))和bodyParser.json()是什么意思?

'node' 未被识别为内部或外部命令

NodeJS:如何调试检测到 EventEmitter 内存泄漏.添加了 11 个侦听器