Accounts, Two-Factor Authentication, SSH Keys, Access Tokens, Service Accounts, and Credentials: Guided Hands-On Workflow and Core Operations
Create a disposable SSH identity, verify GitLab host and project access, authenticate glab safely, exercise a minimal read-only API credential, and prove cleanup.
Learning objectives
- Inspect account, Git remote, and glab authentication state without revealing secret material.
- Generate a dedicated SSH keypair, register only its public key, verify the server host fingerprint, and test repository authorization.
- Authenticate glab through a current supported OAuth flow and verify the selected GitLab host/context.
- Use a temporary minimally scoped token for one read-only API call without placing the token in command history or source.
- Revoke/remove every temporary credential and independently verify cleanup.
1. Preflight: use a disposable identity surface, not production credentials
- Never reuse an employer SSH key or a production automation token for this lab.
- Do not paste recovery codes, private keys, PAT values, browser cookies, or OAuth refresh tokens into source files, screenshots, chat, or shell command arguments.
- Before creating a key/token, record its purpose, intended scope, expected lifetime, and cleanup action.
- If your account is managed by an organization, do not weaken SSO or 2FA policy for the lab.
2. Inspect account and CLI state without exposing secrets
In GitLab, review the current account security pages for password/authentication methods, SSH keys, personal access tokens, and authorized applications. Record only metadata such as method type, key title/fingerprint, token name/scopes/expiry, and application name. Never copy the secret values.
# Local/CLI state: safe metadata only
git config --get user.name
git config --get user.email
git remote -v
glab auth status --hostname gitlab.com
Git commit author metadata is not an authentication credential. A commit can carry any configured name/email; GitLab access is decided by the transport/session/token identity and authorization policy.
3. Verify 2FA and recovery readiness safely
If 2FA is already enabled, confirm you still control at least one enrolled method and that recovery material is stored in an appropriate protected location. Do not reveal or regenerate codes merely to produce evidence. If 2FA is not enabled and this is your own disposable/personal account, follow the current GitLab setup flow only if you can securely retain recovery information.
Passkeys can reduce phishing risk when used correctly, but they do not remove the need to understand recovery. Organization-managed SSO can also change which sign-in methods are permitted. Record the method and policy, not the secret or biometric data.
4. Create a dedicated SSH keypair
Create a separate Ed25519 key so cleanup cannot accidentally remove your normal Git key. A passphrase is recommended when the key will live on a workstation.
# Bash, Git Bash, macOS, Linux, or Windows OpenSSH
ssh-keygen -t ed25519 -C "gitlab-ch02-disposable" \
-f ~/.ssh/id_ed25519_gitlab_ch02
# Inspect fingerprints; this does not reveal the private key.
ssh-keygen -lf ~/.ssh/id_ed25519_gitlab_ch02.pub
Open the .pub file and register only that
public key in your GitLab SSH key settings with a clear lab title
and an expiry if the current UI supports your intended lifecycle.
The file without .pub is the private key and must never
be uploaded.
cat ~/.ssh/id_ed25519_gitlab_ch02 in a
recorded terminal.
There is no learning value in displaying private key material.
5. Verify the GitLab SSH host before trusting it
Before accepting a first-connection host key, compare the fingerprint shown by SSH with GitLab's currently published GitLab.com SSH host fingerprints. For a Self-Managed/Dedicated instance, use the instance-specific fingerprint source supplied by the operator.
# Force this test to use the dedicated lab identity.
ssh -o IdentitiesOnly=yes \
-i ~/.ssh/id_ed25519_gitlab_ch02 \
-T git@gitlab.com
Expected successful authentication identifies your GitLab username and explains that GitLab does not provide shell access. A success here proves the key maps to a GitLab account on this host. It does not prove push rights to the lab project.
6. Connect SSH authentication to one disposable project
Use the project's SSH clone URL and the dedicated identity. To avoid
changing your normal SSH configuration, you can use
GIT_SSH_COMMAND for a single read-only operation:
export GIT_SSH_COMMAND='ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_gitlab_ch02'
git ls-remote git@gitlab.com:YOUR_NAMESPACE/credential-hygiene-lab.git
unset GIT_SSH_COMMAND
Compare the returned default-branch SHA with the GitLab project page. This verifies both authentication and repository authorization without modifying a ref.
7. Authenticate glab with the current supported flow
For interactive GitLab.com use, current GitLab CLI documentation supports OAuth browser or device flows. OAuth avoids asking you to manually copy a reusable PAT into the command line.
# Browser-capable workstation
glab auth login --hostname gitlab.com --web --git-protocol ssh
# Headless environment: authorize using the one-time device flow
glab auth login --hostname gitlab.com --device
# Verify metadata without displaying token material
glab auth status --hostname gitlab.com
glab repo view -R YOUR_NAMESPACE/credential-hygiene-lab -F json
On Self-Managed/Dedicated, OAuth setup can require an application/client configuration and version support; PAT authentication remains another supported path. Verify the target instance documentation. Never add token-display flags to a recorded status command.
8. Perform a minimally scoped read-only API call
The mandatory API concept can be learned with a temporary PAT on
GitLab Free. Create a token named ch02-readonly-lab,
choose the shortest practical expiry, and grant only a read scope
needed for the chosen request. The token value is shown once: place
it directly into a secure input mechanism, not into a script or
remote URL.
For a simple profile read, use a token with read_user.
In Bash, prompt without echoing the value:
read -rsp "Temporary GitLab token: " GITLAB_TOKEN; echo
curl --silent --show-error --fail-with-body \
--header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://gitlab.com/api/v4/user" \
| python -m json.tool
unset GITLAB_TOKEN
PowerShell can avoid command-history exposure by using a secure prompt, converting only inside the current process for the HTTP request, and clearing the variable afterward:
$secure = Read-Host "Temporary GitLab token" -AsSecureString
$token = [System.Net.NetworkCredential]::new("", $secure).Password
Invoke-RestMethod -Uri "https://gitlab.com/api/v4/user" `
-Headers @{"PRIVATE-TOKEN" = $token}
$token = $null
Remove-Variable secure -ErrorAction SilentlyContinue
Expected output is your authenticated profile metadata. Do not save the complete response if it contains personal fields you would not publish.
9. Revoke temporary API credentials and remove the SSH key
Return to the token list and revoke ch02-readonly-lab.
Then repeat the API request only if you can do so without recovering
the old value; the important verification is that the token is
listed revoked/inactive or no longer usable. Remove the dedicated
SSH public key from GitLab and test that the dedicated identity no
longer authenticates.
ssh -o IdentitiesOnly=yes \
-i ~/.ssh/id_ed25519_gitlab_ch02 \
-T git@gitlab.com
# After GitLab-side removal this dedicated identity should no longer authenticate.
Only after hosted removal is verified should you delete the local disposable keypair. Do not delete your default keys by pattern.
10. Read-only tour of credentials you should not create just to learn them
| Feature | Why no creation is required here | What to inspect |
|---|---|---|
| Project/group access tokens | GitLab.com creation is currently tier-dependent. | Official docs: bot identity, role, scopes, expiry, resource boundary. |
| Service accounts | Useful for automation but unnecessary for a beginner credential lab. | Account cannot use normal UI sign-in; membership still grants authorization; quotas/creation roles vary. |
| Impersonation tokens | Administrator-only and high impact. | Self-Managed/Dedicated admin use, auditability, scope, expiry. |
| CI job token | Chapter 10+ will execute pipelines. | Job lifetime, endpoint limitations, target allowlist, triggering-user permissions. |
11. Challenge — choose the credential before choosing the command
For each scenario, choose a credential class and justify why it is
narrower than the alternatives: a human cloning over SSH; a
workstation running glab; a CI job reading an allowed
GitLab resource; an external deployment host pulling a package; a
long-running integration independent of employee turnover. Do not
create the credentials. Your answer must name identity, resource,
protocol, lifetime, and revocation owner.
Knowledge check
Why does the SSH lab use a dedicated filename instead of ~/.ssh/id_ed25519?
Cleanup becomes explicit and low-risk. The learner can remove the lab key without accidentally deleting or overwriting an existing production/personal identity.
What does ssh -T prove that git ls-remote additionally tests?
ssh -T proves account-level SSH authentication to the GitLab host. git ls-remote also exercises authorization to read the specific repository and returns repository refs.
Why is OAuth a good default for interactive glab on GitLab.com?
It avoids manually copying a reusable PAT into terminal commands while using a supported interactive authorization flow. PATs remain appropriate in other contexts when deliberately scoped and stored.
After revoking a PAT, is deleting it from a shell script enough verification?
No. Revocation occurs at GitLab. Removing local text only removes one copy; verify the GitLab credential state and ensure the old token no longer authenticates.
Summary
You inspected authentication state without disclosing secrets, created and removed a dedicated SSH key, verified the GitLab server identity, separated account authentication from repository authorization, authenticated glab with a supported flow, made one minimally scoped read-only API request, and revoked temporary credentials. The workflow deliberately proves state before and after every credential mutation.
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
- GitLab.com settings — SSH host fingerprints
- GitLab CLI — glab auth login
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.