Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
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:
- Go to Settings → Secrets and variables → Actions
- 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
- ✅ Never commit real OAuth credentials to the repository
- ✅ Use GitHub secrets for real credentials
- ✅ Restrict real OAuth tests to internal PRs only
- ✅ Use mock OAuth for external/fork PRs
- ✅ 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