Accounts, Two-Factor Authentication, SSH Keys, Access Tokens, Service Accounts, and Credentials: Concepts, Architecture, and Mental Model
Build a precise mental model of GitLab authentication, authorization, 2FA, SSH, token classes, service identities, and CI job credentials before creating or using secrets.
Learning objectives
- Separate authentication from authorization across web, Git transport, API/CLI, and CI execution.
- Explain 2FA, passkeys, recovery codes, SSH key custody, and host verification without exposing secret material.
- Distinguish personal, project, group, deploy, job, trigger, impersonation, and service-account credentials by identity, reach, and lifetime.
- Reason about effective access as the intersection of credential permission, membership role, resource policy, and endpoint support.
- Choose read-only inspection methods that prove identity and context before mutation.
1. One account, several authentication channels
Chapter 01 separated Git from GitLab resources. Chapter 02 adds the identity layer. The important beginner mistake to avoid is treating “my GitLab password,” “my SSH key,” “my API token,” and “the credential used by a CI job” as different spellings of one secret. They are different authentication mechanisms with different lifetimes, storage locations, scopes, and audit consequences.
Authentication answers “which identity or workload presented an acceptable credential?” Authorization answers “may that authenticated principal perform this operation on this resource?” Successful authentication is therefore necessary but not sufficient. A valid token can still receive a permission denial because the user, bot, service account, token scope, project role, SSO session, protected resource, or job-token allowlist does not authorize the requested action.
2. Credential and authorization mental model
flowchart LR H[Human operator] --> WEB[Web session\npassword / passkey / SSO + 2FA] H --> SSH[SSH private key\nlocal machine] H --> CLI[glab OAuth or PAT] H --> HTTPS[Git over HTTPS\ncredential helper + token] WEB --> GL[GitLab authorization\nuser + membership + policy] SSH --> GL CLI --> GL HTTPS --> GL JOB[CI job] --> JT[CI_JOB_TOKEN\njob lifetime] JT --> GL SVC[Service identity] --> ST[service account PAT\nor resource/deploy token] ST --> GL GL --> P[Project / group / API / registry / environment]
The arrows do not mean every credential reaches every resource. The web session, SSH transport, API/CLI token, job token, deploy token, and service account credential all arrive at GitLab through different authentication paths. GitLab then applies authorization rules for the target resource. A runner is not automatically a trusted user, and a token scope is not a substitute for project membership.
3. Separate sign-in, Git transport, API/CLI, and CI identity
| Channel | Typical credential | What it authenticates | Important boundary |
|---|---|---|---|
| Interactive web | Password, passkey, SSO; 2FA when configured | A human browser session | Session authentication does not grant a higher project role. |
| Git over SSH | SSH private key held locally; public key registered in GitLab | Git transport identity | The private key never belongs in GitLab, source control, chat, or CI logs. |
| Git over HTTPS | Access token stored by an appropriate credential helper | Git HTTP transport | Do not embed the token in the remote URL. |
| glab | OAuth is the preferred interactive GitLab.com path; PAT and job-token modes also exist | CLI/API operations |
glab auth status can verify state; do not use
token-display options in course evidence.
|
| REST/GraphQL | OAuth/access token or supported workload token | API client identity | Token type, scope, resource reach, and user role all matter. |
| CI job | CI_JOB_TOKEN |
A running GitLab job | Generated for the job, limited to supported resources/endpoints, and revoked after the job ends. |
4. Account protection: 2FA, passkeys, and recovery
Two-factor authentication (2FA) makes account takeover harder by requiring a second factor after the primary sign-in step. GitLab supports OTP authenticators and WebAuthn/passkey-style methods; passkeys can also be used for sign-in in supported configurations. The exact methods exposed can depend on the GitLab version and instance policy.
Recovery planning is part of enabling 2FA, not an afterthought. OTP setup produces recovery codes that must be stored outside GitLab and outside the device whose loss they are intended to cover. Each recovery code is single-use. Do not paste recovery codes into a password manager field that is synchronized to an untrusted team vault, issue, repository, screenshot, or lesson evidence packet.
Never “test” recovery by disabling a known-good factor on a valuable account. A safe lab verifies that recovery material exists and is stored appropriately without exposing it.
5. SSH keys: public registration, private custody
An SSH keypair has two halves. The public key can be registered with GitLab. The private key proves possession and must remain on the trusted client. GitLab does not need your private key. The server also has its own SSH host key: verifying that host fingerprint protects you from accepting an unexpected server during first connection.
For GitLab.com, GitLab publishes current SSH host fingerprints. For
Self-Managed or Dedicated, verify the instance-specific fingerprints
from the instance help/configuration or your administrator. A
successful ssh -T git@gitlab.com proves SSH
authentication to that host; it does not prove authorization to
every repository.
6. Token classes are identities with different reach
| Credential class | Identity / reach | Typical use | Availability note |
|---|---|---|---|
| Personal access token (PAT) | User identity; can reach resources the user can access, constrained by scope/permissions | API, HTTPS Git, tooling | Free/Premium/Ultimate across GitLab.com, Self-Managed, Dedicated; instance/group policy can restrict use. |
| Fine-grained PAT | User identity with resource-specific permissions | Least-privilege API/Git automation | Current docs mark it generally available in GitLab 19.2; verify target version. |
| Project access token | Bot identity scoped to one project | Project automation | GitLab.com currently requires Premium/Ultimate; Self-Managed/Dedicated availability differs. |
| Group access token | Bot identity scoped to a group hierarchy | Group automation | GitLab.com currently requires Premium/Ultimate; Self-Managed/Dedicated availability differs. |
| Deploy token | Dedicated non-human credential for supported Git/registry/package operations | Deployment/read distribution | Available across tiers/offerings; not a general GitLab public API credential. |
CI_JOB_TOKEN |
Running job, influenced by triggering user and allowlist/policy | Job-to-GitLab access | All tiers/offerings; short-lived and endpoint-limited. |
| Pipeline trigger token | Project trigger credential associated with creator access | Start pipelines from external systems | Treat as a secret; leakage can cause unauthorized pipeline execution. |
| Impersonation/admin token | Acts as another user | Administrator support/automation | Administrator-only on Self-Managed/Dedicated; not a normal learner credential. |
The table deliberately separates scope from reach.
A read_api project token cannot escape its project
simply because the scope sounds broad. Conversely, a personal token
may have wide resource reach because its user has broad membership
even if the token is “read only.”
7. Service accounts and service identities
A service account is a non-human GitLab account intended for automation that should not depend on a specific employee remaining on the team. Current GitLab documentation describes service accounts as non-billable, external users that cannot sign in through the normal UI; they authenticate using personal access tokens and must still be granted membership/roles where needed. Availability and creation limits vary by offering and subscription, so verify current documentation rather than copying a quota into production policy.
Do not conclude that every automation should use a service account.
For a GitLab CI job, CI_JOB_TOKEN is usually preferable
when it supports the required endpoint because its lifetime is
naturally bounded to the job. For external read-only package
consumption, a deploy token can be a narrower fit. Identity choice
should follow the task.
8. Scope, role, resource, and policy form an authorization intersection
Think of effective permission as the intersection of several constraints rather than one switch:
effective permission ≈ authenticated identity
∩ token / credential permission
∩ project or group role
∩ resource visibility / protection
∩ SSO / instance / namespace policy
∩ endpoint-specific token support
This is a mental model, not a literal GitLab formula. It explains why adding a broader token scope can fail to solve a missing project role, and why granting Maintainer can fail to solve an endpoint that does not accept a deploy token.
9. Read-only inspection first
Start by proving which host and authentication context you are using. None of the commands below should print secret values.
git remote -v
ssh -G git@gitlab.com | grep -E '^(hostname|user|identityfile) '
glab auth status --hostname gitlab.com
glab repo view -F json # inside a GitLab project clone, if glab is authenticated
glab auth status has an option that can display stored
token material. Do not use that option in
screenshots, logs, support tickets, or course exercises. The useful
evidence is host, authenticated account, protocol/context, and
whether authentication succeeds.
10. Why credential hygiene is a DevOps control
Review rules and protected branches matter only if the identities operating them are trustworthy. A leaked Maintainer PAT can turn a carefully designed pipeline into an attack surface. A long-lived personal token in deployment automation can silently become an orphaned dependency after offboarding. A runner can expose credentials if untrusted code is allowed to print or exfiltrate them.
Production credential design therefore asks: Who or what is the principal? What resource must it reach? Through which protocol? For how long? From what machine/runner? What evidence will prove use? How is it revoked and rotated?
Knowledge check
An SSH test succeeds, but a push to a private project is denied. Did authentication fail?
Not necessarily. The SSH key may have authenticated the user successfully while project membership, branch protection, or another authorization rule denies the push. Inspect identity and authorization separately.
Why should a CI job prefer CI_JOB_TOKEN over a long-lived PAT when the required endpoint supports it?
The job token is created for the running job, has a narrower supported surface, and is revoked when the job ends. That reduces credential lifetime and usually improves attribution compared with a reusable human PAT.
Does a read_api scope prove that a token can read every project on the GitLab instance?
No. Scope limits operations, while token reach and the underlying user/bot membership still constrain which resources are visible.
Where should an SSH private key be registered in GitLab?
Nowhere. Register only the public key. The private key stays under the client or automation system's custody.
Why are 2FA recovery codes part of availability engineering?
If the second factor is lost, recovery codes may be the remaining path to the account. Poor custody can lock out an operator; exposed codes can weaken account security.
Summary
GitLab authentication is a family of channels, not one credential. Separate web sessions, SSH, HTTPS Git, CLI/API, service identities, trigger tokens, and job identity; then apply scope, role, resource, SSO, and platform policy. Protect recovery material and private keys, prefer short-lived workload identity where possible, and prove current state before changing credentials.
Official references
- GitLab Docs — Token overview
- GitLab Docs — Access token scopes
- GitLab Docs — Two-factor authentication
- GitLab Docs — 2FA troubleshooting and recovery
- GitLab Docs — Passkeys
- GitLab Docs — SSH keys
- GitLab CLI — Authentication
- GitLab CLI — glab auth status
- GitLab Docs — Personal access tokens
- GitLab Docs — Project access tokens
- GitLab Docs — Group access tokens
- GitLab Docs — Deploy tokens
- GitLab Docs — CI/CD job token
- GitLab Docs — Service accounts
- GitLab Docs — REST API authentication
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.