Auth0 - 如何在自定义 API 或后端信任和保存用户信息?
Auth0 - How to Trust and Save User Information on a Custom API or Backend?
我正在尝试弄清楚如何在我的 API 服务器上 'trust' 用户信息(例如姓名、电子邮件和 sub
声明)以用于 React 本机应用程序。我在这里遵循了 auth0 的官方 React Native 快速入门指南:
https://auth0.com/docs/quickstart/native/react-native/
而且我已经在网络上看到了这 4 或 5 种方式的迭代。是的,这很棒,我们有一个前端身份验证方法 - 我们在前端获得 id_token
和 access_token
返回给我们。 access_token
很好,我完全理解,即将它保存到设备上的本地存储,将它添加到 Authorization
header,并使用 jwt 中间件来保护路由(也由自定义 APIs 页面上的 auth0 提供):
var express = require('express');
var app = express();
var jwt = require('express-jwt');
var jwks = require('jwks-rsa');
var port = process.env.PORT || 8080;
var jwtCheck = jwt({
secret: jwks.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: 'https://<myauth0domain>/.well-known/jwks.json'
}),
audience: '<myapiendpoing>',
issuer: '<myauth0domain>',
algorithms: ['RS256']
});
app.use(jwtCheck);
app.get('/authorized', function (req, res) {
res.send('Secured Resource');
});
app.listen(port);
现在终于到了我卡住的地方:关于 id_token
,我如何将任何用户 ID 信息保存到我的服务器并相信它真的是那个用户? 我想保存他们的姓名和电子邮件之类的东西,因为我的应用程序还有一个用户设置 table,用户可以在其中更改他们的个人资料信息。
我当然不能只转发 id_token
用作 'trusted' 身份 server-side。在 auth0 服务器、设备和我的 API 之间存在连接步骤的那一刻,坏人可能会欺骗 id_token
中的值——毕竟,它只是 JSON.
我当前的解决方案是从我的后端调用 auth0 的 built-in /userinfo
端点 - 您传递 access_token
并取回用户信息,但显然这不是很高效。为了尽量避免性能问题,我这样做一次以设置帐户信息,然后使用 access_token
中的 sub
声明(即用户 ID)来识别用户是谁用户设置相关端点。 sub
声明在 通过 JWT 中间件后 是可信的,对吗?
我能想到的唯一其他解决方案是将我的 React 应用程序上的授权回调 URI 更改为我的 API 上的端点,而不是更改为返回 React 本机应用程序的 URI,但后来我认为这意味着在 express 中实现整个用户 session 和护照故事。如果我想对 API?
执行任何 user-based 操作,也许无论如何我都必须这样做
他们说 OAuth 使事情变得容易得多,但在这一点上,我真的很困惑相信用户是否真的是他们所说的 server-side。事实上,将 id_token
放在 UI 一边有什么意义呢?根据我的理解,id_token
中的值只能是 'trusted' 纯粹用于显示目的。您永远不能将它们用作对服务器的请求中的标识密钥。
答案是使用 Proof Key for Code Exchange (PKCE) 流程。在此流程中,您生成一个代码验证器和挑战器,并接收一个 one-time 使用代码,可用于获取身份验证令牌、刷新令牌和 ID 令牌。这个请求可以在客户端完成。
使用此 one-time 使用代码,我们可以从我们自己的服务器发出第二个请求,即针对实际令牌的请求。由于此请求是从您信任的服务器发生的(不是在客户端上,Auth0 也不允许您在客户端上发出请求!)我们可以相信返回的 id 令牌的内容没有被篡改。 (即它是从您的 API 服务器到 Auth0 的 machine-to-machine 连接)
这也是查看用户是否已经存在的绝佳时间点(如果不存在,则使用 id 令牌的内容生成 server-side 帐户或用户信息)。在理想情况下,用户只需进行一次身份验证(因此访问此端点一次),并且我们可以在使用我们已安全保存在他们的帐户中的刷新令牌不断更新授权令牌后一直使用。
唯一的例外是刷新令牌本身过期,此时我们要求他们再次进行身份验证。
编辑:
出于 非常 的好奇,我 运行 在使用 React Native Expo 项目实施 PKCE 时遇到了一个额外的,但稍微不相关的问题。可以查看该问题的解决方案here and here.
我正在尝试弄清楚如何在我的 API 服务器上 'trust' 用户信息(例如姓名、电子邮件和 sub
声明)以用于 React 本机应用程序。我在这里遵循了 auth0 的官方 React Native 快速入门指南:
https://auth0.com/docs/quickstart/native/react-native/
而且我已经在网络上看到了这 4 或 5 种方式的迭代。是的,这很棒,我们有一个前端身份验证方法 - 我们在前端获得 id_token
和 access_token
返回给我们。 access_token
很好,我完全理解,即将它保存到设备上的本地存储,将它添加到 Authorization
header,并使用 jwt 中间件来保护路由(也由自定义 APIs 页面上的 auth0 提供):
var express = require('express');
var app = express();
var jwt = require('express-jwt');
var jwks = require('jwks-rsa');
var port = process.env.PORT || 8080;
var jwtCheck = jwt({
secret: jwks.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: 'https://<myauth0domain>/.well-known/jwks.json'
}),
audience: '<myapiendpoing>',
issuer: '<myauth0domain>',
algorithms: ['RS256']
});
app.use(jwtCheck);
app.get('/authorized', function (req, res) {
res.send('Secured Resource');
});
app.listen(port);
现在终于到了我卡住的地方:关于 id_token
,我如何将任何用户 ID 信息保存到我的服务器并相信它真的是那个用户? 我想保存他们的姓名和电子邮件之类的东西,因为我的应用程序还有一个用户设置 table,用户可以在其中更改他们的个人资料信息。
我当然不能只转发 id_token
用作 'trusted' 身份 server-side。在 auth0 服务器、设备和我的 API 之间存在连接步骤的那一刻,坏人可能会欺骗 id_token
中的值——毕竟,它只是 JSON.
我当前的解决方案是从我的后端调用 auth0 的 built-in /userinfo
端点 - 您传递 access_token
并取回用户信息,但显然这不是很高效。为了尽量避免性能问题,我这样做一次以设置帐户信息,然后使用 access_token
中的 sub
声明(即用户 ID)来识别用户是谁用户设置相关端点。 sub
声明在 通过 JWT 中间件后 是可信的,对吗?
我能想到的唯一其他解决方案是将我的 React 应用程序上的授权回调 URI 更改为我的 API 上的端点,而不是更改为返回 React 本机应用程序的 URI,但后来我认为这意味着在 express 中实现整个用户 session 和护照故事。如果我想对 API?
执行任何 user-based 操作,也许无论如何我都必须这样做他们说 OAuth 使事情变得容易得多,但在这一点上,我真的很困惑相信用户是否真的是他们所说的 server-side。事实上,将 id_token
放在 UI 一边有什么意义呢?根据我的理解,id_token
中的值只能是 'trusted' 纯粹用于显示目的。您永远不能将它们用作对服务器的请求中的标识密钥。
答案是使用 Proof Key for Code Exchange (PKCE) 流程。在此流程中,您生成一个代码验证器和挑战器,并接收一个 one-time 使用代码,可用于获取身份验证令牌、刷新令牌和 ID 令牌。这个请求可以在客户端完成。
使用此 one-time 使用代码,我们可以从我们自己的服务器发出第二个请求,即针对实际令牌的请求。由于此请求是从您信任的服务器发生的(不是在客户端上,Auth0 也不允许您在客户端上发出请求!)我们可以相信返回的 id 令牌的内容没有被篡改。 (即它是从您的 API 服务器到 Auth0 的 machine-to-machine 连接)
这也是查看用户是否已经存在的绝佳时间点(如果不存在,则使用 id 令牌的内容生成 server-side 帐户或用户信息)。在理想情况下,用户只需进行一次身份验证(因此访问此端点一次),并且我们可以在使用我们已安全保存在他们的帐户中的刷新令牌不断更新授权令牌后一直使用。
唯一的例外是刷新令牌本身过期,此时我们要求他们再次进行身份验证。
编辑:
出于 非常 的好奇,我 运行 在使用 React Native Expo 项目实施 PKCE 时遇到了一个额外的,但稍微不相关的问题。可以查看该问题的解决方案here and here.