Question: I am writing a Python application that needs to clone private repositories from an organization. I've already registered a GitHub App, and I can see in the documentation that this needs an installation access token, but each of the steps in how to get one of these takes me down a rabbit hole of (circular references of) links.

Answer: 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  Go to the organization you have created the App for Go to Settings > Developer Settings > GitHub Apps 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:  Load your PEM Use the PEM to create a JSON Web Token that will authenticate your API call Call the GitHub API to get an installation token (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.