Flask-Discord icon indicating copy to clipboard operation
Flask-Discord copied to clipboard

Secret doesn't end up in JWT

Open Mister-SOSA opened this issue 1 year ago • 5 comments

Some Contextual Information: Python v3.10 JWT v.2.6.0 OS: Ubuntu

Firstly, I am constructing a DiscordOAuth2Session() like so (I have shuffled up all the values to protect my application):

app = Flask(__name__)
app.config["SECRET_KEY"] = 'os.urandom(24)'

os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "true"

app.config["DISCORD_CLIENT_ID"] = 398041555473157536
app.config["DISCORD_CLIENT_SECRET"] = "LQYn4UiOgyIJspje6Y1aueKwK2Ccwput"            
app.config["DISCORD_REDIRECT_URI"] = "http://mysite.net/callback/"             
app.config["DISCORD_BOT_TOKEN"] = "QNkkzNjoyODgzFzE2EzU4MjI1.BVHlrQ.kdCdDeAKzFXYByMkB3_zVIaosQrQFO4Us6tjdQ" 

discord = DiscordOAuth2Session(app)

I then specify my callback address and input it into the Discord Developer Panel:

@app.route("/callback/")
def callback():
    discord.callback()
    user = discord.fetch_user()
    return redirect('/')

@app.errorhandler(Unauthorized)
def redirect_unauthorized(e):
    return redirect(url_for("login"))

image

Upon trying to access a @requires_authorization location on my site, I am redirected to the Discord OAuth screen, perfect so far. All the information displayed on this screen is correct.

As soon as I click "Authorize," I am redirected to what appears to be the correct location on my website, with a Flask traceback indicating some sort of problem with JWT.

The traceback:

Traceback (most recent call last):
  File "/home/ubuntu/.local/lib/python3.10/site-packages/jwt/api_jws.py", line 251, in _load
    signing_input, crypto_segment = jwt.rsplit(b".", 1)
ValueError: not enough values to unpack (expected 2, got 1)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/ubuntu/.local/lib/python3.10/site-packages/flask/app.py", line 2548, in __call__
    return self.wsgi_app(environ, start_response)
  File "/home/ubuntu/.local/lib/python3.10/site-packages/flask/app.py", line 2528, in wsgi_app
    response = self.handle_exception(e)
  File "/home/ubuntu/.local/lib/python3.10/site-packages/flask/app.py", line 2525, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/ubuntu/.local/lib/python3.10/site-packages/flask/app.py", line 1822, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/ubuntu/.local/lib/python3.10/site-packages/flask/app.py", line 1820, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/ubuntu/.local/lib/python3.10/site-packages/flask/app.py", line 1796, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
  File "/home/ubuntu/discord_bot/web/flask/main.py", line 48, in callback
    discord.callback()
  File "/home/ubuntu/.local/lib/python3.10/site-packages/flask_discord/client.py", line 161, in callback
    return jwt.decode(state, current_app.config["SECRET_KEY"], algorithms="HS256")
  File "/home/ubuntu/.local/lib/python3.10/site-packages/jwt/api_jwt.py", line 168, in decode
    decoded = self.decode_complete(
  File "/home/ubuntu/.local/lib/python3.10/site-packages/jwt/api_jwt.py", line 120, in decode_complete
    decoded = api_jws.decode_complete(
  File "/home/ubuntu/.local/lib/python3.10/site-packages/jwt/api_jws.py", line 191, in decode_complete
    payload, signing_input, header, signature = self._load(jwt)
  File "/home/ubuntu/.local/lib/python3.10/site-packages/jwt/api_jws.py", line 254, in _load
    raise DecodeError("Not enough segments") from err
jwt.exceptions.DecodeError: Not enough segments

It's hard for me to tell exactly what is wrong, as I am not very good at cracking modules open myself, but this is what I was able to find.

  • The issue occurs when processing app.config["SECRET_KEY"] to jwt.decode()
  • The key displays just fine when print(f'SECRET AS SEEN IN client.py: {current_app.config["SECRET_KEY"]}') is ran on line 159 of client.py in Flask-Discord
  • print(jwt) outputs b'' when ran on line 250 of api_jws.py in jwt

I've tried several different types of secrets to no avail, and I am currently torn between this being my own error or not. If someone has more details, please let me know.

Mister-SOSA avatar Nov 03 '22 15:11 Mister-SOSA

Check if this helps https://github.com/weibeu/Flask-Discord/issues/56#issuecomment-985147104 Additionally, re-check just in case that your callback URL configured in config and that on dashboard are exactly same. Including http/https URL scheme

weibeu avatar Nov 03 '22 15:11 weibeu

I feel fairly confident that I have done this part correctly, but anything is possible when I take on a project. Here's what I have:

In main.py: app.config["DISCORD_REDIRECT_URI"] = "http://XXXXX.net/callback/"

On my Discord Developer Dashboard: http://XXXXX.net/callback/

What appears in the addressbar after I click "Authorize": http://XXXXX.net/callback/?code=NfqYd9YQqieAGCEjHhhHUeXceBr3hz&state=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfX3N0YXRlX3NlY3JldF8iOiJxQTV5dzU2dHZoY0VMVXI5TmJ2c052NVlqTW5ieEQifQ.DxB1RwizZnLMBFikrGkEQf5OKvFy4QLgrNXu_kKuGuM

My @app.route():

@app.route("/callback/")
def callback():
    discord.callback() # <--- Error occurs here according to traceback
    user = discord.fetch_user()
    return redirect('/')

Setting my secret key:

app.config["SECRET_KEY"] = os.urandom(24)

Mister-SOSA avatar Nov 03 '22 15:11 Mister-SOSA

Some newfound information.

In callback(self) at line 142, self.__get_state() returns nothing. If I try to print it, it's an empty string, which leads me to believe that this item is not in my session when it is called? That would explain why there isn't enough segments when it's passed to jwt.decode()

Mister-SOSA avatar Nov 03 '22 16:11 Mister-SOSA

Sounds either of the following or something similar could be happening:

  • The cookie isn't being set for some reason. Which is done when calling discord.create_session method.
  • The cookie is being set but it isn't accessible or found or sent when the user is redirected to your callback endpoint.
  • Few more possible reasons I couldn't think of.

weibeu avatar Nov 06 '22 17:11 weibeu

Hello @Mister-SOSA - If you still need this to be fixed, you need to change this line. https://github.com/weibeu/Flask-Discord/pull/74

fizzrepo avatar Nov 21 '23 22:11 fizzrepo