Files
gh-lucacri-claude-gitlab-do…/skills/gitlab/references/authentication.md
2025-11-30 08:38:11 +08:00

16 KiB

GitLab Authentication Reference

Overview

GitLab supports multiple authentication methods for accessing the API, Git repositories, and the web interface.

Authentication Methods

1. Personal Access Tokens (PATs)

Most common method for API and Git authentication.

Creating a Personal Access Token

Via UI:

  1. Navigate to User Settings > Access Tokens
  2. Enter token name
  3. Set expiration date (optional but recommended)
  4. Select scopes
  5. Click "Create personal access token"
  6. Copy token (shown only once)

Scopes:

  • api - Complete API access
  • read_api - Read-only API access
  • read_user - Read user information
  • read_repository - Read repository (pull code)
  • write_repository - Write repository (push code)
  • read_registry - Read container registry
  • write_registry - Write container registry
  • sudo - Perform actions as any user (admin only)
  • admin_mode - Admin mode access

Using Personal Access Tokens

API requests:

# Header method (preferred)
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.com/api/v4/projects"

# Query parameter method
curl "https://gitlab.com/api/v4/projects?private_token=<your_access_token>"

Git operations:

# Clone with token
git clone https://oauth2:<your_access_token>@gitlab.com/username/project.git

# Or configure credential helper
git config --global credential.helper store
# Then use token as password when prompted

Python example:

import requests

token = "your_access_token"
headers = {"PRIVATE-TOKEN": token}

response = requests.get(
    "https://gitlab.com/api/v4/projects",
    headers=headers
)
print(response.json())

Token Best Practices

  • Set expiration dates on all tokens
  • Use minimal required scopes
  • Store tokens securely (environment variables, secret managers)
  • Rotate tokens regularly
  • Revoke unused tokens
  • Never commit tokens to repositories

2. OAuth 2.0

OAuth 2.0 for third-party application authorization.

OAuth Application Setup

Create OAuth Application:

  1. Navigate to User Settings > Applications
  2. Enter application name
  3. Set redirect URI
  4. Select scopes
  5. Click "Save application"
  6. Note Application ID and Secret

Authorization Code Flow:

import requests
from flask import Flask, request, redirect

app = Flask(__name__)

CLIENT_ID = "your_client_id"
CLIENT_SECRET = "your_client_secret"
REDIRECT_URI = "http://localhost:5000/callback"
GITLAB_URL = "https://gitlab.com"

@app.route('/login')
def login():
    """Redirect user to GitLab authorization page"""
    auth_url = (
        f"{GITLAB_URL}/oauth/authorize?"
        f"client_id={CLIENT_ID}&"
        f"redirect_uri={REDIRECT_URI}&"
        f"response_type=code&"
        f"scope=read_user+api"
    )
    return redirect(auth_url)

@app.route('/callback')
def callback():
    """Handle OAuth callback"""
    code = request.args.get('code')

    # Exchange code for access token
    token_response = requests.post(
        f"{GITLAB_URL}/oauth/token",
        data={
            'client_id': CLIENT_ID,
            'client_secret': CLIENT_SECRET,
            'code': code,
            'grant_type': 'authorization_code',
            'redirect_uri': REDIRECT_URI
        }
    )

    token_data = token_response.json()
    access_token = token_data['access_token']
    refresh_token = token_data['refresh_token']

    # Use access token for API requests
    headers = {'Authorization': f'Bearer {access_token}'}
    user_response = requests.get(
        f"{GITLAB_URL}/api/v4/user",
        headers=headers
    )

    return user_response.json()

if __name__ == '__main__':
    app.run(port=5000)

Refreshing Access Token:

def refresh_access_token(refresh_token):
    response = requests.post(
        f"{GITLAB_URL}/oauth/token",
        data={
            'client_id': CLIENT_ID,
            'client_secret': CLIENT_SECRET,
            'refresh_token': refresh_token,
            'grant_type': 'refresh_token',
            'redirect_uri': REDIRECT_URI
        }
    )
    return response.json()

