可以将 Client Secret 作为 nonce 发送吗?

Is it ok to send the Client Secret as nonce?

我正在构建一个连接到我的后端的 SPA API,我必须集成 Azure AD 登录,我对整个授权流程有点困惑。我正在尝试尽可能安全。我将在下面解释流程:

  1. 我在后端构建 url(包含租户 ID 和其他信息),返回给 SPA 以添加到按钮上。
  2. 用户单击该按钮,被重定向到 Microsoft/Company 身份验证页面。
  3. 如果身份验证成功,用户将连同 ID 令牌一起重定向回 SPA。
  4. SPA 获取 ID 令牌并在每次请求时将其作为承载令牌发送到 API。
  5. API 检查签名,然后验证一些 JWT 令牌声明(例如 aud、iss、exp 等)。

我已经阅读了 statenonce 参数,这些参数最初发送到 Azure 是为了提高安全性,但我对两者的作用感到困惑。

我想将随机数设置为客户端密码,然后在 ID 令牌中返回时验证声明(第 5 步)。

是正确的做法吗?从我读到的内容来看,其他人使用 JWT 签名验证和验证或客户端 ID / 客户端秘密技术,但为什么我不能像在我的示例中那样使用两者,当 nonce秘密.

其次,如果我为此使用随机数,我应该将 state 参数用于什么?我是否应该将状态构建为由 SPA(前端)创建的随机字符串。

更新: 进一步阅读后,我意识到你 不能 使用客户端密码作为随机数,因为整个想法nonce 每次都是唯一的。随机数实际上是一个只创建和使用一次的词,之后它就被丢弃了。鉴于客户端密钥始终相同,它不会减轻“重放攻击”。

我会保留这个 post 因为我还有以下问题:

  1. 随机数是否用于 API/Backend 检查,状态是否由 Client/Browser(例如前端)使用?
  2. 我应该如何处理客户端密钥?现在好像没用了。我应该将其添加为加密的自定义声明吗?

最终更新: 除了接受的答案,请阅读隐式流程、授权代码流程、ID 令牌和访问令牌以及它们之间的区别以了解。

1。不实现协议,使用库

最好(也是最简单)的安全实施方式是不要自己实施。相反,使用可信赖且 well-maintained 实现协议的客户端库,让您可以自由地关注应用程序带来的价值,而不是协议的细节。

对于你的情况,我建议使用 Microsoft Authentication Library for JavaScript (MSAL.js). The quickstart for MSAL.js 是一个很好的起点。

2。对于 SPA,将授权代码流与 PKCE

结合使用

您正在尝试从 JavaScript 应用程序实施隐式授权流程。相反,您应该切换到使用授权代码流程(使用 PKCE)。要正确地做到这一点,您将需要处理“代码验证器”和“代码挑战”并进行一些哈希处理。相反,你应该只使用一个库(见上面的#1)。

最新版本MSAL.js使用PKCE实现了Authorization Code Grant流程,你完全不用管这个

3。不,不要使用客户端密码作为随机数。

(Edit是刚加的,具体原因就不细说了)

Is nonce used for the API/Backend to check and state is used by the Client/Browser (e.g. frontend)?

不,两者都被客户端使用(在您的情况下,JavaScript 应用程序)。 (在 many/most 情况下,single-page JavaScript 应用程序不会将 ID 令牌发送到其后端,它会发送 access 令牌(它将不包含随机数),所以后端永远不会看到状态 随机数。)

What should I do with the Client Secret? It seems to be useless now. Should I add it as an encrypted custom claim?

不,不要那样做。

首先,您的 JavaScript 应用程序的任何部分都不应包含任何 long-term 机密(例如客户端机密)。请记住,任何可以加载该应用程序的人都可以查看您的应用程序代码,并查看您的应用程序与其调用的任何后端服务器之间的所有流量。如果此通信包含机密,则您应用的任何用户都可以看到该机密。

如果您的客户端密码没有用处,那么您就不需要客户端密码。对于 public 客户端应用程序(您似乎正在构建的应用程序),不需要客户端密码是正常的。