Skip to content

Authentication

githubkit supports a variety of authentication strategies for the GitHub API. The following table summarizes all available strategies:

Strategy Use Case
UnauthAuthStrategy Public endpoints, quick tests
TokenAuthStrategy Personal Access Tokens (PAT)
AppAuthStrategy GitHub App (JWT)
AppInstallationAuthStrategy GitHub App installation
OAuthAppAuthStrategy OAuth App (client credentials)
OAuthTokenAuthStrategy Stored user access tokens
OAuthWebAuthStrategy OAuth web flow code exchange
OAuthDeviceAuthStrategy OAuth device flow (CLI, IoT)
ActionAuthStrategy GitHub Actions workflows

All strategies are importable from the top-level githubkit package.

Without Authentication

Access public GitHub API endpoints without credentials. Useful for quick tests, but subject to much lower rate limits.

from githubkit import GitHub, UnauthAuthStrategy

# Simply omit the auth parameter
github = GitHub()

# Or explicitly use UnauthAuthStrategy
github = GitHub(UnauthAuthStrategy())

Token Authentication

The simplest way to authenticate — pass a Personal Access Token (PAT) as a string. This works for both classic tokens and fine-grained PATs.

from githubkit import GitHub, TokenAuthStrategy

# Shorthand: pass a token string directly
github = GitHub("<your_token_here>")

# Explicit: use TokenAuthStrategy
github = GitHub(TokenAuthStrategy("<your_token_here>"))

Tip

Store tokens in environment variables or a secrets manager — never hard-code them in source files.

GitHub App Authentication

Authenticate as a GitHub App using a JSON Web Token (JWT) signed with the app's private key. This gives you access to app-level API endpoints (e.g., listing installations). See GitHub Docs — Authenticating as a GitHub App for background.

You can identify the app by app ID or client ID (GitHub supports both). The client ID and client secret are only required if you plan to use OAuth features (e.g., exchanging user tokens).

from githubkit import GitHub, AppAuthStrategy

# Using app ID (client ID and secret are optional)
github = GitHub(
    AppAuthStrategy(
        "<app_id>", "<private_key>", "<optional_client_id>", "<optional_client_secret>"
    )
)

# Using client ID instead of app ID
github = GitHub(
    AppAuthStrategy(
        None, "<private_key>", "<client_id>", "<optional_client_secret>"
    )
)

GitHub App Installation Authentication

Authenticate as a specific installation of your GitHub App. This grants access to the repositories and permissions that the organization or user has approved for that installation. API requests are attributed to the app.

See GitHub Docs — Authenticating as an installation for details.

from githubkit import GitHub, AppInstallationAuthStrategy

# Using app ID
github = GitHub(
    AppInstallationAuthStrategy(
        "<app_id>", "<private_key>", installation_id, "<optional_client_id>", "<optional_client_secret>",
    )
)

# Using client ID instead of app ID
github = GitHub(
    AppInstallationAuthStrategy(
        None, "<private_key>", installation_id, "<client_id>", "<optional_client_secret>",
    )
)

Tip

You can also derive an installation client from a GitHub App instance using with_auth — see Switching Auth Strategies below.

OAuth App Authentication

Authenticate as an OAuth App using client credentials. This strategy uses Basic authentication with the client ID and secret, which is required for certain endpoints (e.g., managing OAuth tokens).

from githubkit import GitHub, OAuthAppAuthStrategy

github = GitHub(OAuthAppAuthStrategy("<client_id>", "<client_secret>"))

OAuth User Token Authentication

Act on behalf of a user using a previously obtained OAuth access token. This is the strategy to use when you have stored a user's token in your database and want to make API calls as that user.

Without token expiration

For OAuth Apps or GitHub Apps without user-to-server token expiration enabled:

from githubkit import GitHub, OAuthTokenAuthStrategy

github = GitHub(
    OAuthTokenAuthStrategy(
        "<client_id>", "<client_secret>", token="<access_token>"
    )
)

With token expiration (refresh tokens)

For GitHub Apps with user-to-server token expiration enabled, provide the refresh token so githubkit can automatically renew expired access tokens. If you also supply the access token, you must include its expiration time:

from datetime import datetime

from githubkit import GitHub, OAuthTokenAuthStrategy

github = GitHub(
    OAuthTokenAuthStrategy(
        "<client_id>",
        "<client_secret>",
        token="<access_token>",  # optional if refresh_token is set
        expire_time=datetime(),  # required when token is provided
        refresh_token="<refresh_token>",  # optional if token is set
        refresh_token_expire_time=datetime(),  # optional
    )
)

Manually refreshing the token

You can force a token refresh at any time:

# sync
github.auth.refresh(github)
# async
await github.auth.async_refresh(github)

This updates the token and refresh_token attributes in place on the auth strategy object. After refreshing, persist the new values from github.auth to your database.

OAuth Web Flow Authentication

Exchange an OAuth authorization code (from the web application flow) for a user access token. See GitHub Docs — Using the web application flow.

from githubkit import GitHub, OAuthWebAuthStrategy

github = GitHub(
    OAuthWebAuthStrategy("<client_id>", "<client_secret>", "<code>")
)

Warning

This strategy is one-time use — the authorization code can only be exchanged once. After obtaining the token, persist it and switch to OAuthTokenAuthStrategy for subsequent requests.

To exchange the code and retrieve the resulting token:

from githubkit import GitHub, OAuthWebAuthStrategy, OAuthTokenAuthStrategy

