<!--
    tagline: Access privately hosted packages/repositories
-->

# Authentication for privately hosted packages and repositories

Your [private package server](handling-private-packages.md) or version control system is probably secured with one
or more authentication options. In order to allow your project to have access to these
packages and repositories you will have to tell Composer how to authenticate with the server that hosts them.

# Authentication principles

Whenever Composer encounters a protected Composer repository it will try to authenticate
using already defined credentials first. When none of those credentials apply it will prompt
for credentials and save them (or a token if Composer is able to retrieve one).

|                        type                         | Generated by Prompt? |
|:---------------------------------------------------:|:--------------------:|
|              [http-basic](#http-basic)              |         yes          |
|       [Inline http-basic](#inline-http-basic)       |          no          |
|             [HTTP Bearer](#http-bearer)             |          no          |
|          [Custom Headers](#custom-headers)          |          no          |
|   [Inline Custom Headers](#inline-custom-headers)   |          no          |
|            [gitlab-oauth](#gitlab-oauth)            |         yes          |
|            [gitlab-token](#gitlab-token)            |         yes          |
|            [github-oauth](#github-oauth)            |         yes          |
|         [bitbucket-oauth](#bitbucket-oauth)         |         yes          |
| [Client TLS certificates](#client-tls-certificates) |          no          |
|           [forgejo-token](#forgejo-token)           |         yes          |

Sometimes automatic authentication is not possible, or you may want to predefine
authentication credentials.

Credentials can be stored on 4 different places; in an `auth.json` for the project, a global
`auth.json`, in the `composer.json` itself or in the `COMPOSER_AUTH` environment variable.

## Authentication in auth.json per project

In this authentication storage method, an `auth.json` file will be present in the same folder
as the projects' `composer.json` file. You can either create and edit this file using the
command line or manually edit or create it.

> **Note: Make sure the `auth.json` file is in `.gitignore`** to avoid
> leaking credentials into your git history.

## Global authentication credentials

If you don't want to supply credentials for every project you work on, storing your credentials
globally might be a better idea. These credentials are stored in a global `auth.json` in your
Composer home directory.

### Command line global credential editing

For all authentication methods it is possible to edit them using the command line;

- [http-basic](#command-line-http-basic)
- [Inline http-basic](#command-line-inline-http-basic)
- [HTTP Bearer](#command-line-http-bearer-authentication)
- [Custom Headers](#command-line-custom-headers)
- [gitlab-oauth](#command-line-gitlab-oauth)
- [gitlab-token](#command-line-gitlab-token)
- [github-oauth](#command-line-github-oauth)
- [bitbucket-oauth](#command-line-bitbucket-oauth)
- [forgejo-token](#command-line-forgejo-token)

### Manually editing global authentication credentials

> **Note:** It is not recommended to manually edit your authentication options as this might
> result in invalid json. Instead preferably use [the command line](#command-line-global-credential-editing).

To manually edit it, run:

```shell
php composer.phar config --global --editor [--auth]
```

For specific authentication implementations, see their sections;

- [http-basic](#manual-http-basic)
- [Inline http-basic](#manual-inline-http-basic)
- [HTTP Bearer](#manual-http-bearer-authentication)
- [Custom Headers](#manual-custom-headers)
- [Inline Custom Headers](#manual-inline-custom-headers)
- [gitlab-oauth](#manual-gitlab-oauth)
- [gitlab-token](#manual-gitlab-token)
- [github-oauth](#manual-github-oauth)
- [bitbucket-oauth](#manual-bitbucket-oauth)
- [Client TLS certificates](#manual-client-certificates)
- [forgejo-token](#manual-forgejo-token)

Manually editing this file instead of using the command line may result in invalid json errors.
To fix this you need to open the file in an editor and fix the error. To find the location of
your global `auth.json`, execute:

```shell
php composer.phar config --global home
```

The folder will contain your global `auth.json` if it exists.

You can open this file in your favorite editor and fix the error.

## Authentication in composer.json file itself

> **Note:** **This is not recommended** as these credentials are visible
> to anyone who has access to the composer.json, either when it is shared through
> a version control system like git or when an attacker gains (read) access to
> your production server files.

It is also possible to add credentials to a `composer.json` on a per-project basis in the `config`
section or directly in the repository definition.

## Authentication using the COMPOSER_AUTH environment variable

> **Note:** Using the command line environment variable method also has security implications.
> These credentials will most likely be stored in memory,
> and may be persisted to a file like `~/.bash_history` (linux) or `ConsoleHost_history.txt`
> (PowerShell on Windows) when closing a session.

The final option to supply Composer with credentials is to use the `COMPOSER_AUTH` environment variable.
These variables can be either passed as command line variables or set in actual environment variables.
Read more about the usage of this environment variable [here](../03-cli.md#composer-auth).

# Authentication methods

## http-basic

### Command line http-basic

```shell
php composer.phar config [--global] http-basic.repo.example.org username password
```

In the above command, the config key `http-basic.repo.example.org` consists of two parts:

- `http-basic` is the authentication method.
- `repo.example.org` is the repository host name, you should replace it with the host name of your repository.

### Manual http-basic

```shell
php composer.phar config [--global] --editor --auth
```

```json
{
    "http-basic": {
        "example.org": {
            "username": "username",
            "password": "password"
        }
    }
}
```

## Inline http-basic

For the inline http-basic authentication method the credentials are not stored in a separate
`auth.json` in the project or globally, but in the `composer.json` or global configuration
in the same place where the Composer repository definition is defined.

Make sure that the username and password are encoded according
to [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986#section-2.1) (2.1. Percent-Encoding).
If the username e.g. is an email address it needs to be passed as `name%40example.com`.

### Command line inline http-basic

```shell
php composer.phar config [--global] repositories.unique-name composer https://username:password@repo.example.org
```

### Manual inline http-basic

```shell
php composer.phar config [--global] --editor
```

```json
{
    "repositories": [
        {
            "type": "composer",
            "url": "https://username:password@example.org"
        }
    ]
}
```

## HTTP Bearer

### Command line HTTP Bearer authentication

```shell
php composer.phar config [--global] bearer.repo.example.org token
```

In the above command, the config key `bearer.repo.example.org` consists of two parts:

- `bearer` is the authentication method.
- `repo.example.org` is the repository host name, you should replace it with the host name of your repository.

### Manual HTTP Bearer authentication

```shell
php composer.phar config [--global] --editor --auth
```

```json
{
    "bearer": {
        "example.org": "TOKEN"
    }
}
```

## custom-headers

Use custom HTTP headers for authentication with private repositories that require header-based authentication.

### Command line custom-headers

```shell
php composer.phar config [--global] custom-headers.repo.example.org "API-TOKEN: YOUR-API-TOKEN" "X-CUSTOM-HEADER: Value"
```

In the above command, the config key `custom-headers.repo.example.org` consists of two parts:

- `custom-headers` is the authentication method.
- `repo.example.org` is the repository host name, you should replace it with the host name of your repository.

You can provide multiple custom headers as separate arguments. Each header must be in the standard HTTP header
format `"Header-Name: Header-Value"`.

### Manual custom-headers

```shell
php composer.phar config [--global] --editor --auth
```

```json
{
    "custom-headers": {
        "repo.example.org": [
            "API-TOKEN: YOUR-API-TOKEN",
            "X-CUSTOM-HEADER: Value"
        ]
    }
}
```

## Inline custom-headers

### Manual inline custom-headers

For the inline custom-headers authentication method, the custom headers are defined directly
in your `composer.json` file as part of the repository configuration.

```shell
php composer.phar config [--global] --editor
```

```json
{
    "repositories": [
        {
            "type": "composer",
            "url": "https://repo.example.org",
            "options": {
                "http": {
                    "header": [
                        "API-TOKEN: YOUR-API-TOKEN",
                        "X-CUSTOM-HEADER: Value"
                    ]
                }
            }
        }
    ]
}
```

## gitlab-oauth

> **Note:** For the gitlab authentication to work on private gitlab instances, the
> [`gitlab-domains`](../06-config.md#gitlab-domains) section should also contain the URL.

### Command line gitlab-oauth

```shell
php composer.phar config [--global] gitlab-oauth.gitlab.example.org token
```

In the above command, the config key `gitlab-oauth.gitlab.example.org` consists of two parts:

- `gitlab-oauth` is the authentication method.
- `gitlab.example.org` is the host name of your GitLab instance, you should replace it with the host name of your GitLab
  instance or use `gitlab.com` if you don't have a self-hosted GitLab instance.

### Manual gitlab-oauth

```shell
php composer.phar config [--global] --editor --auth
```

```json
{
    "gitlab-oauth": {
        "example.org": "token"
    }
}
```

## gitlab-token

> **Note:** For the gitlab authentication to work on private gitlab instances, the
> [`gitlab-domains`](../06-config.md#gitlab-domains) section should also contain the URL.

To create a new access token, go to
your [access tokens section on GitLab](https://gitlab.com/-/user_settings/personal_access_tokens)
(or the equivalent URL on your private instance) and create a new token. See
also [the GitLab access token documentation](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#creating-a-personal-access-token)
for more information.

When creating a gitlab token manually, make sure it has either the `read_api` or `api` scope.

### Command line gitlab-token

```shell
php composer.phar config [--global] gitlab-token.gitlab.example.org token
```

In the above command, the config key `gitlab-token.gitlab.example.org` consists of two parts:

- `gitlab-token` is the authentication method.
- `gitlab.example.org` is the host name of your GitLab instance, you should replace it with the host name of your GitLab
  instance or use `gitlab.com` if you don't have a self-hosted GitLab instance.

### Manual gitlab-token

```shell
php composer.phar config [--global] --editor --auth
```

```json
{
    "gitlab-token": {
        "example.org": "token"
    }
}
```

## github-oauth

GitHub currently offers two types of access tokens:

- [Fine-grained tokens](https://github.com/settings/personal-access-tokens)
- [Tokens (classic)](https://github.com/settings/personal-access-tokens)

These can be found in [Settings](https://github.com/settings/profile), at the very bottom of the left-side menu ([Developer options](https://github.com/settings/apps)). To create a new access token, head to your [token settings section on GitHub](https://github.com/settings/personal-access-tokens) and [generate a new token](https://github.com/settings/personal-access-tokens/new).

Read more about [Personal Access Tokens](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token).

It is [recommended](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#types-of-personal-access-tokens) to use fine-grained tokens,
as you can have much tighter control over what can be accessed. Composer requires read-only access to repository metadata and contents.

In most cases, a fine-grained token with read-only access to public repositories might be sufficient. Even without any additional permissions, these tokens [raise your API rate limits](https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api).

Additional permissions will be necessary in the following cases:

- You are using `vcs` type `repositories` entries in your `composer.json` file pointing to private repositories.
- You are cloning `source` or downloading `dist` files for private repositories over HTTPS (and not over SSH, for example).

In these cases, create a fine-grained token with read-only access to "contents". The token can be bound to either all of your or the organisation's repositories, or even scoped down to only selected repositories.

As of November 2025, fine-grained tokens are limited in that you can only use them to access the private repositories of a single user _or_ a single organisation at once. You may want to check the [GitHub documentation](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#fine-grained-personal-access-tokens-limitations) on details about that. If you need to work with repositories from different organisations, check if using directory-specific authentication configuration can meet your requirements.

As a last option, a "classic" token with the `repo` scope will give broad access to all of your private repositories – including write permissions and much more. The [scopes documentation](https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps) contains the complete list. Be careful when using this kind of token.

Regardless of the type of token used, we recommend using tokens with a limited lifetime. This reduces the exposure in case the token is compromised.

### Command line github-oauth

```shell
php composer.phar config [--global] github-oauth.github.com token
```

In the above command, the config key `github-oauth.github.com` consists of two parts:

- `github-oauth` is the authentication method.
- `github.com` is the host name for which this token applies. For GitHub you most likely do not need to change this.

### Manual github-oauth

```shell
php composer.phar config [--global] --editor --auth
```

```json
{
    "github-oauth": {
        "github.com": "token"
    }
}
```

## bitbucket-oauth

The BitBucket driver uses OAuth to access your private repositories via the BitBucket REST APIs, and you will need to
create an OAuth consumer to use the driver, please refer
to [Atlassian's Documentation](https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/). You
will need to fill the callback URL with something to satisfy BitBucket, but the address does not need to go anywhere and
is not used by Composer.

### Command line bitbucket-oauth

```shell
php composer.phar config [--global] bitbucket-oauth.bitbucket.org consumer-key consumer-secret
```

In the above command, the config key `bitbucket-oauth.bitbucket.org` consists of two parts:

- `bitbucket-oauth` is the authentication method.
- `bitbucket.org` is the host name for which this token applies. Unless you have a private instance you don't need to
  change this.

### Manual bitbucket-oauth

```shell
php composer.phar config [--global] --editor --auth
```

```json
{
    "bitbucket-oauth": {
        "bitbucket.org": {
            "consumer-key": "key",
            "consumer-secret": "secret"
        }
    }
}
```

## Client TLS certificates

Accessing private repositories that require client TLS certificates.

For global/project-wide configuration
see [Handling private packages: Security section](handling-private-packages.md#security).

### Manual client certificates

```shell
php composer.phar config [--global] --editor --auth
```

```json
{
    "client-certificate": {
        "repo.example.org": {
            "local_cert": "/path/to/certificate",
            "local_pk": "/path/to/key",
            "passphrase": "MySecretPassword"
        }
    }
}
```

Supported options are `local_cert` (required), `local_pk`, `passphrase`.
More information for options can be found at [SSL context options](https://www.php.net/manual/en/context.ssl.php)

Options could be omitted:

- `local_pk`: in case of keeping certificate and private key in a single file;
- `passphrase`: in case of passwordless private key.

## forgejo-token

> **Note:** For the forge authentication to work on private Forgejo instances, the
> [`forgejo-domains`](../06-config.md#forgejo-domains) section should also contain the domain.

To create a new access token, go to
your [applications section on Forgejo](https://codeberg.org/user/settings/applications)
(or the equivalent URL on your private instance) and create a new access token. See
also [the Forgejo access token documentation](https://docs.codeberg.org/advanced/access-token/) for more information.

When creating a Forgejo access token, make sure it has the `read:repository` scope.

### Command line forgejo-token

```shell
php composer.phar config [--global] forgejo-token.forgejo.example.org username access-token
```

In the above command, the config key `forgejo-token.forgejo.example.org` consists of two parts:

- `forgejo-token` is the authentication method.
- `forgejo.example.org` is the host name of your Forgejo instance, you should replace it with the host name of your
  Forgejo instance or use `codeberg.org` if you don't have a self-hosted Forgejo instance.

### Manual forgejo-token

```shell
php composer.phar config [--global] --editor --auth
```

```json
{
    "forgejo-token": {
        "forgejo.example.org": {
            "username": "forgejo-user",
            "token": "access-token"
        }
    }
}
```