OAuth Scopes

  • api - Full API access
  • read_user - Read user information
  • read_api - Read-only API access
  • read_repository - Read repositories
  • write_repository - Write to repositories
  • read_registry - Read container registry
  • write_registry - Write container registry
  • sudo - Admin impersonation (admin only)
  • openid - OpenID Connect
  • profile - User profile info
  • email - User email

3. SSH Keys

SSH keys for Git operations.

Generating SSH Keys

# Generate new SSH key
ssh-keygen -t ed25519 -C "your_email@example.com"

# Or RSA (if ed25519 not supported)
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

# Start SSH agent
eval "$(ssh-agent -s)"

# Add key to agent
ssh-add ~/.ssh/id_ed25519

Adding SSH Key to GitLab

Via UI:

  1. Navigate to User Settings > SSH Keys
  2. Paste public key content (~/.ssh/id_ed25519.pub)
  3. Set title
  4. Optional: Set expiration date
  5. Click "Add key"

Via API:

curl --request POST --header "PRIVATE-TOKEN: <token>" \
  --data "title=My SSH Key" \
  --data "key=$(cat ~/.ssh/id_ed25519.pub)" \
  "https://gitlab.com/api/v4/user/keys"

Using SSH Keys

# Clone with SSH
git clone git@gitlab.com:username/project.git

# Configure Git to use SSH
git remote set-url origin git@gitlab.com:username/project.git

# Test SSH connection
ssh -T git@gitlab.com

SSH Key Best Practices

  • Use Ed25519 keys (more secure, faster)
  • Set passphrase on private keys
  • Use separate keys for different purposes
  • Set expiration dates
  • Store private keys securely
  • Never share private keys

4. Deploy Keys

Read-only or read-write SSH keys for specific projects.

Creating Deploy Keys

Via UI:

  1. Navigate to Project Settings > Repository > Deploy Keys
  2. Enter title and key content
  3. Check "Grant write permissions" if needed
  4. Click "Add key"

Via API:

curl --request POST --header "PRIVATE-TOKEN: <token>" \
  --data "title=Deploy Key" \
  --data "key=$(cat ~/.ssh/deploy_key.pub)" \
  --data "can_push=false" \
  "https://gitlab.com/api/v4/projects/:id/deploy_keys"

Deploy Key Use Cases

  • CI/CD pipelines
  • Deployment scripts
  • Automated processes
  • Read-only repository access

5. Deploy Tokens

Project or group-level tokens for registry and package access.

Creating Deploy Tokens

Via UI:

  1. Navigate to Project/Group Settings > Repository > Deploy Tokens
  2. Enter name
  3. Set expiration date
  4. Select scopes:
    • read_repository - Clone repositories
    • read_registry - Pull container images
    • write_registry - Push container images
    • read_package_registry - Pull packages
    • write_package_registry - Push packages
  5. Click "Create deploy token"
  6. Copy username and token

Via API:

curl --request POST --header "PRIVATE-TOKEN: <token>" \
  --header "Content-Type: application/json" \
  --data '{
    "name": "My Deploy Token",
    "expires_at": "2025-12-31",
    "scopes": ["read_repository", "read_registry"]
  }' \
  "https://gitlab.com/api/v4/projects/:id/deploy_tokens"

Using Deploy Tokens

Clone repository:

git clone https://<deploy-token-username>:<deploy-token>@gitlab.com/group/project.git

Pull Docker image:

docker login -u <deploy-token-username> -p <deploy-token> registry.gitlab.com
docker pull registry.gitlab.com/group/project/image:tag

CI/CD:

docker-build:
  script:
    - docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY
    - docker pull $CI_REGISTRY_IMAGE:latest

6. Job Tokens (CI/CD)

Temporary tokens for CI/CD job authentication.

