401:尝试获取 Discord OAuth2 访问令牌时未经授权 || Python 3.10

401: Unauthorized when trying to fetch Discord OAuth2 access token || Python 3.10

所以有一天我萌生了制作一个机器人仪表板的想法(它目前包括一个 rickroll 和一个毫无意义的按钮)。我看了一些教程,讨论如何从 OAuth2 获取用户信息(这样我就可以在仪表板和服务器上向他们展示他们的个人资料,以便他们可以修改机器人)。

我完全按照教程中显示的方式编写了所有代码(甚至复制并粘贴了一两次),但出于某种原因,代码对所有内容都会 return None。 None 用于用户名,None 用于用户 ID,None 用于用户头像,None 用于公会。顺便说一句,任何想亲自看看的人,这是网站:https://catsybot.235baron.repl.co/login(这将引导您登录,然后会显示一个损坏的页面)

我后来让代码打印出所有内容以查看问题所在,到目前为止,我只能从打印结果推断 OAuth2 出于某种原因拒绝给我 access_token

打印测试结果如下:

None #this is the user's id

None #this is the user's avatar

None #this is the username

None #this is the user's discriminator

{'message': '404: Not Found', 'code': 0} #This sometimes shows 401: Unauthorized

None #and this is the access_token

[redacted] #supposedly the code given by OAuth2

Flask 文件(只有一部分)

@app.route('/login', methods=['GET'])
def login():
    return redirect(DiscordOauth.login_url)


# Route for dashboard
@app.route('/dashboard', methods=['GET'])
def dashboard():
    code = request.args.get('code')
    access_token = DiscordOauth.get_access_token(code)
    user_object = DiscordOauth.get_user(access_token)

    user_guild_object = DiscordOauth.get_user_current_guild(access_token)

    id = user_object.get('id')
    avatar = user_object.get('avatar')
    username = user_object.get('username')
    usertag = user_object.get('discriminator')

    print(str(id))
    print(str(avatar))
    print(str(username))
    print(str(usertag))
    print(str(user_object))
    print(str(access_token))
    print(str(code))
    return render_template('dashboard.html', render_user_avatar=f'https://cdn.discordapp.com/avatars/{id}/{avatar}.png',
                           render_username=f'{username}#{usertag}', render_guild=user_guild_object)

discord_oauth 文件 (只有一部分)

@staticmethod
    def get_access_token(code):
        #access_token_url = DiscordOauth.token_url
        payload = {
            'client_id': DiscordOauth.client_id,
            'client_secret': DiscordOauth.client_secret,
            'grant_type': 'authorization_code',
            'code': code,
            'redirect_uri': DiscordOauth.redirect_uri,
            'scope': DiscordOauth.scope
        }
        headers = {
            'Content-Type': 'application/x-www-form-urlencoded'
        }
        access_token = requests.post(
            url=DiscordOauth.token_url,
            data=payload,
            headers=headers
        ).json()
        return access_token.get('access_token')

    # Get user
    @staticmethod
    def get_user(access_token):
        url = DiscordOauth.api_endpoint+"/user/@me"
        headers = {
            'Authorization': 'Bearer {}'.format(access_token)
        }
        user_object = requests.get(url=url, headers=headers)
        user_json = user_object.json()

        return user_json

    # Get user current guild
    @staticmethod
    def get_user_current_guild(access_token):
        user_guild_object = requests.get(
            url=f'{DiscordOauth.api_endpoint}/users/@me/guilds',
            headers={'Authorization': 'Bearer %s' % access_token}
        ).json()

        return user_guild_object

编辑

我深入研究了 discord 开发人员文档并使用了他们在那里建议的代码,我得到了这个 Traceback:

Traceback (most recent call last):
  File "/home/runner/catsybot/venv/lib/python3.8/site-packages/flask/app.py", line 2077, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/runner/catsybot/venv/lib/python3.8/site-packages/flask/app.py", line 1525, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/runner/catsybot/venv/lib/python3.8/site-packages/flask/app.py", line 1523, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/runner/catsybot/venv/lib/python3.8/site-packages/flask/app.py", line 1509, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
  File "/home/runner/catsybot/keep_alive.py", line 22, in dashboard
    access_token = DiscordOauth.get_access_token(code)
  File "/home/runner/catsybot/routes/discord_oauth.py", line 32, in get_access_token
    r.raise_for_status()
  File "/home/runner/catsybot/venv/lib/python3.8/site-packages/requests/models.py", line 960, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url: https://discord.com/api/v8/oauth2/token
172.18.0.1 - - [19/Apr/2022 17:59:49] "GET /dashboard?code=[redacted] HTTP/1.1" 500 -

是啊...我找到了问题,花了我半个小时。 问题出在 get_user 函数而不是 url = DiscordOauth.api_endpoint+"/user/@me" url 应该是 url = DiscordOauth.api_endpoint+"/users/@me" 而不是 user但是 用户

看来,我的问题是我没有意识到客户端密码和机器人令牌之间存在差异。

我以为他们是一样的。 (我仍然无法获取用户数据)