SSO Integration Guide

How to set up Single Sign-On (SSO) authentication for the LATTS documentation site with Cloudflare Access.

Overview

This guide covers how to integrate Single Sign-On (SSO) authentication with the LATTS documentation site to control access and ensure only authorized team members can view internal documentation. We focus on Cloudflare Access as the primary solution for modern, scalable authentication.

Cloudflare Access is the preferred authentication solution for static sites like Hugo documentation. It provides enterprise-grade security with minimal configuration.

Prerequisites

  • Cloudflare account with domain management
  • GitHub organization for team management
  • Static site hosted on Cloudflare Pages or custom domain

Step-by-Step Setup

1. Enable Cloudflare Zero Trust

  1. Navigate to Zero Trust Dashboard

    • Go to dash.cloudflare.com
    • Click Zero Trust in the sidebar
    • Complete onboarding if first-time setup
  2. Configure Team Domain

    • Set your team domain: latts-team.cloudflareaccess.com
    • This domain will handle authentication flows

2. Add GitHub as Identity Provider

  1. Create GitHub OAuth Application

    • Go to https://github.com/organizations/latts-ie/settings/applications
    • Click New OAuth App
    • Configure:
      • Application name: LATTS Docs - Cloudflare Access
      • Homepage URL: https://docs.latts.ie
      • Authorization callback URL: https://latts-team.cloudflareaccess.com/cdn-cgi/access/callback
  2. Configure GitHub in Cloudflare

    • In Zero Trust Dashboard → SettingsAuthentication
    • Click Add newGitHub
    • Enter GitHub OAuth credentials:
      • App ID: GitHub Client ID
      • Client Secret: GitHub Client Secret
      • Connection name: GitHub - LATTS Team

