pythonjwtpygithubgithub3.py

Issue with JWT token authentication in PyGithub


I want to create a github app in python, and I'm stuck at the authentication part. Since they don't support python by default, I have to use a third party library. After I generate the JWT token I can successfully authenticate with curl, but not with the library.

I've tried using PyGithub and Github.py and both returned a "Bad credentials" error, so I must have overlooked something.

import jwt
from github import Github
from dotenv import load_dotenv


load_dotenv()
GITHUB_PRIVATE_KEY = os.getenv('GITHUB_PRIVATE_KEY')
GITHUB_APP_IDENTIFIER = os.getenv('GITHUB_APP_IDENTIFIER')
GITHUB_WEBHOOK_SECRET = os.getenv('GITHUB_WEBHOOK_SECRET')

message = {'iat': int(time.time()),
           'exp': int(time.time()) + (10 * 60),
           'iss': GITHUB_APP_IDENTIFIER}

token = jwt.encode(message, GITHUB_PRIVATE_KEY.strip().encode(), 'RS256')

gh = Github(jwt=token.decode())

for repo in gh.get_user().get_repos():
    print(repo.name)

This curl command returns my app's details:

curl -i -H "Authorization: Bearer YOUR_JWT" -H "Accept: application/vnd.github.machine-man-preview+json" https://api.github.com/app

I expect the code to authenticate and print my repos, however i get

Traceback (most recent call last):
  File "C:/python/jeev/testing.py", line 21, in <module>
    for repo in gh.get_user().get_repos():
  File "C:/python/jeev\venv\lib\site-packages\github\PaginatedList.py", line 62, in __iter__
    newElements = self._grow()
  File "C:/python/jeev\venv\lib\site-packages\github\PaginatedList.py", line 74, in _grow
    newElements = self._fetchNextPage()
  File "C:/python/jeev\venv\lib\site-packages\github\PaginatedList.py", line 199, in _fetchNextPage
    headers=self.__headers
  File "C:/python/jeev\venv\lib\site-packages\github\Requester.py", line 276, in requestJsonAndCheck
    return self.__check(*self.requestJson(verb, url, parameters, headers, input, self.__customConnection(url)))
  File "C:/python/jeev\venv\lib\site-packages\github\Requester.py", line 287, in __check
    raise self.__createException(status, responseHeaders, output)
github.GithubException.BadCredentialsException: 401 {'message': 'Bad credentials', 'documentation_url': 'https://developer.github.com/v3'}

Github3.py version:

import jwt
import github3
from dotenv import load_dotenv


load_dotenv()
GITHUB_PRIVATE_KEY = os.getenv('GITHUB_PRIVATE_KEY')
GITHUB_APP_IDENTIFIER = os.getenv('GITHUB_APP_IDENTIFIER')
GITHUB_WEBHOOK_SECRET = os.getenv('GITHUB_WEBHOOK_SECRET')

gh = github3.github.GitHub()
gh.login_as_app(GITHUB_PRIVATE_KEY.encode(), GITHUB_APP_IDENTIFIER)
gh.me()

Same 401 bad credentials exception is raised. I've included a print in the login_as_app function, so now it outputs the JWT token, i used it with the curl command and I get what I want. Weird.


Solution

  • Typical case of RTFM: I should have authenticated as a installation.