Chapter 02Lesson 01~145 minutes

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.

AuthenticationAuthorization2FASSHTokensService identity

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.

Core production rule: diagnose identity and authorization separately. “The token works” is not proof that the token should be able to read a private project, push a protected branch, start a deployment, or access another project.

2. Credential and authorization mental model

Authentication channels and trust boundaries
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.

GitLab.com Free recovery consequence: current GitLab documentation states that Support cannot reset 2FA for Free accounts when normal recovery methods are exhausted. Treat recovery-code custody as a real availability control and verify the current policy before relying on support.

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?

Why should a CI job prefer CI_JOB_TOKEN over a long-lived PAT when the required endpoint supports it?

Does a read_api scope prove that a token can read every project on the GitLab instance?

Where should an SSH private key be registered in GitLab?

Why are 2FA recovery codes part of availability engineering?

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.

Next lesson

Build a safe disposable authentication workflow

Lesson 2 creates a dedicated SSH lab key, verifies the server identity, authenticates glab without exposing credentials, and performs a scoped read-only API exercise.

Official references

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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.