3. Create Access Application

  1. Add New Application

    • Go to Zero TrustAccessApplications
    • Click Add an applicationSelf-hosted
  2. Configure Application Details

    • Application name: LATTS Internal Documentation
    • Application domain: docs.latts.ie (or your domain)
    • Path: /* (protect entire site)
  3. Set Access Policies

    • Policy name: LATTS Organization Members
    • Action: Allow
    • Include rules:
      • GitHub Organizations: latts-ie
    • Click Save policy

4. Advanced Access Control

For more granular permissions:

# Team-based access control
Include:
  - GitHub Teams: latts-ie/developers
  - GitHub Teams: latts-ie/documentation-team

# Email domain restrictions
Include:
  - Emails ending in: company.com, latts.ie

# Geographic restrictions  
Include:
  - Country: Ireland, United Kingdom

# Time-based access (business hours only)
Require:
  - Time-based: Monday-Friday, 9:00-17:00 GMT

Configuration Examples

Basic Organization Access

{
  "name": "LATTS Team Access",
  "decision": "allow",
  "include": [
    {
      "github": {
        "name": "latts-ie",
        "teams": ["all"]
      }
    }
  ]
}

Granular Team Access

{
  "name": "Documentation Team Access", 
  "decision": "allow",
  "include": [
    {
      "github": {
        "name": "latts-ie",
        "teams": ["developers", "documentation-team", "leads"]
      }
    }
  ],
  "require": [
    {
      "email_domain": ["latts.ie", "company.com"]
    }
  ]
}

Alternative: GitHub OAuth with oauth2-proxy

For self-hosted deployments or custom authentication flows:

Prerequisites

  • Docker environment for oauth2-proxy
  • GitHub organization with team management
  • Reverse proxy capability (nginx, Apache, etc.)

Setup Steps

  1. Configure oauth2-proxy

    # docker-compose.yml
    version: '3'
    services:
      oauth2-proxy:
        image: quay.io/oauth2-proxy/oauth2-proxy:v7.4.0
        command:
          - --provider=github
          - --email-domain=*
          - --upstream=http://hugo-site:80
          - --http-address=0.0.0.0:4180
          - --github-org=latts-ie
          - --github-team=latts-ie/developers
          - --github-team=latts-ie/documentation-team
        environment:
          OAUTH2_PROXY_CLIENT_ID: ${GITHUB_CLIENT_ID}
          OAUTH2_PROXY_CLIENT_SECRET: ${GITHUB_CLIENT_SECRET}
          OAUTH2_PROXY_COOKIE_SECRET: ${COOKIE_SECRET}
    
  2. Nginx Reverse Proxy Configuration

    server {
        listen 443 ssl;
        server_name docs.latts.ie;
    
        # SSL configuration
        ssl_certificate /path/to/cert.pem;
        ssl_certificate_key /path/to/key.pem;
    
        # Authentication endpoint
        location /oauth2/ {
            proxy_pass http://oauth2-proxy:4180;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Scheme $scheme;
            proxy_set_header X-Auth-Request-Redirect $request_uri;
        }
    
        # Authentication subrequest
        location = /oauth2/auth {
            proxy_pass http://oauth2-proxy:4180;
            proxy_pass_request_body off;
            proxy_set_header Content-Length "";
            proxy_set_header X-Original-URI $request_uri;
        }
    
        # Protected documentation
        location / {
            auth_request /oauth2/auth;
            error_page 401 = /oauth2/sign_in;
    
            proxy_pass http://hugo-site:80;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Scheme $scheme;
    
            # Pass user information to backend
            auth_request_set $user $upstream_http_x_auth_request_user;
            auth_request_set $email $upstream_http_x_auth_request_email;
            proxy_set_header X-User $user;
            proxy_set_header X-Email $email;
        }
    }
    

Azure Active Directory Integration

For enterprise environments using Azure AD:

Prerequisites

  • Azure AD tenant access
  • Application registration permissions
  • Understanding of OIDC/SAML protocols

Setup Steps

  1. Register Application in Azure AD

    • Go to Azure Portal → Azure Active Directory → App registrations
    • Create new registration:
      • Name: LATTS Internal Documentation
      • Redirect URI: https://latts-team.cloudflareaccess.com/cdn-cgi/access/callback
      • Account types: Single tenant
  2. Configure in Cloudflare Access

    • Add Azure AD as identity provider in Zero Trust
    • Use Azure AD application credentials
    • Configure group-based access control
  3. Group-based Access Control

    {
      "name": "Azure AD Group Access",
      "decision": "allow", 
      "include": [
        {
          "azureAD": {
            "connection_id": "azure-ad-connection",
            "identity_groups": [
              "documentation-readers",
              "latts-team-all"
            ]
          }
        }
      ]
    }
    

Security Best Practices

Session Management

  • Session timeout: 8 hours maximum
  • Secure cookies: HTTPS-only, SameSite=Strict
  • Cookie secrets: Use cryptographically secure random values
  • Rotate secrets: Quarterly rotation schedule

Access Control

  • Least privilege: Grant minimum necessary access
  • Regular audits: Monthly access reviews
  • Group-based permissions: Avoid individual user grants
  • Audit logging: Enable comprehensive access logs

Infrastructure Security

  • HTTPS enforcement: Redirect all HTTP to HTTPS
  • Security headers: Implement CSP, HSTS, XSS protection
  • Rate limiting: Prevent authentication abuse
  • DDoS protection: Use Cloudflare’s built-in protection

Configuration Examples

Security Headers

# static/_headers (for Cloudflare Pages)
/*
  X-Frame-Options: DENY
  X-Content-Type-Options: nosniff
  X-XSS-Protection: 1; mode=block
  Referrer-Policy: strict-origin-when-cross-origin
  Strict-Transport-Security: max-age=31536000; includeSubDomains
  Content-Security-Policy: default-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; script-src 'self' 'unsafe-inline'

Rate Limiting (Cloudflare Rules)

{
  "expression": "(http.request.uri.path contains \"/cdn-cgi/access/\" and rate(5m) > 20)",
  "action": "challenge",
  "description": "Rate limit authentication attempts"
}

Testing and Validation

Local Testing

  1. Test OAuth flow with development applications
  2. Verify group membership affects access decisions
  3. Test session timeout and renewal behavior
  4. Validate error handling for authentication failures

Production Testing

  1. End-to-end authentication with real user accounts
  2. Different browser environments and incognito mode
  3. Mobile device compatibility for team members
  4. Edge case scenarios like expired sessions

Automated Testing

#!/bin/bash
# Authentication flow test script

# Test unauthenticated access (should redirect)
response=$(curl -s -o /dev/null -w "%{http_code}" https://docs.latts.ie/)
if [ "$response" -eq 302 ]; then
  echo "✅ Unauthenticated access properly redirects"
else
  echo "❌ Authentication not working (got $response)"
fi

# Test authentication endpoint
auth_response=$(curl -s -o /dev/null -w "%{http_code}" https://docs.latts.ie/cdn-cgi/access/get-identity)
echo "Auth endpoint response: $auth_response"

Monitoring and Maintenance

Cloudflare Analytics

  • Authentication events: Monitor login attempts and failures
  • Geographic patterns: Review access locations for anomalies
  • Device analytics: Track authentication device types
  • Performance metrics: Monitor authentication latency

Log Analysis

# Example log queries for Cloudflare Access
# Failed authentication attempts
grep "access_denied" /var/log/cloudflare-access.log | tail -10

# Geographic anomalies
grep "country" /var/log/cloudflare-access.log | sort | uniq -c

# High-frequency users
grep "user_email" /var/log/cloudflare-access.log | cut -d'"' -f4 | sort | uniq -c | sort -nr

Regular Maintenance Tasks

Weekly

  • Review failed authentication logs
  • Check for unusual access patterns
  • Verify team membership changes

Monthly

  • Audit user access permissions
  • Review and update access policies
  • Test authentication flow end-to-end
  • Check SSL certificate expiration

Quarterly

  • Rotate OAuth application secrets
  • Review and update security policies
  • Conduct access control audit
  • Update documentation based on changes

Troubleshooting

Common Issues

Authentication loops or redirects

  • Verify callback URLs match exactly in OAuth app
  • Check for trailing slashes in domain configuration
  • Ensure HTTPS is properly configured

Users in organization but can’t access

  • Verify organization membership is public
  • Check if user has two-factor authentication enabled
  • Confirm OAuth app is approved for organization

Session expires immediately

  • Check cookie domain configuration
  • Verify system clock synchronization
  • Review session timeout settings

Debug Commands

# Test DNS resolution
dig docs.latts.ie

# Check SSL certificate
openssl s_client -connect docs.latts.ie:443 -servername docs.latts.ie

# Test authentication endpoint
curl -v https://docs.latts.ie/cdn-cgi/access/get-identity

# Verify Cloudflare Access policies
curl -H "Authorization: Bearer ${CF_API_TOKEN}" \
  "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/access/apps"

Cost Analysis

Cloudflare Access Pricing

  • Free tier: Up to 50 users
  • Teams plan: $3/user/month for 1,000+ users
  • Enterprise: Custom pricing for advanced features

Comparison with Alternatives

SolutionSetup TimeMonthly CostMaintenanceSecurity Level
Cloudflare Access30 minutes$0-150/monthLowEnterprise
oauth2-proxy2-4 hoursServer costsMediumHigh
Azure AD1-2 hours$6-22/user/monthMediumEnterprise
Repository visibility5 minutes$0Very LowBasic

See Also