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

So I came to the idea one day to make a bot dashboard (it currently includes a rickroll and a pointless button). I watched some tutorials talking about how to get the user's information from OAuth2 (So that I could show them their profile on the dashboard and their servers so that they could modify the bot).

I did all the code exactly as was shown in the tutorials (even copied and pasted once or twice) but for some reason the code would return None for everything. None for username, None for userid, None for user avatar and None for guilds. btw, anyone who wants to see for themselves, this is the website: https://catsybot.235baron.repl.co/login (this will lead you to login and then will show you a broken page)

Here is what I get in my website

I later on made the code print out everything to see what was wrong and so far, I can only infer from the printing results that OAuth2 for some reason is refusing to give me the access_token

the results for the printing test for thus:

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 file (only part of it)

@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 file (only part of it)

@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

EDIT

I digged into the discord developer documentation and used the code they advised there and I got this 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 -


Solution 1:[1]

As it seems, my problem was that I didn't realize there was a difference between a client secret and bot token.

I thought they were the same. (I am still having problems with the getting of the user data)

Solution 2:[2]

Yeah... I found the problem, took me half an hour. The problem was in get_user function instead of url = DiscordOauth.api_endpoint+"/user/@me" url there should be url = DiscordOauth.api_endpoint+"/users/@me" not user but users

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 235baron
Solution 2 Koll