Skip to content

Instantly share code, notes, and snippets.

@jasonbot
Last active April 27, 2023 10:42
Show Gist options
  • Select an option

  • Save jasonbot/2c7484af615a5d524c2994c77327e5e7 to your computer and use it in GitHub Desktop.

Select an option

Save jasonbot/2c7484af615a5d524c2994c77327e5e7 to your computer and use it in GitHub Desktop.
Get a github3 client instance for an app installation
def get_github3_client():
"""See
https://developer.github.com/apps/building-github-apps/authenticating-with-github-apps/#authenticating-as-a-github-app
for an explanation of how/why this is like it is.
Requires requests, pyjwt, and github3. Make sure you intall a newer
version of cryptography for pyjwt as well."""
payload = {
# issued at time
'iat': int(time.time()),
# JWT expiration time (10 minute maximum)
'exp': int(time.time() + (10 * 60)),
# GitHub App's identifier
'iss': str(config.GITHUB_ID)
}
url = "https://api.github.com/app"
jwt_payload = jwt.encode(payload, config.GITHUB.PRIVATE_KEY, algorithm="RS256")
headers = {"Authorization": "Bearer {jwt}".format(jwt=str(jwt_payload)),
"Accept": "application/vnd.github.machine-man-preview+json"}
# Requests "helpfully" clobbers Authentication headers if you don't use your own
# authentication method. Thanks, requests.
class CustomJWTAuth(requests.auth.AuthBase):
def __call__(self, r):
r.headers['Authorization'] = headers['Authorization']
return r
response = requests.get(url, headers=headers, auth=CustomJWTAuth())
response.raise_for_status()
installations_url = "https://api.github.com/app/installations"
installations_response = requests.get(installations_url, headers=headers, auth=CustomJWTAuth())
installations_response.raise_for_status()
for item in installations_response.json():
installation_id = item['id']
access_tokens_url = "https://api.github.com/app/installations/{installation_id}/access_tokens".format(
installation_id=installation_id)
access_tokens_response = requests.post(access_tokens_url, headers=headers, auth=CustomJWTAuth())
access_tokens_response.raise_for_status()
token = access_tokens_response.json()['token']
return github3.login(token=token)
raise Exception("No app installations")
@xor2003
Copy link

xor2003 commented Oct 1, 2019

For Python3 "Bearer {jwt}".format(jwt=jwt_payload) represents as bytes.
For example "Bearer b'abcdef123'" but it should be "Bearer 'abcdef123'"
When I fixed - it works

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment