Testing auth

This is a draft. Meant for quick self reference for testing auth flows with Keycloak and other such tools.

Challenges:

  • Auth bugs = security nightmares
  • Can't mess with prod identity providers
  • Need realistic flows for integration tests
  • Load testing requires predictable tokens

docker compose for keycloak

version: '3.8'
services:
  keycloak:
    image: quay.io/keycloak/keycloak:latest
    ports:
      - "8080:8080"
    environment:
      KEYCLOAK_ADMIN: felonious
      KEYCLOAK_ADMIN_PASSWORD: st3v3car3ll
    command: start-dev

GitHub Actions (CI/CD)

services:
  keycloak:
    image: quay.io/keycloak/keycloak:latest
    ports:
      - 8080:8080
    options: >-
      --health-cmd "curl --fail http://localhost:8080/health/ready || exit 1"
      --health-interval 10s
      --health-timeout 5s
      --health-retries 10
    env:
      KEYCLOAK_ADMIN: felonious
      KEYCLOAK_ADMIN_PASSWORD: st3v3car3ll
    command: start-dev

Note:Use health checks and increase retries if needed. Keycloak takes forever to start up.

Setup testing Realm

Manually

  • Go to http://localhost:8080
  • Login: admin/admin
  • Create realm β†’ Import JSON

Automated Way (for CI)

# Configure admin CLI
docker exec my-keycloak /opt/keycloak/bin/kcadm.sh config credentials \
  --server http://localhost:8080 --realm master --user felonious --password st3v3car3ll

# Import realm config
docker exec my-keycloak /opt/keycloak/bin/kcadm.sh create realms -f /realm-export.json

Testing OAuth2 Flows

Client Credentials (Service-to-Service)

# Get token
curl -X POST "http://localhost:8080/realms/test-realm/protocol/openid-connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=test-client" \
  -d "client_secret=test-secret"

# Response
{
  "access_token": "something_alpha_numeric_h3r3",
  "token_type": "Bearer",
  "expires_in": 300
}

Authorization Code Flow (OIDC)

# Step 1: Get auth code (browser redirect)
http://localhost:8080/realms/test-realm/protocol/openid-connect/auth?
  client_id=test-client&
  redirect_uri=http://localhost:3000/callback&
  response_type=code&
  scope=openid

# Step 2: Exchange code for token
curl -X POST "http://localhost:8080/realms/test-realm/protocol/openid-connect/token" \
  -d "grant_type=authorization_code" \
  -d "client_id=test-client" \
  -d "client_secret=test-secret" \
  -d "code=AUTH_CODE_HERE" \
  -d "redirect_uri=http://localhost:3000/callback"

Token Validation

# Decode JWT (don't use in prod!)
echo "TOKEN_HERE" | cut -d '.' -f2 | base64 -d | jq .

# Validate token against userinfo endpoint
curl -H "Authorization: Bearer TOKEN_HERE" \
  http://localhost:8080/realms/test-realm/protocol/openid-connect/userinfo

Health Check Script

#!/bin/bash
echo "Waiting for Keycloak..."
for i in {1..30}; do
  if curl -s http://localhost:8080/health/ready | grep UP; then
    echo "βœ… Keycloak ready!"
    exit 0
  fi
  echo "⏳ Still waiting... ($i/30)"
  sleep 5
done
echo "❌ Keycloak failed to start"
exit 1

Basic SAML Response Test

<!-- Test SAML assertion structure -->
<saml2:Assertion>
  <saml2:Subject>
    <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">
      [email protected]
    </saml2:NameID>
  </saml2:Subject>
  <saml2:AttributeStatement>
    <saml2:Attribute Name="email">
      <saml2:AttributeValue>[email protected]</saml2:AttributeValue>
    </saml2:Attribute>
  </saml2:AttributeStatement>
</saml2:Assertion>

Google OAuth2 Playground

Good for testing real-world integrations

  1. Go to https://developers.google.com/oauthplayground/
  2. Pick scopes you need
  3. Authorize & get code
  4. Exchange for tokens
  5. Test API calls

Good for:

  • Debug redirect URI issues
  • Test scope combinations
  • Validate token refresh flows

Testing Checklist

Happy Path Tests

  • [ ] Can get access token
  • [ ] Token contains expected claims
  • [ ] Token works for API calls
  • [ ] Refresh token works

Error Scenarios

  • [ ] Invalid client credentials
  • [ ] Expired tokens
  • [ ] Invalid redirect URIs
  • [ ] Missing scopes
  • [ ] Network timeouts

Security Tests

  • [ ] PKCE validation (if applicable)
  • [ ] State parameter validation
  • [ ] CSRF protection
  • [ ] Token expiration enforced
  • [ ] Proper CORS headers

Gotchas

  • Keycloak startup time: Use health checks, don't assume it's ready
  • Clock skew: SAML is picky about timestamps.
  • Redirect URI matching: Must be exact, including trailing slashes
  • HTTPS in prod: OAuth2 requires HTTPS (except localhost; can't bypass it)
  • Token storage: Don't log tokens in plaintext (this test doesn't cover it explicitly.)

Keycloak APIs

# Get all realms
GET /admin/realms

# Get realm info
GET /admin/realms/{realm}

# Get clients
GET /admin/realms/{realm}/clients

# Get users
GET /admin/realms/{realm}/users

# Token introspection
POST /realms/{realm}/protocol/openid-connect/token/introspect

Environment Variables Template

# Keycloak
KEYCLOAK_URL=http://localhost:8080
KEYCLOAK_REALM=test-realm
KEYCLOAK_CLIENT_ID=test-client
KEYCLOAK_CLIENT_SECRET=test-secret

# Testing
[email protected]
TEST_USER_PASSWORD=password123

Quick Docker Commands

# Start Keycloak
docker run -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin \
  quay.io/keycloak/keycloak:21.1.1 start-dev

# Check logs
docker logs <container_id> -f

# Get container ID
docker ps -q -f ancestor=quay.io/keycloak/keycloak

# Execute commands in container
docker exec -it <container_id> bash
  • Realm export/import: Great for backing up configs
  • Custom themes: Test UI changes in development realm first
  • Event listeners: Useful for debugging auth flows
  • Admin API: Automate user/client management
  • Database: H2 for dev, PostgreSQL for serious testing