Files
docs/cli-docs/authentication.md
T
2026-10-22 11:28:15 +02:00

7.4 KiB

sidebar_position
sidebar_position
3

Logging in

gt auth login logs in to a Gitea instance. gt can authenticate in three ways:

Method Flag Best for
OAuth in a web browser --oauth Interactive use, instances with single sign-on or two-factor authentication
Access token --with-token Any instance, machines without a browser
SSH key signing --ssh-key, --ssh-agent-key, --ssh-agent-principal Using an SSH key you already have instead of a token

gt never asks for your password. On a terminal, gt auth login without a method flag asks for the instance, how to log in, where to keep the token, and whether Git should use gt for the instance:

gt auth login

OAuth

gt auth login --host https://gitea.example.com --oauth

gt opens the instance's authorization page in your browser, or prints its URL when no browser opens. You sign in there as you do on the web, so single sign-on through an external identity provider and two-factor authentication work unchanged. gt listens on 127.0.0.1 for the answer, so the browser has to run on the same machine as gt. OAuth needs this interaction and is refused with --no-input.

By default the token has write access to everything but administration. --scopes requests fewer, using the token scope names:

gt auth login --host https://gitea.example.com --oauth --scopes read:repository,read:user

gt refreshes an expiring OAuth token on its own. gt auth refresh refreshes it now.

gt uses the OAuth application that Gitea registers by default for its command line client, listed as tea in DEFAULT_APPLICATIONS. If an administrator turned it off, register an OAuth2 application that is not a confidential client, with the redirect URI http://127.0.0.1, and pass its client ID with --client-id. gt remembers the ID for the instance.

Access tokens

  1. Sign in to the instance in a web browser, with single sign-on or two-factor authentication if the instance uses them.

  2. Under Settings > Applications, create an access token with the scopes you need.

  3. Save the token in a private file and log in with it:

    gt auth login --host https://gitea.example.com --with-token < token.txt
    

    On a terminal, --with-token without input asks for the token instead.

gt needs read:user to find out which account a token belongs to. Add the scopes of the commands you use:

Scope Commands
repository repo, pr, release, branch, run, workflow, secret and variable of a repository, webhook, wiki
issue issue, label, milestone, time, and comments on pull requests
organization org, team, and secret, variable and webhook with --org
notification notification
package package
user ssh-key, and secret and variable with --account
admin admin

Choose write: for the commands that change something, read: for the ones that only read. Gitea counts pull request comments, labels and milestones as issue operations, so working with pull requests usually needs both write:repository and write:issue. The scopes table describes each scope.

A token pasted with --with-token cannot be refreshed. When it expires or is revoked, log in again.

Where credentials are kept

gt keeps the instances and accounts in hosts.yml and its preferences in config.yml, in its configuration directory. gt config path prints both files; GITEA_CLI_CONFIG_DIR moves the directory.

Tokens are not written to these files. --credential-store chooses where they go:

  • keyring (default): the system keyring, such as the macOS Keychain, the Windows Credential Manager, or the Secret Service on Linux. When no keyring is available, the login fails rather than falling back to a file.
  • file: a credentials directory in the configuration directory that only your user can read. Use it where no keyring exists, such as in a container or over SSH.

A token given in GITEA_TOKEN is never stored. See Using gt in CI.

gt auth status shows the accounts on each instance, the active one, and how each authenticates; gt auth status --verify checks every credential against its instance. gt auth token prints the token of the active account, for scripts that call the API themselves. gt auth logout forgets an account and deletes its stored credential.

SSH keys

Instead of a token, gt can sign each API request with an SSH key that is registered for your account on the instance:

gt auth login --host https://gitea.example.com --ssh-key ~/.ssh/id_ed25519

When a certificate (id_ed25519-cert.pub) is next to the key, gt signs with the certificate. gt asks for the passphrase of an encrypted key. To sign with a key held by ssh-agent, pass its fingerprint with --ssh-agent-key; to sign with an agent certificate, pass its principal with --ssh-agent-principal. Accounts that sign requests have no token, so gt auth token has nothing to print for them.

Git over HTTPS

gt's own clone and checkout commands authenticate without any setup. For git push and git fetch over HTTPS, let Git ask gt for credentials:

gt auth setup-git
gt auth setup-git --host gitea.example.com
# only for the current repository, always as alice
gt auth setup-git --local --user alice

Git then uses the active account of the instance, or the account of --user. Other credential helpers, such as a system keychain, are turned off for the instance, since they would answer first and keep a copy of gt's token; --keep-helpers keeps them. gt auth login on a terminal offers to do this for you.

Several instances and accounts

Run gt auth login once per instance and account. Commands pick the instance from the repository's Git remote, --host, GITEA_CLI_HOST, the default_host setting, or the only instance you are logged in to; gt help environment gives the full order.

Each instance has one active account. gt auth switch changes it: with two accounts it toggles between them, with more it asks which one. --user, or GITEA_CLI_USER, uses another account for a single command:

gt auth switch bob --host gitea.example.com
gt issue list --user alice

To use another instance by default outside a clone:

gt config set default_host https://gitea.example.com

Access proxies and client certificates

An instance behind an access proxy may need extra headers or a TLS client certificate. --header sends a header with every request to the instance; a value of $NAME or ${NAME} is read from that environment variable each time, so the secret stays out of gt's files:

gt auth login --host https://gitea.example.com --with-token \
  --header 'CF-Access-Client-Id: $CF_ID' \
  --header 'CF-Access-Client-Secret: $CF_SECRET' < token.txt

--client-cert presents a PEM client certificate, and --client-key names its unencrypted PEM key when the key is not in the certificate file. Convert a PKCS#12 file with:

openssl pkcs12 -in cert.p12 -clcerts -nokeys -out cert.pem
openssl pkcs12 -in cert.p12 -nocerts -nodes -out key.pem

gt keeps these per instance; gt config set headers, client_cert and client_key with --host change them later. --insecure skips TLS certificate verification for an instance, for testing only.