使用 OpenID 连接的节点快递
Posted
技术标签:
【中文标题】使用 OpenID 连接的节点快递【英文标题】:Node express with OpenID connect 【发布时间】:2020-11-28 18:26:28 【问题描述】:我使用 this 库将 oidc
与 nodejs 一起使用
我需要的是:
用户使用用户密码登录,或者数据已经是会话 cookie。这是调用我的应用根路由"/"
我已经在authorisation server
中注册应用程序,身份验证服务器应该调用我的app/redirect
我从身份验证服务器获取了 clientId 和客户端密码,并将其放入应用程序中。
当用户登录时,身份验证服务器应该调用我的应用程序 redirect 路由。
从oidc
策略我需要得到tokenset.claims();
和tokenset.id_token
,用户令牌。,在重定向调用
应该有
response_type: 'code',
https://github.com/auth0/express-openid-connect#getting-started
问题是调用了getUser
函数(在调试应用程序时)但是我从req.session.userIdentity
得到userIdentity
,即undefined
,知道这里可能有什么问题吗?
我们有相同的旧实现,它使用 OIDC,它适用于相同的身份验证服务器和 clientid 和 secret。
const auth, requiresAuth = require('express-openid-connect');
const session = require('express-session');
const bodyParser = require('body-parser');
module.exports = async (app) =>
const ClientId = process.env.CI;
const ClientSecret = process.env.CS;
const URL = process.env.S_URL;
app.use(session(
name: 'bat-auth',
secret: 'cookie-secret',
));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded( extended: true ));
app.use(auth(
clientSecret: ClientSecret,
issuerBaseURL: `$URL`,
clientID: ClientId,
baseURL: process.env.REDT_URL,
redirectUriPath: '/redirect', //my app redirect route
authorizationParams:
response_type: 'code',
response_mode: 'form_post',
scope: 'openid',
,
async handleCallback(req, res, next)
req.session.openidTokens = req.openidTokens;
console.log('---req.openidTokens', req.openidTokens);
req.session.userIdentity = req.openidTokens.claims();
next();
,
async getUser(req)
return req.session.userIdentity;
,
));
app.get('/', (req, res) =>
const tokenSet = req.openid.makeTokenSet(req.session.openidTokens);
console.log(`tokenset root: $tokenSet`);
res.send(req.isAuthenticated() ? 'Logged in' : 'Logged out');
);
app.get('/redirect', async (req, res) =>
const tokenSet = req.openid.makeTokenSet(req.session.openidTokens);
console.log(`tokenset: $tokenSet`);
console.log('redirect called');
res.send('redirect called');
);
我应该使用表单发布,最后,我需要从tokenset
、user.id_token
获取?
这是我已经验证过的!
来自身份验证服务器的 ClientID 来自身份验证服务器的 ClientSecret 配置身份验证服务器我的应用程序
redirect
路径,成功登录后应该调用我 我也有aud
键
顺便说一句,在调试应用程序时,它不会停止添加 handleCallback 函数,但它首先在 getUser
应用程序上停止,不知道可能是什么原因...
【问题讨论】:
你能改进一下这个问题吗?你想达到什么目标? @ToreNestenius - 按照我的要求,我用 stesp 更新了我的问题,现在更清楚了吗?如果有什么不清楚的地方请告诉我 redirectUriPath 不应该是:'/redirect'?前面有 /?当你应该使用绝对或相对 URL 时,你必须小心。我会检查使用 Fidder 之类的工具来捕获流量,然后在您的问题中添加失败的请求。 @ToreNestenius - 感谢您的提示,我也尝试了'/redirect'
,但仍然遇到同样的错误,还有其他想法吗?我的其他配置看起来还可以吗?
我会检查使用 Fidder 之类的工具来捕获流量,然后在您的问题中添加失败的请求。这样我们就可以更轻松地找出您在流程中卡住的位置。
【参考方案1】:
看起来您正在尝试从req.session.userIdentity
读取,但您从未在任何地方设置它。您正在设置 req.session.openidTokens
。
基于example code,您可能希望将您的handleCallback 函数修改为以下内容:
async handleCallback(req, res, next)
req.session.openidTokens = req.openidTokens;
console.log('---req.openidTokens', req.openidTokens);
req.session.userIdentity = req.openidTokens.claims(); // <-- this is required to make your code sample work
next();
【讨论】:
谢谢,我试了一下,它也不起作用,在调试应用程序时它不会在handleCallback
停止它只是在getUser
停止所以你提供的代码将不起作用,任何想法为什么它不停止?
知道如何进行吗?
我会逐字获取示例代码并验证它是否有效,然后进行小的增量更改,直到达到所需的状态。【参考方案2】:
看看你做了什么。你没有让人们回答你的问题变得太容易,你可以做更多的事情来改善你自己的自我诊断:
响应模式
去掉这个字段——我想我说得对,应该始终将授权响应设置为“查询”,这将是默认值。这可能会导致问题。
异步语法
我可能是错的,但我将从Auth0 page 的确切语法开始。有时我通过错误的语法在这方面犯了错误。
handleCallback: async function (req, res, next)
req.session.userIdentity = req.openidTokens.claims();
next();
,
HTTP 调试
Tore 说您应该在此处跟踪消息并发布任何故障是 100% 正确的。作为消息外观的示例,请参阅我的blog post。这涵盖了客户端授权代码流 (PKCE) 而不是服务器端授权代码流,但消息非常相似。
这里更广泛的一点是,如果您不了解 OAuth 消息和令牌字段,您将经常被阻止,而不是能够诊断自己的问题。在您的情况下,也许第 7 步没有作为预期的查询参数返回,因此库失败了?
如何捕获 HTTP 消息
您能否按照与我的NodeJS API 相同的方式更新您的配置,方法是添加以下类型的配置,然后运行诸如 Fiddler 或 Charles 之类的工具。然后,您应该能够在您的 Web 后端和授权服务器之间捕获 OAuth 消息,然后将任何失败的消息发回此处:
auth(
client_id: 'qhuefhuef',
...,
httpOptions:
agent: TunnelAgent.httpsOverHttp(
proxy: Url.parse('http://127.0.0.1:8888'),
)
花点时间来完成这项工作是非常值得的,这将有利于该领域的所有未来发展。我的HTTP debugging write up 中有更多详细信息。
错误处理
另一种可能性是授权服务器在标准“错误”/“错误描述”字段中返回错误响应,而您没有处理它们。
一旦解决了眼前的问题,就不要满足。 OAuth 解决方案有多个移动部分,并且会出现间歇性问题,一旦您将应用部署到测试人员或生产环境,您将希望能够快速解决这些问题。
我始终建议在开发过程中使 OAuth 消息失败,然后确保您捕获正确的数据并控制 UI 错误报告。有关测试故障点的方法,请参阅我的文章的第 10 步和第 17 步。
【讨论】:
当我删除 response_mode 时,出现错误:Error: Response mode "form_post" is not supported by the issuer. Supported response modes are "query", "fragment".
因此我尝试使用 query
,但我不确定它是否正确...
response_mode = query 表示使用授权代码流时如何接收授权代码,如我所写的第 7 步所示。然后使用表单帖子将代码交换为令牌,但您没有指定。另请参阅section 4.1.2 of official specs。
最后我需要的是user.id_token
我已将其更改为仅使用:authorizationParams: scope: 'openid', ,
,但仍然出现错误:Error: Response mode "form_post" is not supported by the issuer. Supported response modes are "query", "fragment".
我应该试试别的吗?以上是关于使用 OpenID 连接的节点快递的主要内容,如果未能解决你的问题,请参考以下文章
无法使用 axios 将 jwtToken 从反应客户端发送到节点/快递后端