Reputation: 844
I'm attempting to port the GitHub Apps sample starter code from Ruby to Python, but I'm running into trouble whilst generating the required JWT. The Ruby script looks like this, and works fine:
require 'openssl'
require 'jwt' # https://rubygems.org/gems/jwt
private_pem = File.read(YOUR_PATH_TO_PEM)
private_key = OpenSSL::PKey::RSA.new(private_pem)
payload = {
iat: Time.now.to_i,
exp: Time.now.to_i + (10 * 60),
iss: GITHUB_APP_IDENTIFIER
}
jwt = JWT.encode(payload, private_key, "RS256")
puts jwt
My Python script is as follows and produces the A JSON web token could not be decoded
error when used against the GitHub API:
import os
import time
import jwt
APP_IDENTIFIER = os.environ["GITHUB_APP_IDENTIFIER"]
with open('./PRIVATE_KEY.pem', 'r') as f:
PRIVATE_KEY = f.read()
payload = {"iat": int(time.time()),
"exp": int(time.time()) + (10*60),
"iss": APP_IDENTIFIER}
print(jwt.encode(payload, PRIVATE_KEY, algorithm='RS256'))
When I tried printing the private keys from both scripts, I found that the Ruby version had an extra newline character. I tried adding this to the private key in the Python script, but it didn't change the output.
My best guess is that the difference is something to do with the OpenSSL::PKey::RSA.new
call, but I'm not sure what that does to the key.
Upvotes: 4
Views: 9975
Reputation: 844
jwt.encode()
will return you bytes in Python 3 which probably ends up having str()
called on it somewhere in the sending pipeline. Calling str()
on bytes objects in Python 3 can result in potentially surprising behaviour:
>>> a = b'hello'
>>> str(a)
"b'hello'"
The correct way to turn bytes into a string in Python 3 is to use:
>>> a.decode('utf-8')
'hello'
I added the call to decode
on the end of my jwt.encode
line and the API suddenly had no problems decoding the JWT.
Upvotes: 4