There's a couple of steps needed for this: firstly you need to get some information from GitHub by hand, and then there is a little dance that your app needs to do to swap its authentication secrets for a temporary code that can be used to authenticate a git clone.

Gather information

Before you can write a function to do this, you need three pieces of information, all of which are available from the App's settings. To get there

  1. Go to the organization you have created the App for
  2. Go to Settings > Developer Settings > GitHub Apps
  3. Click Edit next to the name of the App you're using, and authenticate with 2FA

The three pieces of information you need are:

The App ID

This is in the General page, in the About section at the top.

The Installation ID

If you haven't already, you also need to install the App into the Organization. Once this is done, go back to the Install App page in the App settings, and copy the link for the installation settings. Paste it into your editor and get the number from the end. The link should have the form https://github.com/apps/{app_name}/installations/{installation_id}; the part after the last / is the installation ID.

(If you have multiple installations of your app, there may be a way to get this programmatically; I haven't looked into this as I didn't need it for my use case.)

PEM file

This is how you prove to GitHub that you are in control of the App. Go back to the General page in the App settings, and scroll down to the Private keys section. Click the Generate a private key button; this will immediately generate a .pem file and download it to your machine.

Do not commit this to your repository unless you want everyone who can see the repository to be able to authenticate to GitHub as you.

The code

Once you have these three things, the steps you need in code are:

  1. Load your PEM
  2. Use the PEM to create a JSON Web Token that will authenticate your API call
  3. Call the GitHub API to get an installation token
  4. (Use the installation token to clone the repository of interest.)

Get the installation token

Code to do the first three steps could look like this:

from datetime import datetime
import jwt
import requests

def get_installation_access_token(
    pem_filename: str, app_id: str, installation_id: str
) -> str:
    """
    Obtain and return a GitHub installation access token.

    Arguments:
        pem_filename: Filename of a PEM file generated by GitHub to
                      authenticate as the installed app.
        app_id: The application ID
        installation_id: The ID of the app installation.

    Returns:
        The installation access token obtained from GitHub.
    """

    # With thanks to https://github.com/orgs/community/discussions/48186
    now = int(datetime.now().timestamp())
    with open(pem_filename, "rb") as pem_file:
        signing_key = jwt.jwk_from_pem(pem_file.read())
    payload = {"iat": now, "exp": now + 600, "iss": app_id}
    jwt_instance = jwt.JWT()
    encoded_jwt = jwt_instance.encode(payload, signing_key, alg="RS256")

    response = requests.post(
        "https://api.github.com/app/installations/" f"{installation_id}/access_tokens",
        headers={
            "Authorization": f"Bearer {encoded_jwt}",
            "Accept": "application/vnd.github+json",
            "X-GitHub-Api-Version": "2022-11-28",
        },
    )
    if not 200 <= response.status_code < 300:
        raise RuntimeError(
            "Unable to get token. Status code was "
            f"{response.status_code}, body was {response.text}."
        )

    return response.json()["token"]

Pass in the information collected above as the three parameters to the function. Note that this depends on the jwt and requests packages, both available under those names from pip.

