Skip to content

<GitHubAuth>

The <GitHubAuth> block provides a streamlined interface for authenticating to GitHub.

It automatically detects if the user is already authenticated to GitHub by checking their local environment variables or the GitHub CLI status. It also enables users to authenticate manually via OAuth or by entering a Personal Access Token (PAT). Once authenticated, GitHub credentials are automatically available to subsequent Command and Check blocks.

You can still authenticate to GitHub without this block by using Runbooks’ support for environment variables, however this is the recommended way to authenticate to GitHub in Runbooks.

<GitHubAuth
id="gh-auth"
title="Authenticate to GitHub"
description="Sign in to access private repositories"
/>
<Command
id="clone-repo"
githubAuthId="gh-auth"
title="Clone Repository"
command="git clone https://github.com/gruntwork-io/runbooks.git"
/>

By default, Runbooks will automatically detect and use credentials from:

  1. Environment variables (GITHUB_TOKEN or GH_TOKEN)
  2. GitHub CLI (gh auth token)

If no credentials are detected, users can authenticate manually via OAuth or PAT.

The GitHubAuth block supports multiple authentication sources:

MethodDescription
Environment VariableAuto-detected from GITHUB_TOKEN or GH_TOKEN
GitHub CLIAuto-detected from gh auth token
OAuthSign in via GitHub’s device authorization flow (recommended)
Personal Access TokenEnter a PAT (classic or fine-grained) directly in the UI

The GitHubAuth block supports GitHub.com, GitHub Enterprise Cloud and GitHub Enterprise Server. However, OAuth is only supported for GitHub.com and GitHub Enterprise Cloud. For GitHub Enterprise Server, you can use PAT authentication or contact Gruntwork for enterprise support options.

PropTypeDefaultDescription
idstringrequiredUnique identifier for this component
titlestring”GitHub Authentication”Display title shown in the UI
descriptionstring-Description of the authentication purpose
detectCredentialsfalse or CredentialSource[]['env', 'cli']Whether and how the block should automatically detect credentials in the user’s environment
oauthClientIdstringGruntwork defaultCustom OAuth App client ID
oauthScopesstring[]["repo"]OAuth scopes to request

When authentication succeeds, the following environment variables are set in the session:

VariableDescription
GITHUB_TOKENThe GitHub access token
GITHUB_USERThe authenticated user’s login name

All subsequent Command and Check blocks automatically have access to these credentials. If you authenticate multiple times, the most recent credentials become the default.

You can explicitly reference a GitHubAuth block using the githubAuthId prop. This provides several benefits:

  • Prevents premature execution: The Run/Check button is disabled until the referenced GitHubAuth block has valid credentials, preventing accidental execution without authentication
  • Clear dependency: Documents which authentication is required for each command
  • Deterministic credentials: When multiple GitHubAuth blocks exist, ensures the command uses the exact credentials you specify
<GitHubAuth
id="gh-auth"
title="Authenticate to GitHub"
/>
<Check
id="verify-auth"
title="Verify GitHub Access"
command="gh auth status"
githubAuthId="gh-auth"
successMessage="Successfully authenticated!"
/>
<Command
id="clone-repo"
title="Clone Repository"
command="git clone https://github.com/org/repo.git"
githubAuthId="gh-auth"
successMessage="Repository cloned!"
/>

How Environment Variables Work with References

Section titled “How Environment Variables Work with References”

When a GitHubAuth block authenticates, it does two things:

  1. Sets session-level environment variables (GITHUB_TOKEN, GITHUB_USER) that are available to all subsequent blocks
  2. Stores credentials that can be passed to specific blocks via githubAuthId

When you use githubAuthId to reference a GitHubAuth block, the credentials from that specific GitHubAuth block are passed as environment variables that override any session-level values for that block only. This ensures the command uses the exact credentials from the referenced block, even if:

  • Multiple GitHubAuth blocks exist with different credentials
  • Session-level GITHUB_TOKEN was set by a different auth block
  • The user re-authenticated with different credentials later

Without githubAuthId, blocks use whatever GITHUB_TOKEN is currently in the session environment (set by the most recent authentication).

By default, GitHubAuth automatically detects existing credentials from environment variables and GitHub CLI. You can customize this behavior with the detectCredentials prop.

With no configuration, GitHubAuth tries these sources in order:

{/* Default - same as detectCredentials={['env', 'cli']} */}
<GitHubAuth id="gh-auth" />
  1. Environment variables - GITHUB_TOKEN or GH_TOKEN
  2. GitHub CLI - gh auth token

If either source provides valid credentials, authentication succeeds immediately. If neither is found, users see the manual OAuth/PAT interface.

SourceDescription
'env'Check standard env vars (GITHUB_TOKEN, GH_TOKEN)
{ env: { prefix: 'PREFIX_' } }Check prefixed env vars (PREFIX_GITHUB_TOKEN, PREFIX_GH_TOKEN)
'cli'Check GitHub CLI (gh auth token)
{ block: 'block-id' }Use token from a Command block’s output

Check only environment variables:

<GitHubAuth
id="gh-auth"
detectCredentials={['env']}
/>

Check prefixed environment variables (e.g., PROD_GITHUB_TOKEN):

<GitHubAuth
id="gh-auth"
detectCredentials={[{ env: { prefix: 'PROD_' } }, 'cli']}
/>

Prefix rules (security):

  • Uppercase letters, numbers, and underscores only
  • Must start with a letter
  • Optional trailing underscore (recommended for readability)
  • Only allows reading PREFIX_GITHUB_TOKEN / PREFIX_GH_TOKEN

Force manual authentication only:

<GitHubAuth
id="gh-auth"
detectCredentials={false}
/>

Use a token generated by a previous Command block:

<Command
id="fetch-token"
path="scripts/get-token.sh"
title="Fetch GitHub Token"
/>
<GitHubAuth
id="dynamic-auth"
title="GitHub Access"
detectCredentials={[{ block: 'fetch-token' }]}
/>

The Command script should output the token:

#!/bin/bash
# Example: fetch token from a secrets manager
TOKEN=$(vault read -field=token secret/github)
echo "GITHUB_TOKEN=$TOKEN" >> "$RUNBOOK_OUTPUT"

Once authenticated to GitHub, Runbooks will update the environment variables GITHUB_TOKEN and GITHUB_USER with the authenticated user’s token and username. GitHub tokens have permissions that control what actions they can perform. The way permissions are configured depends on the authentication method:

MethodHow Permissions Are Set
Environment VariablePermissions are inherited from however the token was originally created
GitHub CLIPermissions are inherited from gh auth login; Runbooks warns if repo scope is missing
OAuthRunbook author specifies OAuth scopes via oauthScopes prop; user approves on GitHub
Personal Access Token (PAT)User configures permissions when creating the token on GitHub

When users authenticate via OAuth, the oauthScopes prop controls what permissions are requested. Users see these scopes on GitHub’s authorization page and must approve them.

The default is ["repo"], which grants full read/write access to repositories. Consider requesting fewer permissions if your runbook has limited needs:

ScopeDescription
repoFull access to private and public repositories (default)
public_repoAccess to public repositories only
repo:statusRead/write commit status (useful for CI)
read:orgRead organization membership

For a complete list, see GitHub’s OAuth scopes documentation.

<GitHubAuth
id="gh-auth"
title="Limited GitHub Access"
oauthScopes={["public_repo", "read:org"]}
/>

When users authenticate with a PAT, the token’s permissions are determined by how the user created it on GitHub. Runbook authors cannot control PAT permissions.

  • Classic PATs use the same scope system as OAuth (e.g., repo, read:org)
  • Fine-grained PATs offer more granular control per-repository

If your runbook requires specific permissions, document them clearly so users know what to configure when creating their PAT.

When GitHubAuth detects credentials from environment variables or GitHub CLI, those tokens retain whatever permissions they were created with. If a detected token lacks required permissions, operations may fail at runtime.

The GitHubAuth block is designed with a local-first security model:

  1. Gruntwork never sees your credentials. All authentication happens between your machine and GitHub. Tokens are never transmitted to Gruntwork servers.
  2. Credentials stay in memory. Tokens are stored only in your local Runbooks session and are never persisted to disk.

Each authentication method keeps your credentials on your machine:

MethodHow It Works
Environment VariableRunbooks reads GITHUB_TOKEN from your local environment. The token never leaves your machine.
GitHub CLIRunbooks calls gh auth token locally. The token is retrieved from your CLI’s secure storage and stays local.
OAuthUses GitHub’s Device Authorization Grant. GitHub sends the token directly to your local Runbooks instance—Gruntwork’s servers are never involved.
Personal Access TokenYou paste the token into the local UI. It’s sent directly to your local Runbooks server (localhost), never to any external server.

When you authenticate via OAuth:

  1. Runbooks (running on your machine) requests a device code from GitHub
  2. You open github.com/login/device and enter the code
  3. You see “Gruntwork Runbooks wants to access your account” and approve
  4. GitHub sends the token directly to your local Runbooks instance

The token goes from GitHub to your machine. Gruntwork has no server in this flow and cannot intercept your token.

As part of our internal security practices, we’ve analyzed the potential risks of using the GitHubAuth block.

Malicious Runbook with Custom oauthClientId

Section titled “Malicious Runbook with Custom oauthClientId”

Scenario: An attacker publishes a runbook with oauthClientId="attacker-app-id".

What happens:

  • You see “Attacker’s App” (not “Gruntwork Runbooks”) on GitHub’s authorization page
  • If you approve, the token still goes to YOUR local machine, not the attacker
  • The attacker registered an OAuth app but has no server receiving tokens

Risk: None. The attacker cannot intercept your token because it goes directly from GitHub to your machine. The only effect is that “Attacker’s App” appears in your GitHub authorized apps list, which you can revoke.

Mitigation: Despite no risk, this is still a potential indicator of suspicious activity, so Runbooks displays a warning when oauthClientId differs from the default. Always verify the app name on GitHub’s authorization page before approving.

Scenario: An attacker publishes a runbook that attempts to redirect OAuth to a fake GitHub login page (e.g., oauthBaseUrl="https://github-login.attacker.com").

What happens: Nothing. Runbooks does not allow oauthBaseUrl as a prop. GitHubAuth only communicates with Github.com, so the attack fails before it starts.

Risk: None. This attack vector is blocked by design.

Scenario: A runbook requests excessive permissions with oauthScopes={["repo", "admin:org", "delete_repo"]}.

What happens: Runbooks displays the requested scopes in the UI before you authenticate. GitHub’s authorization page also displays all requested scopes. If you approve without reviewing either, you grant broader access than needed.

Risk: Low. Both Runbooks and GitHub clearly display requested scopes, giving you two opportunities to review before granting access.

Mitigation: Review the scopes shown in Runbooks before clicking “Sign in with GitHub”, and verify them again on GitHub’s authorization page. Be suspicious of runbooks requesting admin:*, delete_repo, or write:* scopes beyond the default repo.

Since Gruntwork never has your tokens, revoking access doesn’t “take back” anything from Gruntwork as there’s nothing to take back. However, revoking at GitHub invalidates the token itself, which is useful if:

  • You want to ensure the token in your local Runbooks session stops working
  • You’re done with a runbook and want to clean up
  • You suspect a token may have been exposed

You can manage authorizations at:

Alternatively, simply closing your Runbooks session discards any tokens stored locally.