github = GitHub(
    OAuthWebAuthStrategy("<client_id>", "<client_secret>", "<code>")
)

# sync
auth: OAuthTokenAuthStrategy = github.auth.exchange_token(github)
# async
auth: OAuthTokenAuthStrategy = await github.auth.async_exchange_token(github)

# Persist these values to your database
access_token = auth.token
refresh_token = auth.refresh_token

See Switching Auth Strategies for a complete example of web flow integration with OAuthAppAuthStrategy.

OAuth Device Flow Authentication

Authenticate a user on input-constrained devices (CLI tools, IoT, smart TVs) without a web browser. githubkit handles the polling loop automatically. See GitHub Docs — Using the device flow.

You must provide a callback function that displays the user code. githubkit calls this function when a code is generated, then polls the server until the user completes authentication or the code expires.

from githubkit import GitHub, OAuthDeviceAuthStrategy

def callback(data: dict):
    """Display the user code and verification URL to the user."""
    print(f"Open {data['verification_uri']} and enter code: {data['user_code']}")

github = GitHub(
    OAuthDeviceAuthStrategy("<client_id>", callback)
)

The callback receives the full device authorization response as a dict. Key fields can be found in the GitHub Docs — Using the device flow.

Warning

This strategy is also one-time use. Exchange and persist the token for future requests:

from githubkit import GitHub, OAuthDeviceAuthStrategy, OAuthTokenAuthStrategy

github = GitHub(OAuthDeviceAuthStrategy("<client_id>", callback))

# sync
auth: OAuthTokenAuthStrategy = github.auth.exchange_token(github)
# async
auth: OAuthTokenAuthStrategy = await github.auth.async_exchange_token(github)

# Persist these values
access_token = auth.token
refresh_token = auth.refresh_token

GitHub Action Authentication

Authenticate automatically inside GitHub Actions workflows using the GITHUB_TOKEN provided by the runner.

from githubkit import GitHub, ActionAuthStrategy

github = GitHub(ActionAuthStrategy())

Make sure the token is available to your step — pass it as an input or environment variable:

- name: Run my script
  with:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# Or as an environment variable
- name: Run my script
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Switching Auth Strategies

The with_auth method creates a new GitHub instance with a different auth strategy while sharing the same configuration (base URL, timeout, cache, etc.). This is essential for OAuth flows where you start as an app and then act as a user.

GitHub App → Installation

from githubkit import GitHub, AppAuthStrategy

github = GitHub(AppAuthStrategy("<app_id>", "<private_key>"))

# Create a new client authenticated as a specific installation
installation_github = github.with_auth(
    github.auth.as_installation(installation_id)
)

GitHub App → OAuth App

Requires client_id and client_secret to be set on the AppAuthStrategy:

from githubkit import GitHub, AppAuthStrategy

github = GitHub(
    AppAuthStrategy(
        "<app_id>", "<private_key>", "<client_id>", "<client_secret>"
    )
)

oauth_github = github.with_auth(github.auth.as_oauth_app())

OAuth App → User (Web Flow)

Exchange a web flow code for a user token and make requests as the user:

from githubkit import GitHub, OAuthAppAuthStrategy

github = GitHub(OAuthAppAuthStrategy("<client_id>", "<client_secret>"))

# Create a client that acts as the user
user_github = github.with_auth(github.auth.as_web_user("<code>"))

# Make a request as the user
resp = user_github.rest.users.get_authenticated()
user = resp.parsed_data

# Retrieve the tokens for persistence
user_token = user_github.auth.token
user_token_expire_time = user_github.auth.expire_time
refresh_token = user_github.auth.refresh_token
refresh_token_expire_time = user_github.auth.refresh_token_expire_time

You can also exchange the code for a token without making a request first:

from githubkit import GitHub, OAuthAppAuthStrategy, OAuthTokenAuthStrategy

github = GitHub(OAuthAppAuthStrategy("<client_id>", "<client_secret>"))

# sync
auth: OAuthTokenAuthStrategy = github.auth.as_web_user("<code>").exchange_token(github)
# async
auth: OAuthTokenAuthStrategy = await github.auth.as_web_user("<code>").async_exchange_token(github)

# Persist the tokens
user_token = auth.token
user_token_expire_time = auth.expire_time
refresh_token = auth.refresh_token
refresh_token_expire_time = auth.refresh_token_expire_time

# Create a new client with the exchanged token
user_github = github.with_auth(auth)

Device Flow → Token

from githubkit import GitHub, OAuthDeviceAuthStrategy, OAuthTokenAuthStrategy

def callback(data: dict):
    print(data["user_code"])

user_github = GitHub(OAuthDeviceAuthStrategy("<client_id>", callback))

# Option 1: Make a request first (triggers the device flow automatically)
resp = user_github.rest.users.get_authenticated()
user = resp.parsed_data

# Retrieve the tokens for persistence
user_token = user_github.auth.token
user_token_expire_time = user_github.auth.expire_time
refresh_token = user_github.auth.refresh_token
refresh_token_expire_time = user_github.auth.refresh_token_expire_time

# you can also exchange the token directly without making a request
auth: OAuthTokenAuthStrategy = github.auth.exchange_token(github)
# or asynchronously
auth: OAuthTokenAuthStrategy = await github.auth.async_exchange_token(github)

user_token = auth.token
user_token_expire_time = auth.expire_time
refresh_token = auth.refresh_token
refresh_token_expire_time = auth.refresh_token_expire_time

# Create a reusable client with the token
token_github = user_github.with_auth(auth)