This will give an installation token that is valid for an hour. (This is much less time than the PEM file is valid, because it has a lot less security. That's the reason this dance is needed—you're trading something pretty secure for something that is less secure but easier to use with git clone; because it's less secure, it has to be time limited instead to reduce the chance of it getting stolen.)

Clone the repository

Assuming that you have a repository URL in the form

repo_url = https://github.com/organization/repository_name

then you can clone the repository as:

import git

if not original_url.startswith("https://"):
    raise ValueError("Need an HTTPS URL")

auth_url = f"https://x-access-token:{token}@{original_url[8:]}"
git.Repo.clone_from(
    auth_url,
    deployment["tempdir_path"] / "repo",
    branch="deployment",
)

Here I've used the GitPython library for Python. Equivalently, you could use the shell command

$ git clone https://x-access-token:${TOKEN}@github.com/organization/repository_name

where ${TOKEN} contains the result of calling the above Python function.

Credits

Many thanks to loujr on the GitHub Community for the guide that eventually clued me into how to do this. I've stripped out the need to use command-line arguments and to manually pass the JWT into curl, instead keeping everything in Python.

Answer from Ed Bennett on Stack Overflow
🌐
GitHub
github.com › vaspapadopoulos › github-app-auth
GitHub - vaspapadopoulos/github-app-auth: A simple Python script to authenticate to GitHub as a GitHub App.
A simple Python script to authenticate to GitHub as a GitHub App. - vaspapadopoulos/github-app-auth
Author   vaspapadopoulos
🌐
Readthedocs
pygithub.readthedocs.io › en › stable › examples › Authentication.html
Authentication — PyGithub 2.9.0 documentation
A specific installation of a Github App can use the Github API like a normal user. It authenticates by the Github App authentication (see above) and the installation id. The AppInstallationAuth fetches an access token for the installation and handles its expiration timeout.
Discussions

python - How do I get an GitHub app installation token to authenticate cloning a repository - Stack Overflow
There's a couple of steps needed for this: firstly you need to get some information from GitHub by hand, and then there is a little dance that your app needs to do to swap its authentication secrets for a temporary code that can be used to authenticate a git clone. More on stackoverflow.com
🌐 stackoverflow.com
oauth 2.0 - how to use github api token in python for requesting - Stack Overflow
I'm able to obtain Github api token in python using username and password but i'm not able to use that API-Token for requesting any POST/DELETE/PATCH. How do we use Github API-Tokens for making any More on stackoverflow.com
🌐 stackoverflow.com
python - gitpython: How to authenticate as a Github app? - Stack Overflow
remote: Invalid username or password. fatal: Authentication failed for 'https://github.com/user/repo' I have installed the app and added it to the repository integrations. It has content permissions to read and write. I am using the client secret as the token. ... I saw on Github documentation (docs.github.com/en/developers/apps/…) that you need to generate something called installation access tokens, but I found that too complicated and I don't know how to do that in Python... More on stackoverflow.com
🌐 stackoverflow.com
PyCharm + GitHub issues
Try comparing the settings between the desktop and laptop. If the PyCharm settings look the same try looking at the raw git configuration files in the .git directory of your project (specifically remote URLs, every detail). Also look if you have a global ".gitconfig" in your home directory and look for any weird settings between computers. Other than that I can't think of any reason for this to happen when it works on the Mac and laptop, but not the desktop. More on reddit.com
🌐 r/Python
11
0
December 18, 2013
🌐
GitHub
docs.github.com › en › apps › creating-github-apps › authenticating-with-a-github-app › about-authentication-with-a-github-app
About authentication with a GitHub App - GitHub Docs
To authenticate as itself, your app will use a JSON Web Token (JWT). Your app should authenticate as itself when it needs to generate an installation access token. An installation access token is required to authenticate as an app installation.
Top answer
1 of 1
10

There's a couple of steps needed for this: firstly you need to get some information from GitHub by hand, and then there is a little dance that your app needs to do to swap its authentication secrets for a temporary code that can be used to authenticate a git clone.

Gather information

Before you can write a function to do this, you need three pieces of information, all of which are available from the App's settings. To get there

  1. Go to the organization you have created the App for
  2. Go to Settings > Developer Settings > GitHub Apps
  3. Click Edit next to the name of the App you're using, and authenticate with 2FA

The three pieces of information you need are:

The App ID

This is in the General page, in the About section at the top.

The Installation ID

If you haven't already, you also need to install the App into the Organization. Once this is done, go back to the Install App page in the App settings, and copy the link for the installation settings. Paste it into your editor and get the number from the end. The link should have the form https://github.com/apps/{app_name}/installations/{installation_id}; the part after the last / is the installation ID.

(If you have multiple installations of your app, there may be a way to get this programmatically; I haven't looked into this as I didn't need it for my use case.)

PEM file

This is how you prove to GitHub that you are in control of the App. Go back to the General page in the App settings, and scroll down to the Private keys section. Click the Generate a private key button; this will immediately generate a .pem file and download it to your machine.

Do not commit this to your repository unless you want everyone who can see the repository to be able to authenticate to GitHub as you.

The code

Once you have these three things, the steps you need in code are:

  1. Load your PEM
  2. Use the PEM to create a JSON Web Token that will authenticate your API call
  3. Call the GitHub API to get an installation token
  4. (Use the installation token to clone the repository of interest.)

Get the installation token

Code to do the first three steps could look like this:

from datetime import datetime
import jwt
import requests

def get_installation_access_token(
    pem_filename: str, app_id: str, installation_id: str
) -> str:
    """
    Obtain and return a GitHub installation access token.

    Arguments:
        pem_filename: Filename of a PEM file generated by GitHub to
                      authenticate as the installed app.
        app_id: The application ID
        installation_id: The ID of the app installation.

    Returns:
        The installation access token obtained from GitHub.
    """

    # With thanks to https://github.com/orgs/community/discussions/48186
    now = int(datetime.now().timestamp())
    with open(pem_filename, "rb") as pem_file:
        signing_key = jwt.jwk_from_pem(pem_file.read())
    payload = {"iat": now, "exp": now + 600, "iss": app_id}
    jwt_instance = jwt.JWT()
    encoded_jwt = jwt_instance.encode(payload, signing_key, alg="RS256")

    response = requests.post(
        "https://api.github.com/app/installations/" f"{installation_id}/access_tokens",
        headers={
            "Authorization": f"Bearer {encoded_jwt}",
            "Accept": "application/vnd.github+json",
            "X-GitHub-Api-Version": "2022-11-28",
        },
    )
    if not 200 <= response.status_code < 300:
        raise RuntimeError(
            "Unable to get token. Status code was "
            f"{response.status_code}, body was {response.text}."
        )

    return response.json()["token"]

Pass in the information collected above as the three parameters to the function. Note that this depends on the jwt and requests packages, both available under those names from pip.

This will give an installation token that is valid for an hour. (This is much less time than the PEM file is valid, because it has a lot less security. That's the reason this dance is needed—you're trading something pretty secure for something that is less secure but easier to use with git clone; because it's less secure, it has to be time limited instead to reduce the chance of it getting stolen.)

Clone the repository

Assuming that you have a repository URL in the form

repo_url = https://github.com/organization/repository_name

then you can clone the repository as:

import git

if not original_url.startswith("https://"):
    raise ValueError("Need an HTTPS URL")

auth_url = f"https://x-access-token:{token}@{original_url[8:]}"
git.Repo.clone_from(
    auth_url,
    deployment["tempdir_path"] / "repo",
    branch="deployment",
)

Here I've used the GitPython library for Python. Equivalently, you could use the shell command

$ git clone https://x-access-token:${TOKEN}@github.com/organization/repository_name

where ${TOKEN} contains the result of calling the above Python function.

Credits

Many thanks to loujr on the GitHub Community for the guide that eventually clued me into how to do this. I've stripped out the need to use command-line arguments and to manually pass the JWT into curl, instead keeping everything in Python.

🌐
Donchev
donchev.is › post › how-to-authenticate-a-github-app-using-python
How to authenticate a GitHub App using python
Now that I have verified the origin (GitHub) I can start calling the GitHub API with the APP. In order for me to do this I need to create a JWT (JSON Web Token) and use that to authenticate with the GitHub API. The JWT is created using the private key that I downloaded from the GitHub app settings.
🌐
Readthedocs
python-social-auth.readthedocs.io › en › latest › backends › github.html
GitHub - Python Social Auth
Testing python-social-auth · Use Cases · Thanks · Copyrights and Licence · Index · Module Index · Back to top · View this page · GitHub works similar to Facebook (OAuth). On your project settings, you should add Github on your AUTHENTICATION_BACKENDS: AUTHENTICATION_BACKENDS = ( ... ...
Find elsewhere
🌐
Medium
medium.com › @lyle-okoth › github-oauth-using-python-and-flask-a385876540af
How To Authorize a User Using the GitHub OAuth API , Python and Flask: Part Two. | by Lyle Okoth | Medium
May 29, 2022 - Using the access token, we send a GET request to ‘https://api.github.com/user' to get the users data. ... The /index route for testing out the application. Accepts GET requests and serves out JSON response of the form: The /home route that serves out the home page. This contains a button that a user can click to start the authentication process.
Top answer
1 of 5
51

Here's some code that might help you out.

Examples:

Example 1 (auth):

username = 'user'
token = 'token'

login = requests.get('https://api.github.com/search/repositories?q=github+api', auth=(username,token))

Example 2 (headers):

headers = {'Authorization': 'token ' + token}

login = requests.get('https://api.github.com/user', headers=headers)
print(login.json())

Example 3 (delete repo):

user = 'username'
repo = 'some_repo' # Delete this repo

headers = {'Authorization': 'token ' + token}

login = requests.delete('https://api.github.com/' + 'repos/' + user + '/' + repo, headers=headers)

Example 4 (create repo):

repo = 'some_repo'
description = 'Created with api'

payload = {'name': repo, 'description': description, 'auto_init': 'true'}

login = requests.post('https://api.github.com/' + 'user/repos', auth=(user,token), data=json.dumps(payload))

You might want to take a look at the following docs:

Requests Docs

Github API docs

I hope this helps.

2 of 5
39

For one, I would recommend using a wrapper for the API. You're asking a lot of questions on here that could be simplified by finding a wrapper whose API you appreciate. There's a list of wrappers written in Python here.

As for your actually answering your question, the GitHub documentation is fairly clear that you need to send the Authorization header. Your call would actually look like this:

self.headers = {'Authorization': 'token %s' % self.api_token}
r = requests.post(url, headers=self.headers)

Since it seems like you're using requests and a class, might I be so bold as to make a recommendation? Let's say you're doing something like making a client for the API. You might have a class like so:

class GitHub(object):
    def __init__(self, **config_options):
        self.__dict__.update(**config_options)
        self.session = requests.Session()
        if hasattr(self, 'api_token'):
           self.session.headers['Authorization'] = 'token %s' % self.api_token
        elif hasattr(self, 'username') and hasattr(self, 'password'):
           self.session.auth = (self.username, self.password)

    def call_to_the_api(self, *args):
        # do stuff with args
        return self.session.post(url)

The Session object will take care of the authentication for you (either by the tokens or username and password combination).

Also, if you end up deciding to use github3.py for your API wrapper needs, there's a tag on here for it.

🌐
Stack Overflow
stackoverflow.com › questions › 67257664 › gitpython-how-to-authenticate-as-a-github-app
python - gitpython: How to authenticate as a Github app? - Stack Overflow
When I do remote = f"https://{username}:{password}@github.com/user/repo" git.Repo.clone_from(remote, 'repo') I get to clone the repository with my personal credentials. But if I try an app
🌐
GitHub
github.com › orgs › community › discussions › 48186
GitHub App Installation Token and Authenticating as a GitHub App · community · Discussion #48186
Unlike their token brethren, they don't require a user and can make requests on their own identity, no service account required. To authenticate against the GitHub API, you will need to generate a GitHub App Installation Token.
🌐
Readthedocs
github-app-tutorial.readthedocs.io › en › latest › creating-github-app.html
Building a GitHub App — Say It With Bots! documentation
GitHub App Tutorial using Python, gidgethub, and aiohttp · Sponsor @Mariatta · Follow @mariatta · Building a GitHub App · About webhooks · Webhook events · How does authentication works with a GitHub App? Create a webservice · Deploy the webservice to Heroku ·
🌐
Educative
educative.io › home › courses › managing your codebase with the github api in python › authentication
GitHub API Authentication with Personal Access Tokens
Managing Your Codebase with the GitHub API in Python · Explore how to authenticate with the GitHub API using personal access tokens to increase your request limits from 60 to 5000 per hour. Understand how authentication enables access to private data and learn to fetch user profiles while handling rate limits effectively.
🌐
GitHub
docs.github.com › en › apps › creating-github-apps › authenticating-with-a-github-app › generating-a-json-web-token-jwt-for-a-github-app
Generating a JSON Web Token (JWT) for a GitHub App - GitHub Docs
require 'openssl' require 'jwt' # https://rubygems.org/gems/jwt # Private key contents private_pem = File.read("YOUR_PATH_TO_PEM") private_key = OpenSSL::PKey::RSA.new(private_pem) # Generate the JWT payload = { # issued at time, 60 seconds in the past to allow for clock drift iat: Time.now.to_i - 60, # JWT expiration time (10 minute maximum) exp: Time.now.to_i + (10 * 60), # GitHub App's client ID iss: "YOUR_CLIENT_ID" } jwt = JWT.encode(payload, private_key, "RS256") puts jwt ... You must run pip install PyJWT cryptography to install the PyJWT and the cryptography packages in order to use th
🌐
Bugout
blog.bugout.dev › 2020 › 06 › 02 › how-to-build-a-github-app
How To Build a GitHub App: Step-by-step instructions – The Bugout.dev Blog
June 2, 2020 - You have to authenticate as an installation to access other resources. You first use a JWT for the GitHub App to generate an access token for the installation. This means you have to generate the JWT to make the access token request. The GitHub API docs show how to do this using a simple Ruby ...
🌐
Real Python
realpython.com › lessons › creating-github-app
Creating a GitHub App (Video) – Real Python
Creating a GitHub Application. To use GitHub authentication with Django user management, you’ll first have to create an application. Log in to your GitHub account and go to the URL seen on-screen and fill in the form. The most important part here is…
Published   April 19, 2022
🌐
GitHub
github.com › python-social-auth
Python Social Auth · GitHub
Python Social Auth is an easy to setup social authentication/registration mechanism with support for several frameworks and auth providers.
🌐
Thomas Stringer
trstringer.com › github-app-authentication
Understanding GitHub App Authentication | Thomas Stringer
May 17, 2022 - One of the big barries is how the App authenticates to GitHub, both as an App but also against the installations’ repos, and how GitHub authenticates to your App through the webhook secret. I hope this blog post has helped illustrate these workflows! ... This post is licensed under CC BY 4.0 by the author. ... aks azure azure functions containers debian devops docker fedora flask github gnome golang gunicorn helm istio kubernetes linux mysql openssl opentelemetry postgresql prometheus python security software development sre systemd terraform ubuntu vim
🌐
GitHub
github.com › PyGithub › PyGithub
GitHub - PyGithub/PyGithub: Typed interactions with the GitHub API v3 · GitHub
This library enables you to manage GitHub resources such as repositories, user profiles, and organizations in your Python applications. ... from github import Github # Authentication is defined via github.Auth from github import Auth # using ...
Starred by 7.7K users
Forked by 1.9K users
Languages   Python 99.6% | Shell 0.4%