Using CI_JOB_TOKEN

API requests in CI:

test-api:
  script:
    - |
      curl --header "JOB-TOKEN: $CI_JOB_TOKEN" \
        "https://gitlab.com/api/v4/projects/$CI_PROJECT_ID"

Clone other repositories:

build:
  script:
    - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/group/project.git

Pull Docker images:

build:
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker pull $CI_REGISTRY_IMAGE:latest

Job Token Scope

Configure which projects can be accessed:

  1. Navigate to Settings > CI/CD > Token Access
  2. Add allowed projects
  3. Enable/disable token access

7. Project Access Tokens

Project-level tokens for automation.

Creating Project Access Tokens

Via UI:

  1. Navigate to Project Settings > Access Tokens
  2. Enter token name
  3. Set expiration date
  4. Select role (Guest, Reporter, Developer, Maintainer)
  5. Select scopes
  6. Click "Create project access token"

Via API:

curl --request POST --header "PRIVATE-TOKEN: <token>" \
  --header "Content-Type: application/json" \
  --data '{
    "name": "Project Token",
    "scopes": ["api"],
    "access_level": 40,
    "expires_at": "2025-12-31"
  }' \
  "https://gitlab.com/api/v4/projects/:id/access_tokens"

Access Levels:

  • 10: Guest
  • 20: Reporter
  • 30: Developer
  • 40: Maintainer
  • 50: Owner

8. Group Access Tokens

Group-level tokens for all group projects.

Creating Group Access Tokens

Via UI:

  1. Navigate to Group Settings > Access Tokens
  2. Configure token (similar to project tokens)
  3. Token applies to all group projects

Via API:

curl --request POST --header "PRIVATE-TOKEN: <token>" \
  --header "Content-Type: application/json" \
  --data '{
    "name": "Group Token",
    "scopes": ["api"],
    "access_level": 40
  }' \
  "https://gitlab.com/api/v4/groups/:id/access_tokens"

9. LDAP Authentication

Enterprise edition feature for LDAP/Active Directory integration.

LDAP Configuration

/etc/gitlab/gitlab.rb:

gitlab_rails['ldap_enabled'] = true
gitlab_rails['ldap_servers'] = YAML.load <<-EOS
  main:
    label: 'LDAP'
    host: 'ldap.example.com'
    port: 636
    uid: 'sAMAccountName'
    encryption: 'simple_tls'
    verify_certificates: true
    bind_dn: 'CN=query user,OU=Users,DC=example,DC=com'
    password: 'password'
    active_directory: true
    base: 'OU=Users,DC=example,DC=com'
    user_filter: '(memberOf=CN=GitLab Users,OU=Groups,DC=example,DC=com)'
EOS

10. SAML Authentication

Enterprise edition SAML SSO support.

SAML Configuration

/etc/gitlab/gitlab.rb:

gitlab_rails['omniauth_enabled'] = true
gitlab_rails['omniauth_allow_single_sign_on'] = ['saml']
gitlab_rails['omniauth_block_auto_created_users'] = false

gitlab_rails['omniauth_providers'] = [
  {
    name: 'saml',
    args: {
      assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
      idp_cert_fingerprint: 'XX:XX:XX...',
      idp_sso_target_url: 'https://idp.example.com/sso',
      issuer: 'https://gitlab.example.com',
      name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'
    },
    label: 'Company SSO'
  }
]

Security Best Practices

Token Management

  1. Minimize Scope: Use least privilege principle
  2. Set Expiration: Always set token expiration dates
  3. Rotate Regularly: Rotate tokens on schedule
  4. Secure Storage: Use secret managers (Vault, AWS Secrets Manager)
  5. Monitor Usage: Audit token usage regularly
  6. Revoke Unused: Remove tokens no longer needed

Secure Token Storage

Environment Variables:

export GITLAB_TOKEN="your_token"

Git Credentials:

# Store credentials securely
git config --global credential.helper 'cache --timeout=3600'

