mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-06-05 22:44:17 +00:00
e64fc7f730
* Add redis support for distributed caching * Move towards the self-provided Redis connection pool and RESP protocol implementation. Official redis client library won't work with yaegi. * fixup! Move towards the self-provided Redis connection pool and RESP protocol implementation. Official redis client library won't work with yaegi. * fixup! fixup! Move towards the self-provided Redis connection pool and RESP protocol implementation. Official redis client library won't work with yaegi. * fixup! fixup! fixup! Move towards the self-provided Redis connection pool and RESP protocol implementation. Official redis client library won't work with yaegi. * fixup! fixup! fixup! fixup! Move towards the self-provided Redis connection pool and RESP protocol implementation. Official redis client library won't work with yaegi. * fixup! fixup! fixup! fixup! fixup! Move towards the self-provided Redis connection pool and RESP protocol implementation. Official redis client library won't work with yaegi. * ... and another all nighter. * fixup! ... and another all nighter. * fixup! fixup! ... and another all nighter. * fixup! fixup! fixup! ... and another all nighter. * Resolve issue #85 by adding ability to set custom claims in JWT tokens * Remove redundant validation in auth middleware ( issue #89 ) * Add ability to set cookie prefix for session cookies ( #87 ) * fixup! Add ability to set cookie prefix for session cookies ( #87 ) * Add ability to set cookie max age - issue #91 * Potential fix for code scanning alert no. 10: Size computation for allocation may overflow Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * fixup! Merge main into 0.8.0-redis: resolve conflicts --------- Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
1374 lines
94 KiB
HTML
1374 lines
94 KiB
HTML
<!doctype html>
|
|
<html lang="en" class="scroll-smooth">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>Traefik OIDC - OpenID Connect Authentication Middleware</title>
|
|
<meta
|
|
name="description"
|
|
content="Production-ready OIDC authentication middleware for Traefik. Supports Google, Azure AD, Auth0, Okta, Keycloak, and more. Drop-in replacement for oauth2-proxy."
|
|
/>
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<script>
|
|
tailwind.config = {
|
|
darkMode: 'class'
|
|
}
|
|
</script>
|
|
<link
|
|
rel="stylesheet"
|
|
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"
|
|
/>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
<link
|
|
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap"
|
|
rel="stylesheet"
|
|
/>
|
|
<style>
|
|
body { font-family: "Inter", sans-serif; }
|
|
code, pre { font-family: "JetBrains Mono", monospace; }
|
|
.theme-transition {
|
|
transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
|
|
}
|
|
@keyframes fadeInUp {
|
|
from { opacity: 0; transform: translateY(20px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
@keyframes float {
|
|
0%, 100% { transform: translateY(0px); }
|
|
50% { transform: translateY(-10px); }
|
|
}
|
|
.animate-fade-in-up { animation: fadeInUp 0.6s ease-out; }
|
|
.animate-float { animation: float 3s ease-in-out infinite; }
|
|
.glass {
|
|
background: rgba(255, 255, 255, 0.7);
|
|
backdrop-filter: blur(10px);
|
|
-webkit-backdrop-filter: blur(10px);
|
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
}
|
|
.dark .glass {
|
|
background: rgba(17, 24, 39, 0.7);
|
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
}
|
|
.gradient-text {
|
|
background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 50%, #06b6d4 100%);
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
background-clip: text;
|
|
}
|
|
.dark .gradient-text {
|
|
background: linear-gradient(135deg, #60a5fa 0%, #a78bfa 50%, #22d3ee 100%);
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
background-clip: text;
|
|
}
|
|
.shadow-modern { box-shadow: 0 10px 40px -10px rgba(0, 0, 0, 0.1); }
|
|
.dark .shadow-modern { box-shadow: 0 10px 40px -10px rgba(0, 0, 0, 0.4); }
|
|
html { scroll-behavior: smooth; }
|
|
</style>
|
|
<script>
|
|
if (localStorage.theme === "dark" || (!("theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches)) {
|
|
document.documentElement.classList.add("dark");
|
|
} else {
|
|
document.documentElement.classList.remove("dark");
|
|
}
|
|
</script>
|
|
</head>
|
|
<body class="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 theme-transition">
|
|
<!-- Navigation -->
|
|
<nav class="fixed w-full glass shadow-modern z-50 theme-transition">
|
|
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
|
<div class="flex justify-between h-16 items-center">
|
|
<a href="#" class="flex items-center hover:opacity-80 transition-opacity duration-300 gap-2">
|
|
<i class="fas fa-shield-alt text-2xl text-blue-500"></i>
|
|
<span class="text-xl font-bold gradient-text">Traefik OIDC</span>
|
|
</a>
|
|
<div class="hidden md:flex space-x-6">
|
|
<a href="#features" class="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 font-medium">Features</a>
|
|
<a href="#providers" class="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 font-medium">Providers</a>
|
|
<a href="#installation" class="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 font-medium">Installation</a>
|
|
<a href="#configuration" class="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 font-medium">Configuration</a>
|
|
<a href="#deployment" class="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 font-medium">Deployment</a>
|
|
<a href="#security" class="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 font-medium">Security</a>
|
|
</div>
|
|
<div class="flex items-center space-x-4">
|
|
<button id="theme-toggle" class="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 p-2 min-w-[44px] min-h-[44px] flex items-center justify-center" aria-label="Toggle theme">
|
|
<i class="fas fa-moon dark:hidden text-xl"></i>
|
|
<i class="fas fa-sun hidden dark:inline text-xl"></i>
|
|
</button>
|
|
<a href="https://github.com/lukaszraczylo/traefikoidc" target="_blank" class="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 p-2 min-w-[44px] min-h-[44px] flex items-center justify-center" aria-label="View on GitHub">
|
|
<i class="fab fa-github text-xl"></i>
|
|
</a>
|
|
<button id="mobile-menu-toggle" class="md:hidden text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 p-2 min-w-[44px] min-h-[44px] flex items-center justify-center" aria-label="Toggle menu">
|
|
<i class="fas fa-bars text-xl" id="menu-open-icon"></i>
|
|
<i class="fas fa-times text-xl hidden" id="menu-close-icon"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="mobile-menu" class="hidden md:hidden border-t border-gray-200 dark:border-gray-700">
|
|
<div class="px-4 py-3 space-y-1 bg-white dark:bg-gray-800">
|
|
<a href="#features" class="block px-3 py-3 text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-50 dark:hover:bg-gray-700 rounded font-medium">Features</a>
|
|
<a href="#providers" class="block px-3 py-3 text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-50 dark:hover:bg-gray-700 rounded font-medium">Providers</a>
|
|
<a href="#installation" class="block px-3 py-3 text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-50 dark:hover:bg-gray-700 rounded font-medium">Installation</a>
|
|
<a href="#configuration" class="block px-3 py-3 text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-50 dark:hover:bg-gray-700 rounded font-medium">Configuration</a>
|
|
<a href="#deployment" class="block px-3 py-3 text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-50 dark:hover:bg-gray-700 rounded font-medium">Deployment</a>
|
|
<a href="#security" class="block px-3 py-3 text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-50 dark:hover:bg-gray-700 rounded font-medium">Security</a>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- Hero Section -->
|
|
<section class="relative pt-24 sm:pt-32 pb-12 sm:pb-20 overflow-hidden">
|
|
<div class="absolute inset-0 bg-gradient-to-br from-blue-50 via-purple-50 to-cyan-50 dark:from-gray-900 dark:via-blue-900/20 dark:to-purple-900/20 theme-transition"></div>
|
|
<div class="absolute top-0 -left-4 w-72 h-72 bg-blue-300 dark:bg-blue-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float"></div>
|
|
<div class="absolute top-0 -right-4 w-72 h-72 bg-purple-300 dark:bg-purple-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float" style="animation-delay: 1s;"></div>
|
|
<div class="absolute -bottom-8 left-20 w-72 h-72 bg-cyan-300 dark:bg-cyan-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float" style="animation-delay: 2s;"></div>
|
|
|
|
<div class="relative max-w-6xl mx-auto px-4 sm:px-6">
|
|
<div class="text-center">
|
|
<div class="mb-6 sm:mb-8 flex justify-center animate-fade-in-up">
|
|
<div class="w-24 h-24 sm:w-32 sm:h-32 rounded-2xl bg-gradient-to-br from-blue-500 via-purple-500 to-cyan-500 flex items-center justify-center shadow-xl animate-float">
|
|
<i class="fas fa-shield-alt text-white text-4xl sm:text-5xl"></i>
|
|
</div>
|
|
</div>
|
|
<h1 class="text-3xl sm:text-4xl md:text-5xl lg:text-6xl font-bold text-gray-900 dark:text-gray-100 mb-4 sm:mb-6 leading-tight animate-fade-in-up" style="animation-delay: 0.1s;">
|
|
OpenID Connect for<br /><span class="gradient-text">Traefik</span>
|
|
</h1>
|
|
<p class="text-base sm:text-lg md:text-xl text-gray-600 dark:text-gray-300 mb-8 sm:mb-10 max-w-2xl mx-auto leading-relaxed px-4 animate-fade-in-up" style="animation-delay: 0.2s;">
|
|
Production-ready OIDC authentication middleware. Drop-in replacement for oauth2-proxy and forward-auth with support for 9+ identity providers.
|
|
</p>
|
|
<div class="flex flex-col sm:flex-row gap-3 sm:gap-4 justify-center mb-8 sm:mb-12 px-4 animate-fade-in-up" style="animation-delay: 0.3s;">
|
|
<a href="#installation" class="group relative bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 text-white px-8 py-3 rounded-lg font-medium transition-all duration-300 min-h-[48px] flex items-center justify-center shadow-lg hover:shadow-xl hover:scale-105">
|
|
<span class="relative z-10">Get Started</span>
|
|
</a>
|
|
<a href="https://github.com/lukaszraczylo/traefikoidc" class="group glass hover:shadow-lg text-gray-900 dark:text-gray-100 px-8 py-3 rounded-lg font-medium transition-all duration-300 min-h-[48px] flex items-center justify-center hover:scale-105">
|
|
<i class="fab fa-github mr-2"></i>View on GitHub
|
|
</a>
|
|
</div>
|
|
<div class="flex flex-wrap justify-center gap-2 sm:gap-4 text-sm px-4 animate-fade-in-up" style="animation-delay: 0.4s;">
|
|
<img src="https://img.shields.io/github/v/release/lukaszraczylo/traefikoidc" alt="Version" class="h-5" />
|
|
<img src="https://img.shields.io/github/license/lukaszraczylo/traefikoidc" alt="License" class="h-5" />
|
|
<img src="https://goreportcard.com/badge/github.com/lukaszraczylo/traefikoidc" alt="Go Report" class="h-5" />
|
|
<img src="https://codecov.io/gh/lukaszraczylo/traefikoidc/branch/main/graph/badge.svg" alt="Coverage" class="h-5" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Features Section -->
|
|
<section id="features" class="py-12 sm:py-16 md:py-20 bg-white dark:bg-gray-900 theme-transition">
|
|
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
|
<div class="text-center mb-8 sm:mb-12">
|
|
<h2 class="text-2xl sm:text-3xl md:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-3 sm:mb-4">Features</h2>
|
|
<p class="text-base sm:text-lg text-gray-600 dark:text-gray-300 px-4">Enterprise-grade authentication for your Traefik deployments</p>
|
|
</div>
|
|
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
<div class="glass p-5 rounded-xl group hover:shadow-lg transition-all duration-300">
|
|
<div class="flex items-start gap-4">
|
|
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-blue-500 to-blue-600 flex items-center justify-center flex-shrink-0 group-hover:scale-110 transition-transform duration-300">
|
|
<i class="fas fa-globe text-white"></i>
|
|
</div>
|
|
<div>
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-1">Universal Provider Support</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400">Works with Google, Azure AD, Auth0, Okta, Keycloak, Cognito, GitLab, and any OIDC-compliant provider</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="glass p-5 rounded-xl group hover:shadow-lg transition-all duration-300">
|
|
<div class="flex items-start gap-4">
|
|
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-purple-500 to-purple-600 flex items-center justify-center flex-shrink-0 group-hover:scale-110 transition-transform duration-300">
|
|
<i class="fas fa-magic text-white"></i>
|
|
</div>
|
|
<div>
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-1">Auto-Detection</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400">Automatically detects and configures provider-specific settings from OIDC discovery</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="glass p-5 rounded-xl group hover:shadow-lg transition-all duration-300">
|
|
<div class="flex items-start gap-4">
|
|
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-cyan-500 to-cyan-600 flex items-center justify-center flex-shrink-0 group-hover:scale-110 transition-transform duration-300">
|
|
<i class="fas fa-user-plus text-white"></i>
|
|
</div>
|
|
<div>
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-1">Dynamic Registration</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400">RFC 7591 Dynamic Client Registration for automatic client setup without manual configuration</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="glass p-5 rounded-xl group hover:shadow-lg transition-all duration-300">
|
|
<div class="flex items-start gap-4">
|
|
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-emerald-500 to-emerald-600 flex items-center justify-center flex-shrink-0 group-hover:scale-110 transition-transform duration-300">
|
|
<i class="fas fa-filter text-white"></i>
|
|
</div>
|
|
<div>
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-1">Automatic Scope Filtering</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400">Intelligently filters OAuth scopes based on provider capabilities from discovery documents</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="glass p-5 rounded-xl group hover:shadow-lg transition-all duration-300">
|
|
<div class="flex items-start gap-4">
|
|
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-amber-500 to-amber-600 flex items-center justify-center flex-shrink-0 group-hover:scale-110 transition-transform duration-300">
|
|
<i class="fas fa-shield-alt text-white"></i>
|
|
</div>
|
|
<div>
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-1">Security Headers</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400">Comprehensive security headers including CORS, CSP, HSTS, and customizable profiles</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="glass p-5 rounded-xl group hover:shadow-lg transition-all duration-300">
|
|
<div class="flex items-start gap-4">
|
|
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-rose-500 to-rose-600 flex items-center justify-center flex-shrink-0 group-hover:scale-110 transition-transform duration-300">
|
|
<i class="fas fa-user-lock text-white"></i>
|
|
</div>
|
|
<div>
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-1">Domain & User Restrictions</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400">Limit access to specific email domains, individual users, or role-based groups</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="glass p-5 rounded-xl group hover:shadow-lg transition-all duration-300">
|
|
<div class="flex items-start gap-4">
|
|
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-indigo-500 to-indigo-600 flex items-center justify-center flex-shrink-0 group-hover:scale-110 transition-transform duration-300">
|
|
<i class="fas fa-users-cog text-white"></i>
|
|
</div>
|
|
<div>
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-1">Role-Based Access</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400">Restrict access based on roles and groups from OIDC claims</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="glass p-5 rounded-xl group hover:shadow-lg transition-all duration-300">
|
|
<div class="flex items-start gap-4">
|
|
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-teal-500 to-teal-600 flex items-center justify-center flex-shrink-0 group-hover:scale-110 transition-transform duration-300">
|
|
<i class="fas fa-sync-alt text-white"></i>
|
|
</div>
|
|
<div>
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-1">Automatic Token Refresh</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400">Secure session handling with proactive token refresh before expiry</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="glass p-5 rounded-xl group hover:shadow-lg transition-all duration-300">
|
|
<div class="flex items-start gap-4">
|
|
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-pink-500 to-pink-600 flex items-center justify-center flex-shrink-0 group-hover:scale-110 transition-transform duration-300">
|
|
<i class="fas fa-tachometer-alt text-white"></i>
|
|
</div>
|
|
<div>
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-1">Rate Limiting</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400">Built-in protection against brute force attacks with configurable limits</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="glass p-5 rounded-xl group hover:shadow-lg transition-all duration-300">
|
|
<div class="flex items-start gap-4">
|
|
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-orange-500 to-orange-600 flex items-center justify-center flex-shrink-0 group-hover:scale-110 transition-transform duration-300">
|
|
<i class="fas fa-code text-white"></i>
|
|
</div>
|
|
<div>
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-1">Custom Headers</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400">Template-based headers using OIDC claims and tokens for downstream services</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="glass p-5 rounded-xl group hover:shadow-lg transition-all duration-300">
|
|
<div class="flex items-start gap-4">
|
|
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-slate-500 to-slate-600 flex items-center justify-center flex-shrink-0 group-hover:scale-110 transition-transform duration-300">
|
|
<i class="fas fa-key text-white"></i>
|
|
</div>
|
|
<div>
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-1">PKCE Support</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400">Proof Key for Code Exchange for enhanced security in authorization code flow</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="glass p-5 rounded-xl group hover:shadow-lg transition-all duration-300">
|
|
<div class="flex items-start gap-4">
|
|
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-violet-500 to-violet-600 flex items-center justify-center flex-shrink-0 group-hover:scale-110 transition-transform duration-300">
|
|
<i class="fas fa-memory text-white"></i>
|
|
</div>
|
|
<div>
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-1">Memory Management</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400">Bounded caches with LRU eviction, automatic cleanup, and zero goroutine leaks</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="glass p-5 rounded-xl group hover:shadow-lg transition-all duration-300">
|
|
<div class="flex items-start gap-4">
|
|
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-red-500 to-red-600 flex items-center justify-center flex-shrink-0 group-hover:scale-110 transition-transform duration-300">
|
|
<i class="fas fa-database text-white"></i>
|
|
</div>
|
|
<div>
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-1">Redis Cache</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400">Distributed caching with Redis for multi-replica deployments with circuit breaker and health checks</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="glass p-5 rounded-xl group hover:shadow-lg transition-all duration-300">
|
|
<div class="flex items-start gap-4">
|
|
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-lime-500 to-lime-600 flex items-center justify-center flex-shrink-0 group-hover:scale-110 transition-transform duration-300">
|
|
<i class="fas fa-search text-white"></i>
|
|
</div>
|
|
<div>
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-1">Token Introspection</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400">RFC 7662 Token Introspection support for opaque access tokens and enhanced validation</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Providers Section -->
|
|
<section id="providers" class="py-12 sm:py-16 md:py-20 bg-gray-50 dark:bg-gray-800 theme-transition">
|
|
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
|
<div class="text-center mb-8 sm:mb-12">
|
|
<h2 class="text-2xl sm:text-3xl md:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-3 sm:mb-4">Supported Providers</h2>
|
|
<p class="text-base sm:text-lg text-gray-600 dark:text-gray-300 px-4">Works with all major identity providers out of the box</p>
|
|
</div>
|
|
|
|
<!-- Provider Grid -->
|
|
<div class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4 mb-8">
|
|
<div class="glass p-4 rounded-xl text-center group hover:shadow-lg transition-all duration-300">
|
|
<div class="w-12 h-12 mx-auto mb-3 rounded-xl bg-gradient-to-br from-red-500 to-yellow-500 flex items-center justify-center group-hover:scale-110 transition-transform duration-300">
|
|
<i class="fab fa-google text-white text-xl"></i>
|
|
</div>
|
|
<h4 class="font-semibold text-gray-900 dark:text-gray-100 text-sm">Google</h4>
|
|
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">Full OIDC</p>
|
|
</div>
|
|
<div class="glass p-4 rounded-xl text-center group hover:shadow-lg transition-all duration-300">
|
|
<div class="w-12 h-12 mx-auto mb-3 rounded-xl bg-gradient-to-br from-blue-500 to-blue-600 flex items-center justify-center group-hover:scale-110 transition-transform duration-300">
|
|
<i class="fab fa-microsoft text-white text-xl"></i>
|
|
</div>
|
|
<h4 class="font-semibold text-gray-900 dark:text-gray-100 text-sm">Azure AD</h4>
|
|
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">Full OIDC</p>
|
|
</div>
|
|
<div class="glass p-4 rounded-xl text-center group hover:shadow-lg transition-all duration-300">
|
|
<div class="w-12 h-12 mx-auto mb-3 rounded-xl bg-gradient-to-br from-orange-500 to-orange-600 flex items-center justify-center group-hover:scale-110 transition-transform duration-300">
|
|
<span class="text-white font-bold text-sm">A0</span>
|
|
</div>
|
|
<h4 class="font-semibold text-gray-900 dark:text-gray-100 text-sm">Auth0</h4>
|
|
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">Full OIDC</p>
|
|
</div>
|
|
<div class="glass p-4 rounded-xl text-center group hover:shadow-lg transition-all duration-300">
|
|
<div class="w-12 h-12 mx-auto mb-3 rounded-xl bg-gradient-to-br from-indigo-500 to-indigo-600 flex items-center justify-center group-hover:scale-110 transition-transform duration-300">
|
|
<span class="text-white font-bold text-sm">OK</span>
|
|
</div>
|
|
<h4 class="font-semibold text-gray-900 dark:text-gray-100 text-sm">Okta</h4>
|
|
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">Full OIDC</p>
|
|
</div>
|
|
<div class="glass p-4 rounded-xl text-center group hover:shadow-lg transition-all duration-300">
|
|
<div class="w-12 h-12 mx-auto mb-3 rounded-xl bg-gradient-to-br from-red-600 to-red-700 flex items-center justify-center group-hover:scale-110 transition-transform duration-300">
|
|
<span class="text-white font-bold text-sm">KC</span>
|
|
</div>
|
|
<h4 class="font-semibold text-gray-900 dark:text-gray-100 text-sm">Keycloak</h4>
|
|
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">Full OIDC</p>
|
|
</div>
|
|
<div class="glass p-4 rounded-xl text-center group hover:shadow-lg transition-all duration-300">
|
|
<div class="w-12 h-12 mx-auto mb-3 rounded-xl bg-gradient-to-br from-amber-500 to-amber-600 flex items-center justify-center group-hover:scale-110 transition-transform duration-300">
|
|
<i class="fab fa-aws text-white text-xl"></i>
|
|
</div>
|
|
<h4 class="font-semibold text-gray-900 dark:text-gray-100 text-sm">AWS Cognito</h4>
|
|
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">Full OIDC</p>
|
|
</div>
|
|
<div class="glass p-4 rounded-xl text-center group hover:shadow-lg transition-all duration-300">
|
|
<div class="w-12 h-12 mx-auto mb-3 rounded-xl bg-gradient-to-br from-orange-600 to-orange-700 flex items-center justify-center group-hover:scale-110 transition-transform duration-300">
|
|
<i class="fab fa-gitlab text-white text-xl"></i>
|
|
</div>
|
|
<h4 class="font-semibold text-gray-900 dark:text-gray-100 text-sm">GitLab</h4>
|
|
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">Full OIDC</p>
|
|
</div>
|
|
<div class="glass p-4 rounded-xl text-center group hover:shadow-lg transition-all duration-300">
|
|
<div class="w-12 h-12 mx-auto mb-3 rounded-xl bg-gradient-to-br from-gray-700 to-gray-800 flex items-center justify-center group-hover:scale-110 transition-transform duration-300">
|
|
<i class="fab fa-github text-white text-xl"></i>
|
|
</div>
|
|
<h4 class="font-semibold text-gray-900 dark:text-gray-100 text-sm">GitHub</h4>
|
|
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">OAuth 2.0</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Comparison Table -->
|
|
<div class="glass rounded-xl overflow-hidden shadow-modern">
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full text-sm">
|
|
<thead class="bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
|
<tr>
|
|
<th class="px-4 py-3 text-left font-semibold">Feature</th>
|
|
<th class="px-4 py-3 text-center font-semibold">Google</th>
|
|
<th class="px-4 py-3 text-center font-semibold">Azure AD</th>
|
|
<th class="px-4 py-3 text-center font-semibold">Auth0</th>
|
|
<th class="px-4 py-3 text-center font-semibold">Okta</th>
|
|
<th class="px-4 py-3 text-center font-semibold">Keycloak</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
|
|
<tr class="hover:bg-gray-50 dark:hover:bg-gray-800/50">
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300 font-medium">ID Tokens</td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
</tr>
|
|
<tr class="hover:bg-gray-50 dark:hover:bg-gray-800/50">
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300 font-medium">Refresh Tokens</td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
</tr>
|
|
<tr class="hover:bg-gray-50 dark:hover:bg-gray-800/50">
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300 font-medium">Auto-Configuration</td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
</tr>
|
|
<tr class="hover:bg-gray-50 dark:hover:bg-gray-800/50">
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300 font-medium">Custom Claims</td>
|
|
<td class="px-4 py-3 text-center text-gray-400">Limited</td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
</tr>
|
|
<tr class="hover:bg-gray-50 dark:hover:bg-gray-800/50">
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300 font-medium">Group/Role Claims</td>
|
|
<td class="px-4 py-3 text-center text-gray-400">Limited</td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
</tr>
|
|
<tr class="hover:bg-gray-50 dark:hover:bg-gray-800/50">
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300 font-medium">Self-Hosted</td>
|
|
<td class="px-4 py-3 text-center"><span class="text-red-500">✗</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-red-500">✗</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-red-500">✗</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-red-500">✗</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Installation Section -->
|
|
<section id="installation" class="py-12 sm:py-16 md:py-20 bg-white dark:bg-gray-900 theme-transition">
|
|
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
|
<div class="text-center mb-8 sm:mb-12">
|
|
<h2 class="text-2xl sm:text-3xl md:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-3 sm:mb-4">Installation</h2>
|
|
<p class="text-base sm:text-lg text-gray-600 dark:text-gray-300 px-4">Get started in under 5 minutes</p>
|
|
</div>
|
|
|
|
<!-- Tab Switcher -->
|
|
<div class="max-w-3xl mx-auto mb-6">
|
|
<div class="flex justify-center">
|
|
<div class="glass inline-flex rounded-lg p-1">
|
|
<button class="platform-tab px-6 py-2 rounded-md text-sm font-medium transition-all duration-200 bg-gradient-to-r from-blue-600 to-purple-600 text-white shadow-md" data-platform="docker">
|
|
<i class="fab fa-docker mr-2"></i>Docker Compose
|
|
</button>
|
|
<button class="platform-tab px-6 py-2 rounded-md text-sm font-medium transition-all duration-200 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700" data-platform="kubernetes">
|
|
<i class="fas fa-dharmachakra mr-2"></i>Kubernetes
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="max-w-3xl mx-auto space-y-6">
|
|
<div class="glass p-6 rounded-xl">
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-3 flex items-center">
|
|
<span class="w-8 h-8 rounded-full bg-blue-500 text-white flex items-center justify-center text-sm font-bold mr-3">1</span>
|
|
Enable the Plugin
|
|
</h3>
|
|
<p class="text-gray-600 dark:text-gray-400 mb-3 text-sm platform-desc-docker">Add to your Traefik static configuration or Docker Compose command:</p>
|
|
<p class="text-gray-600 dark:text-gray-400 mb-3 text-sm platform-desc-kubernetes hidden">Add to your Traefik Helm values or static configuration:</p>
|
|
|
|
<!-- Docker -->
|
|
<pre class="platform-example-docker bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm"><code># docker-compose.yml - Traefik service command
|
|
command:
|
|
- "--experimental.plugins.traefikoidc.modulename=github.com/lukaszraczylo/traefikoidc"
|
|
- "--experimental.plugins.traefikoidc.version=v0.7.10"
|
|
|
|
# Or in traefik.yml static config
|
|
experimental:
|
|
plugins:
|
|
traefikoidc:
|
|
moduleName: github.com/lukaszraczylo/traefikoidc
|
|
version: v0.7.10</code></pre>
|
|
|
|
<!-- Kubernetes -->
|
|
<pre class="platform-example-kubernetes hidden bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm"><code># Helm values.yaml for Traefik
|
|
experimental:
|
|
plugins:
|
|
traefikoidc:
|
|
moduleName: github.com/lukaszraczylo/traefikoidc
|
|
version: v0.7.10
|
|
|
|
# Or apply via additionalArguments
|
|
additionalArguments:
|
|
- "--experimental.plugins.traefikoidc.modulename=github.com/lukaszraczylo/traefikoidc"
|
|
- "--experimental.plugins.traefikoidc.version=v0.7.10"</code></pre>
|
|
</div>
|
|
<div class="glass p-6 rounded-xl">
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-3 flex items-center">
|
|
<span class="w-8 h-8 rounded-full bg-blue-500 text-white flex items-center justify-center text-sm font-bold mr-3">2</span>
|
|
Configure the Middleware
|
|
</h3>
|
|
<p class="text-gray-600 dark:text-gray-400 mb-3 text-sm platform-desc-docker">Add middleware configuration via Docker labels:</p>
|
|
<p class="text-gray-600 dark:text-gray-400 mb-3 text-sm platform-desc-kubernetes hidden">Create a Middleware custom resource:</p>
|
|
|
|
<!-- Docker -->
|
|
<pre class="platform-example-docker bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm"><code># docker-compose.yml - Service labels
|
|
labels:
|
|
- "traefik.http.middlewares.oidc-auth.plugin.traefikoidc.providerURL=https://accounts.google.com"
|
|
- "traefik.http.middlewares.oidc-auth.plugin.traefikoidc.clientID=your-client-id"
|
|
- "traefik.http.middlewares.oidc-auth.plugin.traefikoidc.clientSecret=your-client-secret"
|
|
- "traefik.http.middlewares.oidc-auth.plugin.traefikoidc.callbackURL=/oauth2/callback"
|
|
- "traefik.http.middlewares.oidc-auth.plugin.traefikoidc.sessionEncryptionKey=your-32-byte-secret-key-here!!"</code></pre>
|
|
|
|
<!-- Kubernetes -->
|
|
<pre class="platform-example-kubernetes hidden bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm"><code># middleware.yaml
|
|
apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: oidc-auth
|
|
namespace: traefik
|
|
spec:
|
|
plugin:
|
|
traefikoidc:
|
|
providerURL: https://accounts.google.com
|
|
clientID: your-client-id
|
|
clientSecret: your-client-secret
|
|
callbackURL: /oauth2/callback
|
|
sessionEncryptionKey: your-32-byte-secret-key-here!!</code></pre>
|
|
</div>
|
|
<div class="glass p-6 rounded-xl">
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-3 flex items-center">
|
|
<span class="w-8 h-8 rounded-full bg-blue-500 text-white flex items-center justify-center text-sm font-bold mr-3">3</span>
|
|
Apply to Your Routes
|
|
</h3>
|
|
<p class="text-gray-600 dark:text-gray-400 mb-3 text-sm platform-desc-docker">Use the middleware on your services via labels:</p>
|
|
<p class="text-gray-600 dark:text-gray-400 mb-3 text-sm platform-desc-kubernetes hidden">Reference the middleware in your IngressRoute:</p>
|
|
|
|
<!-- Docker -->
|
|
<pre class="platform-example-docker bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm"><code># docker-compose.yml - Protected service
|
|
services:
|
|
my-app:
|
|
image: my-app:latest
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.my-app.rule=Host(`app.example.com`)"
|
|
- "traefik.http.routers.my-app.middlewares=oidc-auth"
|
|
- "traefik.http.routers.my-app.tls=true"
|
|
- "traefik.http.routers.my-app.tls.certresolver=letsencrypt"</code></pre>
|
|
|
|
<!-- Kubernetes -->
|
|
<pre class="platform-example-kubernetes hidden bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm"><code># ingressroute.yaml
|
|
apiVersion: traefik.io/v1alpha1
|
|
kind: IngressRoute
|
|
metadata:
|
|
name: my-app
|
|
namespace: default
|
|
spec:
|
|
entryPoints:
|
|
- websecure
|
|
routes:
|
|
- match: Host(`app.example.com`)
|
|
kind: Rule
|
|
middlewares:
|
|
- name: oidc-auth
|
|
namespace: traefik
|
|
services:
|
|
- name: my-app
|
|
port: 80
|
|
tls:
|
|
certResolver: letsencrypt</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Configuration Section -->
|
|
<section id="configuration" class="py-12 sm:py-16 md:py-20 bg-gray-50 dark:bg-gray-800 theme-transition">
|
|
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
|
<div class="text-center mb-8 sm:mb-12">
|
|
<h2 class="text-2xl sm:text-3xl md:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-3 sm:mb-4">Configuration</h2>
|
|
<p class="text-base sm:text-lg text-gray-600 dark:text-gray-300 px-4">Flexible options for any deployment scenario</p>
|
|
</div>
|
|
|
|
<!-- Tab Switcher -->
|
|
<div class="max-w-4xl mx-auto mb-6">
|
|
<div class="flex justify-center">
|
|
<div class="glass inline-flex rounded-lg p-1">
|
|
<button class="platform-tab px-6 py-2 rounded-md text-sm font-medium transition-all duration-200 bg-gradient-to-r from-blue-600 to-purple-600 text-white shadow-md" data-platform="docker">
|
|
<i class="fab fa-docker mr-2"></i>Docker Compose
|
|
</button>
|
|
<button class="platform-tab px-6 py-2 rounded-md text-sm font-medium transition-all duration-200 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700" data-platform="kubernetes">
|
|
<i class="fas fa-dharmachakra mr-2"></i>Kubernetes
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="max-w-4xl mx-auto space-y-6">
|
|
<div class="glass p-6 rounded-xl">
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-4">Required Parameters</h3>
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full text-sm">
|
|
<thead>
|
|
<tr class="border-b border-gray-200 dark:border-gray-700">
|
|
<th class="text-left py-2 px-3 text-gray-900 dark:text-gray-100">Parameter</th>
|
|
<th class="text-left py-2 px-3 text-gray-900 dark:text-gray-100">Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="text-gray-600 dark:text-gray-400">
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">providerURL</code></td>
|
|
<td class="py-2 px-3">Base URL of your OIDC provider</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">clientID</code></td>
|
|
<td class="py-2 px-3">OAuth 2.0 client identifier</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">clientSecret</code></td>
|
|
<td class="py-2 px-3">OAuth 2.0 client secret</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">sessionEncryptionKey</code></td>
|
|
<td class="py-2 px-3">32+ byte key for session encryption</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">callbackURL</code></td>
|
|
<td class="py-2 px-3">OAuth callback path (e.g., /oauth2/callback)</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="glass p-6 rounded-xl">
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-4">Popular Optional Parameters</h3>
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full text-sm">
|
|
<thead>
|
|
<tr class="border-b border-gray-200 dark:border-gray-700">
|
|
<th class="text-left py-2 px-3 text-gray-900 dark:text-gray-100">Parameter</th>
|
|
<th class="text-left py-2 px-3 text-gray-900 dark:text-gray-100">Default</th>
|
|
<th class="text-left py-2 px-3 text-gray-900 dark:text-gray-100">Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="text-gray-600 dark:text-gray-400">
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">forceHTTPS</code></td>
|
|
<td class="py-2 px-3">false</td>
|
|
<td class="py-2 px-3">Required for TLS termination at load balancer (AWS ALB, etc.)</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">allowedUserDomains</code></td>
|
|
<td class="py-2 px-3">none</td>
|
|
<td class="py-2 px-3">Restrict to specific email domains</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">allowedUsers</code></td>
|
|
<td class="py-2 px-3">none</td>
|
|
<td class="py-2 px-3">Specific email addresses allowed access</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">allowedRolesAndGroups</code></td>
|
|
<td class="py-2 px-3">none</td>
|
|
<td class="py-2 px-3">Restrict to users with specific roles or groups</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">roleClaimName</code></td>
|
|
<td class="py-2 px-3">"roles"</td>
|
|
<td class="py-2 px-3">JWT claim for roles (supports namespaced claims like <code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">https://myapp.com/roles</code>)</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">groupClaimName</code></td>
|
|
<td class="py-2 px-3">"groups"</td>
|
|
<td class="py-2 px-3">JWT claim for groups (supports namespaced claims)</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">excludedURLs</code></td>
|
|
<td class="py-2 px-3">none</td>
|
|
<td class="py-2 px-3">Paths that bypass authentication</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">enablePKCE</code></td>
|
|
<td class="py-2 px-3">false</td>
|
|
<td class="py-2 px-3">Enable PKCE for enhanced security</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">rateLimit</code></td>
|
|
<td class="py-2 px-3">100</td>
|
|
<td class="py-2 px-3">Maximum requests per second</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">sessionMaxAge</code></td>
|
|
<td class="py-2 px-3">86400</td>
|
|
<td class="py-2 px-3">Maximum session age in seconds (24 hours default)</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">cookiePrefix</code></td>
|
|
<td class="py-2 px-3">_oidc_raczylo_</td>
|
|
<td class="py-2 px-3">Custom prefix for session cookies</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">cookieDomain</code></td>
|
|
<td class="py-2 px-3">auto-detected</td>
|
|
<td class="py-2 px-3">Explicit domain for session cookies (multi-subdomain)</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">audience</code></td>
|
|
<td class="py-2 px-3">clientID</td>
|
|
<td class="py-2 px-3">Custom audience for access token validation</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">strictAudienceValidation</code></td>
|
|
<td class="py-2 px-3">false</td>
|
|
<td class="py-2 px-3">Reject sessions with audience mismatch</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">allowOpaqueTokens</code></td>
|
|
<td class="py-2 px-3">false</td>
|
|
<td class="py-2 px-3">Enable opaque (non-JWT) access token support</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">requireTokenIntrospection</code></td>
|
|
<td class="py-2 px-3">false</td>
|
|
<td class="py-2 px-3">Require RFC 7662 introspection for opaque tokens</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">disableReplayDetection</code></td>
|
|
<td class="py-2 px-3">false</td>
|
|
<td class="py-2 px-3">Disable JTI replay detection (for multi-replica without Redis)</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="glass p-6 rounded-xl">
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-3">Example: Google Workspace with Domain Restriction</h3>
|
|
|
|
<!-- Docker -->
|
|
<pre class="platform-example-docker bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm"><code># docker-compose.yml labels
|
|
labels:
|
|
- "traefik.http.middlewares.google-oidc.plugin.traefikoidc.providerURL=https://accounts.google.com"
|
|
- "traefik.http.middlewares.google-oidc.plugin.traefikoidc.clientID=1234567890.apps.googleusercontent.com"
|
|
- "traefik.http.middlewares.google-oidc.plugin.traefikoidc.clientSecret=your-client-secret"
|
|
- "traefik.http.middlewares.google-oidc.plugin.traefikoidc.callbackURL=/oauth2/callback"
|
|
- "traefik.http.middlewares.google-oidc.plugin.traefikoidc.sessionEncryptionKey=your-32-byte-encryption-key!!"
|
|
- "traefik.http.middlewares.google-oidc.plugin.traefikoidc.allowedUserDomains=yourcompany.com,subsidiary.com"
|
|
- "traefik.http.middlewares.google-oidc.plugin.traefikoidc.excludedURLs=/health,/metrics,/api/public"
|
|
- "traefik.http.middlewares.google-oidc.plugin.traefikoidc.forceHTTPS=true"
|
|
- "traefik.http.middlewares.google-oidc.plugin.traefikoidc.logLevel=info"</code></pre>
|
|
|
|
<!-- Kubernetes -->
|
|
<pre class="platform-example-kubernetes hidden bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm"><code>apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: google-oidc
|
|
namespace: traefik
|
|
spec:
|
|
plugin:
|
|
traefikoidc:
|
|
providerURL: https://accounts.google.com
|
|
clientID: 1234567890.apps.googleusercontent.com
|
|
clientSecret: your-client-secret
|
|
callbackURL: /oauth2/callback
|
|
sessionEncryptionKey: your-32-byte-encryption-key!!
|
|
allowedUserDomains:
|
|
- yourcompany.com
|
|
- subsidiary.com
|
|
excludedURLs:
|
|
- /health
|
|
- /metrics
|
|
- /api/public
|
|
forceHTTPS: true
|
|
logLevel: info</code></pre>
|
|
</div>
|
|
<div class="glass p-6 rounded-xl">
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-4">Redis Cache Configuration</h3>
|
|
<p class="text-gray-600 dark:text-gray-400 mb-3 text-sm">For multi-replica deployments, use Redis for distributed session and JTI replay detection:</p>
|
|
<div class="overflow-x-auto mb-4">
|
|
<table class="w-full text-sm">
|
|
<thead>
|
|
<tr class="border-b border-gray-200 dark:border-gray-700">
|
|
<th class="text-left py-2 px-3 text-gray-900 dark:text-gray-100">Parameter</th>
|
|
<th class="text-left py-2 px-3 text-gray-900 dark:text-gray-100">Default</th>
|
|
<th class="text-left py-2 px-3 text-gray-900 dark:text-gray-100">Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="text-gray-600 dark:text-gray-400">
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">redis.enabled</code></td>
|
|
<td class="py-2 px-3">false</td>
|
|
<td class="py-2 px-3">Enable Redis caching</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">redis.address</code></td>
|
|
<td class="py-2 px-3">-</td>
|
|
<td class="py-2 px-3">Redis server address (host:port)</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">redis.password</code></td>
|
|
<td class="py-2 px-3">-</td>
|
|
<td class="py-2 px-3">Redis password</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">redis.db</code></td>
|
|
<td class="py-2 px-3">0</td>
|
|
<td class="py-2 px-3">Redis database number</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">redis.keyPrefix</code></td>
|
|
<td class="py-2 px-3">traefikoidc:</td>
|
|
<td class="py-2 px-3">Key prefix for namespacing</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">redis.cacheMode</code></td>
|
|
<td class="py-2 px-3">redis</td>
|
|
<td class="py-2 px-3">Cache mode: <code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">memory</code>, <code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">redis</code>, or <code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">hybrid</code></td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">redis.poolSize</code></td>
|
|
<td class="py-2 px-3">10</td>
|
|
<td class="py-2 px-3">Connection pool size</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">redis.enableCircuitBreaker</code></td>
|
|
<td class="py-2 px-3">true</td>
|
|
<td class="py-2 px-3">Enable circuit breaker for Redis failures</td>
|
|
</tr>
|
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">redis.enableHealthCheck</code></td>
|
|
<td class="py-2 px-3">true</td>
|
|
<td class="py-2 px-3">Enable periodic health checks</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="py-2 px-3"><code class="bg-gray-200 dark:bg-gray-700 px-1 rounded">redis.enableTLS</code></td>
|
|
<td class="py-2 px-3">false</td>
|
|
<td class="py-2 px-3">Enable TLS for Redis connections</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="glass p-6 rounded-xl">
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-3">Example: Security Headers with CORS</h3>
|
|
|
|
<!-- Docker -->
|
|
<pre class="platform-example-docker bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm"><code># docker-compose.yml labels
|
|
labels:
|
|
- "traefik.http.middlewares.oidc-secure.plugin.traefikoidc.providerURL=https://accounts.google.com"
|
|
- "traefik.http.middlewares.oidc-secure.plugin.traefikoidc.clientID=your-client-id"
|
|
- "traefik.http.middlewares.oidc-secure.plugin.traefikoidc.clientSecret=your-client-secret"
|
|
- "traefik.http.middlewares.oidc-secure.plugin.traefikoidc.callbackURL=/oauth2/callback"
|
|
- "traefik.http.middlewares.oidc-secure.plugin.traefikoidc.sessionEncryptionKey=your-32-byte-encryption-key!!"
|
|
- "traefik.http.middlewares.oidc-secure.plugin.traefikoidc.securityHeaders.enabled=true"
|
|
- "traefik.http.middlewares.oidc-secure.plugin.traefikoidc.securityHeaders.profile=api"
|
|
- "traefik.http.middlewares.oidc-secure.plugin.traefikoidc.securityHeaders.corsEnabled=true"
|
|
- "traefik.http.middlewares.oidc-secure.plugin.traefikoidc.securityHeaders.corsAllowCredentials=true"
|
|
- "traefik.http.middlewares.oidc-secure.plugin.traefikoidc.securityHeaders.strictTransportSecurity=true"</code></pre>
|
|
|
|
<!-- Kubernetes -->
|
|
<pre class="platform-example-kubernetes hidden bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm"><code>apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: oidc-secure
|
|
namespace: traefik
|
|
spec:
|
|
plugin:
|
|
traefikoidc:
|
|
providerURL: https://accounts.google.com
|
|
clientID: your-client-id
|
|
clientSecret: your-client-secret
|
|
callbackURL: /oauth2/callback
|
|
sessionEncryptionKey: your-32-byte-encryption-key!!
|
|
securityHeaders:
|
|
enabled: true
|
|
profile: api
|
|
corsEnabled: true
|
|
corsAllowedOrigins:
|
|
- https://app.example.com
|
|
- https://*.example.com
|
|
corsAllowedMethods:
|
|
- GET
|
|
- POST
|
|
- PUT
|
|
- DELETE
|
|
corsAllowCredentials: true
|
|
strictTransportSecurity: true
|
|
strictTransportSecurityMaxAge: 31536000</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Deployment Section -->
|
|
<section id="deployment" class="py-12 sm:py-16 md:py-20 bg-white dark:bg-gray-900 theme-transition">
|
|
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
|
<div class="text-center mb-8 sm:mb-12">
|
|
<h2 class="text-2xl sm:text-3xl md:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-3 sm:mb-4">Deployment Examples</h2>
|
|
<p class="text-base sm:text-lg text-gray-600 dark:text-gray-300 px-4">Production-ready configurations for Docker Compose and Kubernetes</p>
|
|
</div>
|
|
|
|
<!-- Tab Switcher -->
|
|
<div class="max-w-4xl mx-auto mb-6">
|
|
<div class="flex justify-center">
|
|
<div class="glass inline-flex rounded-lg p-1">
|
|
<button id="tab-docker" class="deployment-tab px-6 py-2 rounded-md text-sm font-medium transition-all duration-200 bg-gradient-to-r from-blue-600 to-purple-600 text-white shadow-md" data-platform="docker">
|
|
<i class="fab fa-docker mr-2"></i>Docker Compose
|
|
</button>
|
|
<button id="tab-kubernetes" class="deployment-tab px-6 py-2 rounded-md text-sm font-medium transition-all duration-200 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700" data-platform="kubernetes">
|
|
<i class="fas fa-dharmachakra mr-2"></i>Kubernetes
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="max-w-4xl mx-auto space-y-6">
|
|
<!-- Basic Setup -->
|
|
<div class="glass p-6 rounded-xl">
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-3 flex items-center">
|
|
<span class="deployment-icon-docker"><i class="fab fa-docker mr-2 text-blue-500"></i></span>
|
|
<span class="deployment-icon-kubernetes hidden"><i class="fas fa-dharmachakra mr-2 text-blue-500"></i></span>
|
|
Basic Setup
|
|
</h3>
|
|
<p class="text-gray-600 dark:text-gray-400 mb-3 text-sm deployment-desc-docker">Complete Docker Compose setup with Traefik OIDC middleware:</p>
|
|
<p class="text-gray-600 dark:text-gray-400 mb-3 text-sm deployment-desc-kubernetes hidden">Kubernetes Middleware resource using Traefik's Custom Resource Definitions:</p>
|
|
|
|
<!-- Docker Compose Basic -->
|
|
<pre class="deployment-example-docker bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm"><code>version: "3.8"
|
|
|
|
services:
|
|
traefik:
|
|
image: traefik:v3.2
|
|
command:
|
|
- "--api.insecure=true"
|
|
- "--providers.docker=true"
|
|
- "--providers.docker.exposedbydefault=false"
|
|
- "--entrypoints.web.address=:80"
|
|
- "--experimental.plugins.traefikoidc.modulename=github.com/lukaszraczylo/traefikoidc"
|
|
- "--experimental.plugins.traefikoidc.version=v0.7.10"
|
|
ports:
|
|
- "80:80"
|
|
- "8080:8080"
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
networks:
|
|
- web
|
|
|
|
whoami:
|
|
image: traefik/whoami
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.whoami.rule=Host(`app.localhost`)"
|
|
- "traefik.http.routers.whoami.entrypoints=web"
|
|
- "traefik.http.routers.whoami.middlewares=oidc-auth"
|
|
# OIDC Middleware Configuration
|
|
- "traefik.http.middlewares.oidc-auth.plugin.traefikoidc.providerURL=https://accounts.google.com"
|
|
- "traefik.http.middlewares.oidc-auth.plugin.traefikoidc.clientID=YOUR_CLIENT_ID"
|
|
- "traefik.http.middlewares.oidc-auth.plugin.traefikoidc.clientSecret=YOUR_CLIENT_SECRET"
|
|
- "traefik.http.middlewares.oidc-auth.plugin.traefikoidc.callbackURL=/oauth2/callback"
|
|
- "traefik.http.middlewares.oidc-auth.plugin.traefikoidc.sessionEncryptionKey=your-32-byte-encryption-key!!"
|
|
- "traefik.http.middlewares.oidc-auth.plugin.traefikoidc.forceHTTPS=false"
|
|
networks:
|
|
- web
|
|
|
|
networks:
|
|
web:
|
|
external: true</code></pre>
|
|
|
|
<!-- Kubernetes Basic -->
|
|
<pre class="deployment-example-kubernetes hidden bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm"><code>apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: oidc-auth
|
|
namespace: traefik
|
|
spec:
|
|
plugin:
|
|
traefikoidc:
|
|
providerURL: https://accounts.google.com
|
|
clientID: your-client-id
|
|
clientSecret: your-client-secret
|
|
sessionEncryptionKey: your-secure-encryption-key-min-32-chars
|
|
callbackURL: /oauth2/callback
|
|
logoutURL: /oauth2/logout
|
|
forceHTTPS: true
|
|
allowedUserDomains:
|
|
- yourcompany.com
|
|
excludedURLs:
|
|
- /health
|
|
- /metrics
|
|
scopes:
|
|
- roles
|
|
securityHeaders:
|
|
enabled: true
|
|
profile: "default"
|
|
---
|
|
apiVersion: traefik.io/v1alpha1
|
|
kind: IngressRoute
|
|
metadata:
|
|
name: my-app
|
|
namespace: default
|
|
spec:
|
|
entryPoints:
|
|
- websecure
|
|
routes:
|
|
- match: Host(`app.example.com`)
|
|
kind: Rule
|
|
middlewares:
|
|
- name: oidc-auth
|
|
namespace: traefik
|
|
services:
|
|
- name: my-service
|
|
port: 80
|
|
tls:
|
|
certResolver: letsencrypt</code></pre>
|
|
</div>
|
|
|
|
<!-- With Redis Cache -->
|
|
<div class="glass p-6 rounded-xl">
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-3 flex items-center">
|
|
<span class="deployment-icon-docker"><i class="fab fa-docker mr-2 text-blue-500"></i></span>
|
|
<span class="deployment-icon-kubernetes hidden"><i class="fas fa-dharmachakra mr-2 text-blue-500"></i></span>
|
|
With Redis Cache (Multi-Replica)
|
|
</h3>
|
|
<p class="text-gray-600 dark:text-gray-400 mb-3 text-sm deployment-desc-docker">Multi-replica deployment with Redis for distributed session management:</p>
|
|
<p class="text-gray-600 dark:text-gray-400 mb-3 text-sm deployment-desc-kubernetes hidden">Production-ready Kubernetes deployment with Redis for high availability:</p>
|
|
|
|
<!-- Docker Compose with Redis -->
|
|
<pre class="deployment-example-docker bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm"><code>version: "3.8"
|
|
|
|
services:
|
|
redis:
|
|
image: redis:alpine
|
|
command: redis-server --requirepass yourpassword
|
|
networks:
|
|
- web
|
|
|
|
traefik:
|
|
image: traefik:v3.2
|
|
deploy:
|
|
replicas: 3
|
|
labels:
|
|
# OIDC Middleware with Redis
|
|
- "traefik.http.middlewares.oidc.plugin.traefikoidc.providerURL=https://accounts.google.com"
|
|
- "traefik.http.middlewares.oidc.plugin.traefikoidc.clientID=YOUR_CLIENT_ID"
|
|
- "traefik.http.middlewares.oidc.plugin.traefikoidc.clientSecret=YOUR_CLIENT_SECRET"
|
|
- "traefik.http.middlewares.oidc.plugin.traefikoidc.callbackURL=/oauth2/callback"
|
|
- "traefik.http.middlewares.oidc.plugin.traefikoidc.sessionEncryptionKey=your-64-char-key"
|
|
# Redis Configuration
|
|
- "traefik.http.middlewares.oidc.plugin.traefikoidc.redis.enabled=true"
|
|
- "traefik.http.middlewares.oidc.plugin.traefikoidc.redis.address=redis:6379"
|
|
- "traefik.http.middlewares.oidc.plugin.traefikoidc.redis.password=yourpassword"
|
|
- "traefik.http.middlewares.oidc.plugin.traefikoidc.redis.cacheMode=hybrid"
|
|
networks:
|
|
- web
|
|
|
|
networks:
|
|
web:
|
|
external: true</code></pre>
|
|
|
|
<!-- Kubernetes with Redis -->
|
|
<pre class="deployment-example-kubernetes hidden bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm"><code>apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: oidc-with-redis
|
|
namespace: traefik
|
|
spec:
|
|
plugin:
|
|
traefikoidc:
|
|
providerURL: https://accounts.google.com
|
|
clientID: your-client-id
|
|
clientSecret: your-client-secret
|
|
sessionEncryptionKey: your-encryption-key
|
|
callbackURL: /oauth2/callback
|
|
forceHTTPS: true
|
|
# Redis Configuration for multi-replica deployments
|
|
redis:
|
|
enabled: true
|
|
address: "redis-service.redis-namespace:6379"
|
|
password: "your-redis-password"
|
|
db: 0
|
|
keyPrefix: "traefikoidc:"
|
|
cacheMode: "hybrid"
|
|
enableCircuitBreaker: true
|
|
circuitBreakerThreshold: 5
|
|
enableHealthCheck: true
|
|
healthCheckInterval: 30</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Security Section -->
|
|
<section id="security" class="py-12 sm:py-16 md:py-20 bg-gray-50 dark:bg-gray-800 theme-transition">
|
|
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
|
<div class="text-center mb-8 sm:mb-12">
|
|
<h2 class="text-2xl sm:text-3xl md:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-3 sm:mb-4">Security First</h2>
|
|
<p class="text-base sm:text-lg text-gray-600 dark:text-gray-300 px-4">Built with enterprise security requirements in mind</p>
|
|
</div>
|
|
<div class="max-w-4xl mx-auto">
|
|
<div class="grid md:grid-cols-2 gap-6">
|
|
<div class="glass p-6 rounded-xl">
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-4 flex items-center">
|
|
<i class="fas fa-lock mr-2 text-blue-500"></i>
|
|
Token Security
|
|
</h3>
|
|
<ul class="text-gray-600 dark:text-gray-400 space-y-2 text-sm">
|
|
<li>• JWT signature verification with JWK rotation</li>
|
|
<li>• Replay attack detection via JTI claims</li>
|
|
<li>• Strict audience and issuer validation</li>
|
|
<li>• Automatic token refresh before expiry</li>
|
|
<li>• Token revocation on logout</li>
|
|
</ul>
|
|
</div>
|
|
<div class="glass p-6 rounded-xl">
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-4 flex items-center">
|
|
<i class="fas fa-shield-alt mr-2 text-purple-500"></i>
|
|
Session Security
|
|
</h3>
|
|
<ul class="text-gray-600 dark:text-gray-400 space-y-2 text-sm">
|
|
<li>• AES-256-GCM encrypted session cookies</li>
|
|
<li>• CSRF protection with state parameter</li>
|
|
<li>• Secure, HttpOnly, SameSite cookies</li>
|
|
<li>• Configurable session timeouts</li>
|
|
<li>• Bounded session cache with LRU eviction</li>
|
|
</ul>
|
|
</div>
|
|
<div class="glass p-6 rounded-xl">
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-4 flex items-center">
|
|
<i class="fas fa-globe mr-2 text-cyan-500"></i>
|
|
Security Headers
|
|
</h3>
|
|
<ul class="text-gray-600 dark:text-gray-400 space-y-2 text-sm">
|
|
<li>• Content Security Policy (CSP)</li>
|
|
<li>• HTTP Strict Transport Security (HSTS)</li>
|
|
<li>• X-Frame-Options, X-Content-Type-Options</li>
|
|
<li>• CORS configuration</li>
|
|
<li>• Customizable header profiles</li>
|
|
</ul>
|
|
</div>
|
|
<div class="glass p-6 rounded-xl">
|
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-4 flex items-center">
|
|
<i class="fas fa-tachometer-alt mr-2 text-emerald-500"></i>
|
|
Rate Limiting
|
|
</h3>
|
|
<ul class="text-gray-600 dark:text-gray-400 space-y-2 text-sm">
|
|
<li>• Configurable request rate limits</li>
|
|
<li>• Protection against brute force attacks</li>
|
|
<li>• Per-client rate limiting</li>
|
|
<li>• Graceful handling of limit exceeded</li>
|
|
<li>• Customizable response codes</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Why Choose Section -->
|
|
<section class="py-12 sm:py-16 md:py-20 bg-gray-50 dark:bg-gray-800 theme-transition">
|
|
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
|
<div class="text-center mb-8 sm:mb-12">
|
|
<h2 class="text-2xl sm:text-3xl md:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-3 sm:mb-4">Why Choose Traefik OIDC?</h2>
|
|
<p class="text-base sm:text-lg text-gray-600 dark:text-gray-300 px-4">A better alternative to oauth2-proxy and forward-auth</p>
|
|
</div>
|
|
<div class="max-w-4xl mx-auto">
|
|
<div class="glass rounded-xl overflow-hidden shadow-modern">
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full text-sm">
|
|
<thead class="bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
|
<tr>
|
|
<th class="px-4 py-3 text-left font-semibold">Feature</th>
|
|
<th class="px-4 py-3 text-center font-semibold">Traefik OIDC</th>
|
|
<th class="px-4 py-3 text-center font-semibold">oauth2-proxy</th>
|
|
<th class="px-4 py-3 text-center font-semibold">forward-auth</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
|
|
<tr class="hover:bg-gray-50 dark:hover:bg-gray-800/50">
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300 font-medium">Native Plugin</td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-red-500">✗</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-red-500">✗</span></td>
|
|
</tr>
|
|
<tr class="hover:bg-gray-50 dark:hover:bg-gray-800/50">
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300 font-medium">No Extra Service</td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-red-500">✗</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-red-500">✗</span></td>
|
|
</tr>
|
|
<tr class="hover:bg-gray-50 dark:hover:bg-gray-800/50">
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300 font-medium">Auto Provider Detection</td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-red-500">✗</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-red-500">✗</span></td>
|
|
</tr>
|
|
<tr class="hover:bg-gray-50 dark:hover:bg-gray-800/50">
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300 font-medium">Dynamic Client Registration</td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-red-500">✗</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-red-500">✗</span></td>
|
|
</tr>
|
|
<tr class="hover:bg-gray-50 dark:hover:bg-gray-800/50">
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300 font-medium">Automatic Scope Filtering</td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-red-500">✗</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-red-500">✗</span></td>
|
|
</tr>
|
|
<tr class="hover:bg-gray-50 dark:hover:bg-gray-800/50">
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300 font-medium">Built-in Security Headers</td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-red-500">✗</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-red-500">✗</span></td>
|
|
</tr>
|
|
<tr class="hover:bg-gray-50 dark:hover:bg-gray-800/50">
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300 font-medium">Template Headers</td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span></td>
|
|
</tr>
|
|
<tr class="hover:bg-gray-50 dark:hover:bg-gray-800/50">
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300 font-medium">Memory Efficient</td>
|
|
<td class="px-4 py-3 text-center"><span class="text-green-500">✓</span> <span class="text-xs text-gray-500">LRU caches</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-gray-400">Varies</span></td>
|
|
<td class="px-4 py-3 text-center"><span class="text-gray-400">Varies</span></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- CTA Section -->
|
|
<section class="py-12 sm:py-16 md:py-20 bg-gradient-to-r from-blue-600 to-purple-600">
|
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 text-center">
|
|
<h2 class="text-2xl sm:text-3xl md:text-4xl font-bold text-white mb-4">Ready to Secure Your Applications?</h2>
|
|
<p class="text-lg text-blue-100 mb-8 max-w-2xl mx-auto">
|
|
Get started with Traefik OIDC in minutes. Full documentation and examples available on GitHub.
|
|
</p>
|
|
<div class="flex flex-col sm:flex-row gap-4 justify-center">
|
|
<a href="https://github.com/lukaszraczylo/traefikoidc" class="bg-white hover:bg-gray-100 text-blue-600 px-8 py-3 rounded-lg font-medium transition-all duration-300 min-h-[48px] flex items-center justify-center shadow-lg hover:shadow-xl hover:scale-105">
|
|
<i class="fab fa-github mr-2"></i>View on GitHub
|
|
</a>
|
|
<a href="https://github.com/lukaszraczylo/traefikoidc/blob/main/README.md" class="bg-transparent border-2 border-white hover:bg-white/10 text-white px-8 py-3 rounded-lg font-medium transition-all duration-300 min-h-[48px] flex items-center justify-center hover:scale-105">
|
|
<i class="fas fa-book mr-2"></i>Documentation
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Footer -->
|
|
<footer class="py-8 bg-white dark:bg-gray-900 border-t border-gray-200 dark:border-gray-800 theme-transition">
|
|
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
|
<div class="flex flex-col md:flex-row justify-between items-center gap-4">
|
|
<div class="flex items-center gap-2">
|
|
<i class="fas fa-shield-alt text-xl text-blue-500"></i>
|
|
<span class="text-xl font-bold gradient-text">Traefik OIDC</span>
|
|
</div>
|
|
<div class="flex items-center space-x-6">
|
|
<a href="https://github.com/lukaszraczylo/traefikoidc" class="text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100">
|
|
<i class="fab fa-github text-xl"></i>
|
|
</a>
|
|
<a href="https://github.com/lukaszraczylo/traefikoidc/issues" class="text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 text-sm">Issues</a>
|
|
<a href="https://github.com/lukaszraczylo/traefikoidc/releases" class="text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 text-sm">Releases</a>
|
|
</div>
|
|
<p class="text-gray-500 dark:text-gray-400 text-sm">Apache 2.0 License</p>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
<script>
|
|
// Theme toggle
|
|
document.getElementById('theme-toggle').addEventListener('click', function() {
|
|
if (document.documentElement.classList.contains('dark')) {
|
|
document.documentElement.classList.remove('dark');
|
|
localStorage.theme = 'light';
|
|
} else {
|
|
document.documentElement.classList.add('dark');
|
|
localStorage.theme = 'dark';
|
|
}
|
|
});
|
|
|
|
// Mobile menu toggle
|
|
document.getElementById('mobile-menu-toggle').addEventListener('click', function() {
|
|
const menu = document.getElementById('mobile-menu');
|
|
const openIcon = document.getElementById('menu-open-icon');
|
|
const closeIcon = document.getElementById('menu-close-icon');
|
|
|
|
menu.classList.toggle('hidden');
|
|
openIcon.classList.toggle('hidden');
|
|
closeIcon.classList.toggle('hidden');
|
|
});
|
|
|
|
// Close mobile menu on link click
|
|
document.querySelectorAll('#mobile-menu a').forEach(link => {
|
|
link.addEventListener('click', function() {
|
|
document.getElementById('mobile-menu').classList.add('hidden');
|
|
document.getElementById('menu-open-icon').classList.remove('hidden');
|
|
document.getElementById('menu-close-icon').classList.add('hidden');
|
|
});
|
|
});
|
|
|
|
// Platform tab switching (unified across all sections)
|
|
function switchPlatform(platform) {
|
|
// Update all tab buttons
|
|
document.querySelectorAll('.platform-tab, .deployment-tab').forEach(tab => {
|
|
if (tab.dataset.platform === platform) {
|
|
tab.classList.add('bg-gradient-to-r', 'from-blue-600', 'to-purple-600', 'text-white', 'shadow-md');
|
|
tab.classList.remove('text-gray-600', 'dark:text-gray-300', 'hover:bg-gray-100', 'dark:hover:bg-gray-700');
|
|
} else {
|
|
tab.classList.remove('bg-gradient-to-r', 'from-blue-600', 'to-purple-600', 'text-white', 'shadow-md');
|
|
tab.classList.add('text-gray-600', 'dark:text-gray-300', 'hover:bg-gray-100', 'dark:hover:bg-gray-700');
|
|
}
|
|
});
|
|
|
|
// Show/hide all platform-specific content (Installation, Configuration sections)
|
|
document.querySelectorAll('.platform-example-docker, .platform-desc-docker').forEach(el => {
|
|
el.classList.toggle('hidden', platform !== 'docker');
|
|
});
|
|
document.querySelectorAll('.platform-example-kubernetes, .platform-desc-kubernetes').forEach(el => {
|
|
el.classList.toggle('hidden', platform !== 'kubernetes');
|
|
});
|
|
|
|
// Show/hide deployment section content
|
|
document.querySelectorAll('.deployment-example-docker, .deployment-desc-docker, .deployment-icon-docker').forEach(el => {
|
|
el.classList.toggle('hidden', platform !== 'docker');
|
|
});
|
|
document.querySelectorAll('.deployment-example-kubernetes, .deployment-desc-kubernetes, .deployment-icon-kubernetes').forEach(el => {
|
|
el.classList.toggle('hidden', platform !== 'kubernetes');
|
|
});
|
|
|
|
// Save preference
|
|
localStorage.setItem('selected-platform', platform);
|
|
}
|
|
|
|
// Initialize all platform tabs
|
|
document.querySelectorAll('.platform-tab, .deployment-tab').forEach(tab => {
|
|
tab.addEventListener('click', function() {
|
|
switchPlatform(this.dataset.platform);
|
|
});
|
|
});
|
|
|
|
// Restore saved preference
|
|
const savedPlatform = localStorage.getItem('selected-platform');
|
|
if (savedPlatform) {
|
|
switchPlatform(savedPlatform);
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|