首页 > 解决方案 > Azure - 获取用户刷新令牌失败

问题描述

我整天坐在上面,也许我需要刷新我的眼睛,但我无法使用Azure OAuth2指南获取用户刷新令牌。

我将解释我的场景:

  1. 我有使用 react 的客户端页面,我调用/authorizeAPI 来获取code以下范围:"email", "openid", "offline_access", "profile". 同意窗口正在打开,我同意这些条款。
    (我可能不需要所有这些,但在我的会话期间我遇到了错误并决定去大规模权限只是为了让它工作)
  2. code正在发送到我的服务器,在那里我调用API/token时使用我在客户端中声明的相同范围/authorize和相同的重定向 URI。

基本 URLhttps://login.microsoftonline.com/common用于上述调用

现在我收到 BAD_REQUEST 的原因如下:

{
  "error": "invalid_grant",
  "error_description": "AADSTS65001: The user or administrator has not consented to use the application 
with ID <CLIENT_ID> named <APP_NAME>. Send an interactive authorization request for this user and resource.\r\nTrace ID: <ID1>\r\nCorrelation ID: <ID2>\r\nTimestamp: 2020-10-02 19:48:18Z",
  "error_codes": [
    65001
  ],
  "timestamp": "2020-10-02 19:48:18Z",
  "trace_id": <ID1>,
  "correlation_id": <ID2>,
  "suberror": "consent_required"
}

在应用注册时,我授予了应用在上述范围内的权限,并且所有这些都来自同一组 API:
应用注册权限

当我转到我的 Microsoft 帐户查看应用程序时,我可以看到下面的权限,这似乎至少我错过了电子邮件:
在此处输入图像描述

我阅读了有关此事的几篇文章,重要的是要说我正在尝试从不同的 Microsoft 帐户登录,我去了该帐户的管理页面并设置启用的用户同意上述权限,但仍然没有用。
在此处输入图像描述

每个请求添加流的代码片段:

  1. 我有一个 React 应用程序 - 使用库react-ms-login,它使用https://login.microsoftonline.com/common/oauth2/v2.0/authorizeAPI 来获取授权代码,它会打开同意窗口,一旦关闭它就会将其发送到我的服务器。
    该组件如下所示:

    <ReactLoginMS clientId={MICROSOFT_CLIENT_ID} redirectUri="https://localhost:3000/msComplete" scopes={["email", "openid", "offline_access", "profile"]} responseType="code" handleLogin={(data) => login(data)} />

  2. Flask Application 获取授权码并执行以下操作:

    def get_refresh_token(code):
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded'
    }
    data = {
        'client_id': MICROSOFT_CLIENT_ID,
        'scope': ["email", "openid", "offline_access", "profile"],
        'code': code,
        'redirect_uri': 'https://localhost:3000/msComplete',
        'grant_type': 'authorization_code',
        'client_secret': MICROSOFT_CLIENT_SECRET
    }
    response = requests.post('https://login.microsoftonline.com/common/oauth2/v2.0/token', headers=headers, data=data)
    response.raise_for_status() # getting 400 with the mentioned error
    return response.json()
    

我有什么遗漏/做错了吗?
希望得到任何帮助,因为这是我第四次删除应用程序注册并重新开始:) 谢谢

标签: azureazure-active-directory

解决方案


尽管错误消息不是很清楚,但您的问题是如何构建令牌请求正文。

如果您将数组作为 POST 请求数据中的值之一传递:

data = { 'foo': ['a', 'b', 'c'] }
requests.post('https://example.com', data=data)

requests库将按如下方式对其进行编码:

foo=a&foo=b&foo=c

因此,在您的代码中,您包含一个字符串数组作为scope令牌请求的值:

'scope': ["email", "openid", "offline_access", "profile"],

您导致生成的请求scope在正文中有多个单独的参数:

...&scope=email&scope=openid&scope=offline_access&scope=profile&...

相反,您需要的是单个scope参数,每个范围值用空格分隔:

'scope': 'openid email offline_access profile',

这将被编码为:

...&scope=openid%20email%20offline_access%20profile&...

这是构建令牌请求正文的更正代码:

data = {
    'client_id': MICROSOFT_CLIENT_ID,
    'scope': "email openid offline_access profile",
    'code': code,
    'redirect_uri': 'https://localhost:3000/msComplete',
    'grant_type': 'authorization_code',
    'client_secret': MICROSOFT_CLIENT_SECRET
}

推荐阅读