Python example:

import os
from dotenv import load_dotenv

load_dotenv()
GITLAB_TOKEN = os.getenv('GITLAB_TOKEN')

Docker Secrets:

echo "your_token" | docker secret create gitlab_token -

Two-Factor Authentication (2FA)

Enabling 2FA

  1. Navigate to User Settings > Account > Two-Factor Authentication
  2. Scan QR code with authenticator app
  3. Enter verification code
  4. Save recovery codes securely

Using 2FA with Git

When 2FA is enabled, use:

  • Personal access tokens instead of passwords
  • SSH keys for Git operations
# Use token as password
git clone https://oauth2:<your_token>@gitlab.com/username/project.git

IP Allowlisting

Restrict API access by IP address (Premium/Ultimate).

Group/Instance Settings:

  1. Navigate to Settings > General > Allowed IP addresses
  2. Add IP ranges
  3. Save changes

API Authentication Examples

Python (requests library)

import requests

class GitLabClient:
    def __init__(self, token, base_url="https://gitlab.com"):
        self.token = token
        self.base_url = base_url
        self.headers = {"PRIVATE-TOKEN": token}

    def get(self, endpoint):
        url = f"{self.base_url}/api/v4/{endpoint}"
        response = requests.get(url, headers=self.headers)
        response.raise_for_status()
        return response.json()

    def post(self, endpoint, data):
        url = f"{self.base_url}/api/v4/{endpoint}"
        response = requests.post(url, headers=self.headers, json=data)
        response.raise_for_status()
        return response.json()

# Usage
client = GitLabClient(token="your_token")
projects = client.get("projects")

JavaScript (fetch API)

class GitLabClient {
  constructor(token, baseURL = 'https://gitlab.com') {
    this.token = token;
    this.baseURL = baseURL;
  }

  async get(endpoint) {
    const response = await fetch(`${this.baseURL}/api/v4/${endpoint}`, {
      headers: {
        'PRIVATE-TOKEN': this.token
      }
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    return await response.json();
  }

  async post(endpoint, data) {
    const response = await fetch(`${this.baseURL}/api/v4/${endpoint}`, {
      method: 'POST',
      headers: {
        'PRIVATE-TOKEN': this.token,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(data)
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    return await response.json();
  }
}

// Usage
const client = new GitLabClient('your_token');
const projects = await client.get('projects');

Go

package main

import (
    "fmt"
    "github.com/xanzy/go-gitlab"
)

func main() {
    git, err := gitlab.NewClient("your_token")
    if err != nil {
        panic(err)
    }

    // List projects
    projects, _, err := git.Projects.ListProjects(&gitlab.ListProjectsOptions{})
    if err != nil {
        panic(err)
    }

    for _, project := range projects {
        fmt.Printf("Project: %s\n", project.Name)
    }
}

Ruby

require 'gitlab'

# Initialize client
Gitlab.configure do |config|
  config.endpoint = 'https://gitlab.com/api/v4'
  config.private_token = 'your_token'
end

# List projects
projects = Gitlab.projects

projects.each do |project|
  puts "Project: #{project.name}"
end

Troubleshooting

Common Authentication Issues

1. 401 Unauthorized

  • Verify token is valid and not expired
  • Check token has required scopes
  • Ensure token is included in request headers

2. 403 Forbidden

  • Check user permissions on resource
  • Verify token scope includes required access
  • For protected resources, check branch protection rules

3. SSH Connection Failed

  • Verify SSH key is added to GitLab
  • Check SSH agent is running
  • Test connection: ssh -T git@gitlab.com
  • Verify SSH key permissions (600 for private key)

4. Token Not Working with 2FA

  • Use personal access token instead of password
  • Or use SSH keys for Git operations

5. Deploy Token Issues

  • Verify token hasn't expired
  • Check token scopes match operation
  • Ensure token is enabled in project settings

Additional Resources