Files
2026-02-13 09:12:11 +00:00

9.0 KiB

Using Mock OAuth2 Server in CI/CD

This guide explains how to use the mock OAuth2 server infrastructure in continuous integration pipelines.

GitHub Actions Configuration

Running with Mock OAuth (Default)

The tests automatically use mock OAuth by default. No special configuration needed:

name: Tests with Mock OAuth

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4

    - name: Set up Python
      uses: actions/setup-python@v5
      with:
        python-version: '3.12'

    - name: Install dependencies
      run: |
        pip install -r requirements-dev.txt

    - name: Run OAuth tests (mock)
      run: |
        pytest tests/test_oauth_integration_flows.py -v

Running with Real OAuth (Using Secrets)

To test with real OAuth credentials (e.g., Authentik, Auth0):

name: Tests with Real OAuth

on: [push, pull_request]

jobs:
  test-real-oauth:
    runs-on: ubuntu-latest
    # Only run if secrets are available (not on external PRs)
    if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository

    steps:
    - uses: actions/checkout@v4

    - name: Set up Python
      uses: actions/setup-python@v5
      with:
        python-version: '3.12'

    - name: Install dependencies
      run: |
        pip install -r requirements-dev.txt

    - name: Run OAuth tests (real)
      env:
        AUTHENTIK_CLIENT_ID: ${{ secrets.AUTHENTIK_CLIENT_ID }}
        AUTHENTIK_CLIENT_SECRET: ${{ secrets.AUTHENTIK_CLIENT_SECRET }}
        AUTHENTIK_CONFIG_URL: ${{ secrets.AUTHENTIK_CONFIG_URL }}
      run: |
        # Tests auto-detect real credentials and use them
        pytest tests/test_oauth_integration_flows.py -v -m requires_external

Hybrid Approach (Best Practice)

Run both mock and real tests in separate jobs:

name: OAuth Tests

on: [push, pull_request]

jobs:
  test-mock-oauth:
    name: OAuth Tests (Mock)
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4

    - name: Set up Python
      uses: actions/setup-python@v5
      with:
        python-version: '3.12'

    - name: Install dependencies
      run: |
        pip install -r requirements-dev.txt

    - name: Run mock OAuth tests
      run: |
        pytest tests/test_oauth_integration_flows.py \
          -v \
          -m "not requires_external"

  test-real-oauth:
    name: OAuth Tests (Real - Internal Only)
    runs-on: ubuntu-latest
    # Only run on internal commits where secrets are available
    if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository

    steps:
    - uses: actions/checkout@v4

    - name: Set up Python
      uses: actions/setup-python@v5
      with:
        python-version: '3.12'

    - name: Install dependencies
      run: |
        pip install -r requirements-dev.txt

    - name: Run real OAuth tests
      env:
        AUTHENTIK_CLIENT_ID: ${{ secrets.AUTHENTIK_CLIENT_ID }}
        AUTHENTIK_CLIENT_SECRET: ${{ secrets.AUTHENTIK_CLIENT_SECRET }}
        AUTHENTIK_CONFIG_URL: ${{ secrets.AUTHENTIK_CONFIG_URL }}
      run: |
        pytest tests/test_oauth_integration_flows.py \
          -v \
          -m requires_external

Required GitHub Secrets

To enable real OAuth testing, configure these secrets in your repository:

  1. Go to Settings → Secrets and variables → Actions
  2. Add the following secrets:
Secret Name Description Example Value
AUTHENTIK_CLIENT_ID OAuth client ID docuelevate-app
AUTHENTIK_CLIENT_SECRET OAuth client secret super-secret-value
AUTHENTIK_CONFIG_URL OIDC discovery URL https://auth.example.com/application/o/docuelevate/.well-known/openid-configuration

Docker Service (Alternative to Testcontainers)

If you prefer not to use testcontainers in CI, you can run mock-oauth2-server as a service:

name: Tests with OAuth Service

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest

    services:
      mock-oauth:
        image: ghcr.io/navikt/mock-oauth2-server:2.1.1
        ports:
          - 8080:8080
        options: >-
          --health-cmd "wget -q -O /dev/null http://localhost:8080/default/.well-known/openid-configuration || exit 1"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
    - uses: actions/checkout@v4

    - name: Set up Python
      uses: actions/setup-python@v5
      with:
        python-version: '3.12'

    - name: Install dependencies
      run: |
        pip install -r requirements-dev.txt

    - name: Configure OAuth to use service
      run: |
        export OAUTH_MOCK_URL=http://localhost:8080
        export USE_MOCK_OAUTH=true

    - name: Run tests
      run: |
        pytest tests/test_oauth_integration_flows.py -v

Forcing Mock or Real Mode

You can override the automatic detection with environment variables:

# Force mock mode (even if real credentials available)
export USE_MOCK_OAUTH=true
pytest tests/test_oauth_integration_flows.py -v

# Force real mode (will skip if credentials not available)
export USE_REAL_OAUTH=true
pytest tests/test_oauth_integration_flows.py -v

Debugging OAuth Tests in CI

View Container Logs

Add this step to debug mock OAuth server issues:

- name: Show mock OAuth logs (on failure)
  if: failure()
  run: |
    docker ps -a
    docker logs $(docker ps -aq --filter ancestor=ghcr.io/navikt/mock-oauth2-server:2.1.1)

Enable Verbose Logging

- name: Run tests with verbose logging
  run: |
    pytest tests/test_oauth_integration_flows.py -vvs --log-cli-level=DEBUG

Check Well-Known Endpoint

- name: Verify mock OAuth server
  run: |
    curl -f http://localhost:8080/default/.well-known/openid-configuration || exit 1

Performance Considerations

  • Mock OAuth: ~1s startup time, tests run in <10s
  • Real OAuth: Depends on network latency, typically <30s
  • Docker Service: Fastest for CI (pre-started), ~0.5s overhead

Security Best Practices

  1. Never commit real OAuth credentials to the repository
  2. Use GitHub secrets for real credentials
  3. Restrict real OAuth tests to internal PRs only
  4. Use mock OAuth for external/fork PRs
  5. Rotate secrets regularly if compromised

Troubleshooting

Tests Skip with "OAuth credentials not available"

Cause: Real OAuth credentials not configured or not accessible.

Solution:

  • For local dev: Use mock mode (default)
  • For CI: Add secrets to GitHub repository settings
  • Check secret availability: if github.event_name == 'push'

Mock OAuth Server Won't Start

Cause: Docker not available or testcontainers can't start container.

Solution:

- name: Start Docker
  run: |
    sudo systemctl start docker
    docker ps

Tests Timeout Waiting for Server

Cause: Server taking too long to start or health check failing.

Solution: Increase timeout in conftest_oauth.py:

container.wait_for_ready(timeout=60)  # Increase from 30

Example: Complete GitHub Actions Workflow

name: Full OAuth Testing Suite

on: [push, pull_request]

jobs:
  # Fast mock OAuth tests (always run)
  mock-oauth-tests:
    name: OAuth Tests (Mock)
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4

    - name: Set up Python
      uses: actions/setup-python@v5
      with:
        python-version: '3.12'

    - name: Install dependencies
      run: pip install -r requirements-dev.txt

    - name: Run mock OAuth tests
      run: |
        pytest tests/test_oauth_integration_flows.py \
          -v \
          -m "not requires_external" \
          --cov=app.auth \
          --cov-report=term-missing

    - name: Upload coverage
      uses: codecov/codecov-action@v3
      with:
        files: ./coverage.xml
        flags: oauth-mock

  # Real OAuth tests (only for internal PRs/pushes)
  real-oauth-tests:
    name: OAuth Tests (Real - Internal)
    runs-on: ubuntu-latest
    if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository

    steps:
    - uses: actions/checkout@v4

    - name: Set up Python
      uses: actions/setup-python@v5
      with:
        python-version: '3.12'

    - name: Install dependencies
      run: pip install -r requirements-dev.txt

    - name: Run real OAuth tests
      env:
        AUTHENTIK_CLIENT_ID: ${{ secrets.AUTHENTIK_CLIENT_ID }}
        AUTHENTIK_CLIENT_SECRET: ${{ secrets.AUTHENTIK_CLIENT_SECRET }}
        AUTHENTIK_CONFIG_URL: ${{ secrets.AUTHENTIK_CONFIG_URL }}
      run: |
        pytest tests/test_oauth_integration_flows.py \
          -v \
          -m requires_external

    - name: Upload coverage
      uses: codecov/codecov-action@v3
      with:
        files: ./coverage.xml
        flags: oauth-real

This workflow:

  • Runs mock tests on all PRs (fast, no secrets needed)
  • Runs real tests only when secrets available
  • Uploads separate coverage reports
  • Provides detailed feedback