Microsoft OAuth 授权代码流程 CORS

问题描述 投票:0回答:1

我有一个 SPA,用户将使用授权代码流使用 Microsoft Entra 登录。客户端是公开的,因此我按照Microsoft 誓言代码流程文档将我的应用程序注册为 SPA 客户端。假设我在这个项目中没有 API,因为我想使用公共流,并且不需要 API,因为我们使用 PKCE 而不是客户端密钥。

Client registered as SPA in my Entra

获取代币:

我正在生成 PKCE(挑战和验证者),然后从

请求授权代码

https://login.microsoftonline.com/[my tenant id]/oauth2/v2.0/authorize

正在发送

  • client_id=[我的客户ID]
  • response_type=代码
  • redirect_uri=[与 entra 中注册的相同]
  • response_mode=查询
  • 范围=.默认
  • code_challenge=[生成的挑战]
  • code_challenge_method=S256

这给了我 GET 请求 URL:

https://login.microsoftonline.com/[my tenant id]/oauth2/v2.0/authorize?client_id=[my client id]&response_type=code&redirect_uri=[url-encoded redirect uri]&response_mode=query&scope=.default&code_challenge=[generated challenge]&code_challenge_method=S256

到目前为止一切顺利。我在给定的 URL 处收到授权码。现在我想用获得的身份验证代码交换令牌,在令牌端点发送 POST 请求:

this.http.post(
    'https://login.microsoftonline.com/[my tenant id]/oauth2/v2.0/token',
    {
      client_id: '[my client id]',
      scope: '.default',
      code: '[received auth code]',
      redirect_uri: 'https://[my domain]/ms-auth-response',
      grant_type: 'authorization_code',
      code_verifier: '[code verifier matching the challenge],
    },
    {
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      }
    });

现在我面临的问题是登录端点令人惊讶地返回 CORS 错误,指出跨源请求是

cors error

文档中有关于此类错误的通知:

cors notice

但是我的客户注册为 SPA 并且清单是正确的:

app manifest

现在,如果我从 POSTMAN 发送代码和验证程序,手动将“origin”标头设置到我的域 - 微软端点将返回令牌。

没有原始标头,正如预期的那样,“为‘单页应用程序’客户端类型发行的令牌只能通过跨源请求兑换。”返回错误。

所以 MS 告诉我 - 你不能使用跨源请求,但你必须使用跨源请求?

我试图从 microsoft github 甚至 MSAL 库中查看一些示例,但 npm 甚至不会安装这些模块,因为它们要么已被弃用,要么正在使用一些旧的节点版本(14-15 左右)。

我使用隐式grand和代码流集成了许多OAuth2 SSO,包括谷歌,但我从未遇到过像这里这样的问题。为什么它可以从原点设置为我的域的邮递员工作,但不能从浏览器中的域本身工作?我已经检查了 chrome 工具,并且发送到令牌端点的所有标头都已正确设置(来源、引用等)

有人遇到过类似的问题吗?我不想改变流程或将confidentail web api客户端注册为整个过程中的中间方,因为不需要它。

关于如何处理这些 CORS 错误的一些建议,或者也许还有其他关于使用 Microsoft 登录进行 oauth 的信息?

authentication oauth-2.0 oauth cors
1个回答
0
投票

正如评论中CBroe所指出的,错误是由于请求编码错误引起的。我假设 Angular 的 http 客户端会通过查看 headers 来做到这一点(这就是 Postman 正在做的事情 - 这就是为什么它在那里工作得很好)。使用

URLSearchParams
显式编码对象立即解决了问题:

const encodedBody = new URLSearchParams({
  client_id: '[my client id]',
  scope: '.default',
  code: '[received auth code]',
  redirect_uri: 'https://[my domain]/ms-auth-response',
  grant_type: 'authorization_code',
  code_verifier: '[code verifier matching the challenge],
});

this.http.post(
    'https://login.microsoftonline.com/[my tenant id]/oauth2/v2.0/token',
    encodedBody.toString(),
    {
        headers: {
            'Cache-Control': 'no-cache',
            'Content-Type': 'application/x-www-form-urlencoded',
        }
    }
);
© www.soinside.com 2019 - 2024. All rights reserved.