# How Authentication is Configured in actions/checkout: PAT vs SSH Implementation

> Learn how actions/checkout configures authentication using PAT vs SSH. Understand the simple process for secure Git access in your GitHub Actions workflows.

- Repository: [GitHub Actions/checkout](https://github.com/actions/checkout)
- Tags: deep-dive
- Published: 2026-07-05

---

**The `actions/checkout` action configures authentication by reading workflow inputs in [`src/input-helper.ts`](https://github.com/actions/checkout/blob/main/src/input-helper.ts) and applying them through [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts), which sets up either an HTTP extra header with a base64-encoded personal access token or a temporary SSH key file with a custom `GIT_SSH_COMMAND`.**

The `actions/checkout` GitHub Action supports two distinct authentication mechanisms to access private repositories: **Personal Access Tokens (PAT)** via HTTPS and **SSH keys**. Understanding how authentication is configured in actions/checkout requires examining the TypeScript source files that parse workflow inputs and translate them into Git configuration commands.

## Authentication Mechanisms Overview

The action implements two primary authentication paths:

- **Personal Access Token (PAT)**: Provided via the `token` input, stored in `IGitSourceSettings.authToken`, and applied as an HTTP extra header (`http.<host>/.extraheader`) containing a base64-encoded `x-access-token` credential.
- **SSH Key**: Provided via the `ssh-key` input (with optional `ssh-known-hosts`, `ssh-strict`, and `ssh-user`), stored in `IGitSourceSettings.sshKey`, and applied through a temporary key file and `GIT_SSH_COMMAND` environment variable.

## Input Parsing and Configuration

### Reading Workflow Inputs

Authentication configuration begins in [`src/input-helper.ts`](https://github.com/actions/checkout/blob/main/src/input-helper.ts) within the `getInputs()` function. At approximately line 139, the action reads the `token` input, which defaults to the GitHub-provided `GITHUB_TOKEN` secret:

```typescript
// Line ~139 - Authentication token
result.authToken = core.getInput('token', {required: true})

```

Immediately following at lines 142-148, the function gathers SSH-related parameters:

```typescript
// Lines ~142-148 - SSH configuration
result.sshKey = core.getInput('ssh-key')
result.sshKnownHosts = core.getInput('ssh-known-hosts')
result.sshStrict = (core.getInput('ssh-strict') || 'true').toUpperCase() === 'TRUE'
result.sshUser = core.getInput('ssh-user')

```

These values populate the `IGitSourceSettings` interface, which is passed to the authentication helper when the checkout step executes.

## Token-Based Authentication

### HTTP Extra Header Construction

When a PAT is provided, [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts) handles the configuration through the `configureToken()` method. At lines 55-65, the helper constructs the Git configuration key and value:

```typescript
const serverUrl = urlHelper.getServerUrl(this.settings.githubServerUrl)
this.tokenConfigKey = `http.${serverUrl.origin}/.extraheader`
const basicCredential = Buffer.from(`x-access-token:${this.settings.authToken}`, 'utf8')
    .toString('base64')
this.tokenConfigValue = `AUTHORIZATION: basic ${basicCredential}`

```

The `tokenConfigKey` follows the Git credential pattern `http.<host>/.extraheader`, which instructs Git to include the specified header in all HTTPS requests to that host.

### Temporary Credential Storage

At lines 26-44, `configureToken()` implements a placeholder strategy to avoid exposing the token in process listings. It writes a placeholder entry into a temporary credentials configuration file, then replaces the placeholder with the actual base64-encoded authorization header. This file is added to Git's `includeIf` chain, ensuring the token is available for subsequent Git operations without appearing in the repository's permanent configuration.

## SSH-Based Authentication

### Key File and Known Hosts Setup

If `sshKey` is supplied, the `configureSsh()` method (starting around line 50 in [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts)) performs the following operations:

1. Writes the private key to a temporary file under `RUNNER_TEMP` with a UUID filename.
2. Optionally writes known-hosts entries to a companion file, including an implicit `github.com` entry if none are specified.
3. Sets appropriate file permissions (600) on the key file.

### GIT_SSH_COMMAND Configuration

At approximately line 250, the helper constructs and exports the `GIT_SSH_COMMAND` environment variable:

```bash
ssh -i "$RUNNER_TEMP/<uuid>" -o StrictHostKeyChecking=yes -o UserKnownHostsFile=$RUNNER_TEMP/<uuid>_known_hosts

```

This command is exported via `git.setEnvironmentVariable('GIT_SSH_COMMAND', ...)` at lines 50-70, ensuring all Git SSH operations use the temporary key without modifying the user's global SSH configuration.

## Credential Persistence and Cleanup

### Persisting Credentials

The `persist-credentials` input (parsed at lines 149-152 in [`src/input-helper.ts`](https://github.com/actions/checkout/blob/main/src/input-helper.ts)) controls whether authentication settings survive beyond the checkout step. When set to `true` (the default):

- For PAT authentication: The temporary credentials file remains available for subsequent Git commands in the same job.
- For SSH authentication: The `core.sshCommand` Git configuration is set to the generated SSH command, allowing later steps to execute authenticated Git operations over SSH.

### Post-Job Cleanup

The action implements automatic cleanup through its post-job step (defined in [`action.yml`](https://github.com/actions/checkout/blob/main/action.yml) and executed via [`dist/index.js`](https://github.com/actions/checkout/blob/main/dist/index.js)). The `removeAuth()` method (lines 33-38) and related `removeGlobalConfig()` functions delete temporary key files, unset the HTTP extra header, and clear any `core.sshCommand` entries. This ensures secrets do not persist on the runner after the workflow completes.

## Practical Implementation Examples

### Minimal Checkout with PAT

The most common configuration uses the default GitHub token:

```yaml
- name: Checkout repository
  uses: actions/checkout@v4
  with:
    token: ${{ secrets.GITHUB_TOKEN }}

```

This creates a temporary Git config entry at `http.<host>/.extraheader` containing the base64-encoded `x-access-token` credential, authenticating all Git HTTPS operations for the job.

### SSH Key Authentication

For repositories requiring SSH deployment keys:

```yaml
- name: Checkout via SSH
  uses: actions/checkout@v4
  with:
    ssh-key: ${{ secrets.DEPLOY_SSH_KEY }}
    ssh-known-hosts: |
      github.com ssh-rsa AAAAB3...
    persist-credentials: true

```

This writes the private key and known-hosts to temporary files, sets `GIT_SSH_COMMAND`, and configures `core.sshCommand` in the repository's Git config, enabling authenticated SSH operations for subsequent steps.

### Disabling Credential Persistence

For least-privilege security models, prevent credential persistence:

```yaml
- name: Checkout (no later Git auth)
  uses: actions/checkout@v4
  with:
    token: ${{ secrets.PAT }}
    persist-credentials: false

```

With this configuration, the token is only used for the initial `git fetch` and `git checkout` operations. The `removeAuth()` method immediately cleans up the temporary configuration, preventing later steps from unintentionally accessing the repository using the PAT.

## Summary

- **Authentication in `actions/checkout`** is configured through two primary mechanisms: PAT via the `token` input and SSH via the `ssh-key` input.
- **Input parsing** occurs in [`src/input-helper.ts`](https://github.com/actions/checkout/blob/main/src/input-helper.ts) (lines 139-152), where `getInputs()` populates the `IGitSourceSettings` interface.
- **Token authentication** creates a base64-encoded HTTP extra header (`http.<host>/.extraheader`) in [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts) (lines 26-65) using the `x-access-token` scheme.
- **SSH authentication** generates temporary key files and sets `GIT_SSH_COMMAND` in [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts) (lines 50-70, ~250) to isolate credentials from the global SSH agent.
- **Credential persistence** is controlled by the `persist-credentials` input and cleaned up automatically by the post-job step invoking `removeAuth()` (lines 33-38).

## Frequently Asked Questions

### What is the default authentication method in actions/checkout?

By default, `actions/checkout` uses the Personal Access Token provided via the `token` input, which defaults to `${{ secrets.GITHUB_TOKEN }}`. As implemented in [`src/input-helper.ts`](https://github.com/actions/checkout/blob/main/src/input-helper.ts) at line 139, this token is always read and passed to the authentication helper, making HTTPS the default transport unless overridden by specifying `ssh-key`.

### How does actions/checkout secure the token during the workflow?

The action implements a placeholder strategy in [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts) (lines 26-44) where `configureToken()` writes a dummy value to a temporary config file before replacing it with the actual base64-encoded credential. Additionally, tokens are never written to the permanent Git configuration; they exist only in temporary files that are deleted by the post-job cleanup step calling `removeAuth()`.

### Can I use both token and SSH authentication simultaneously?

No, the action processes these as mutually exclusive authentication paths. According to the source code in [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts), if `sshKey` is present, the action configures SSH authentication via `configureSsh()`, while token authentication via `configureToken()` is typically used for HTTPS operations. The workflow should specify one method based on the repository URL scheme.

### Why should I set persist-credentials to false?

Setting `persist-credentials: false` (parsed at lines 149-152 in [`src/input-helper.ts`](https://github.com/actions/checkout/blob/main/src/input-helper.ts)) prevents the action from leaving authentication credentials in the Git configuration or environment variables after the checkout step completes. This follows the principle of least privilege, ensuring that subsequent steps in the same job cannot accidentally or maliciously access the repository using the stored credentials.