traefik-sso icon indicating copy to clipboard operation
traefik-sso copied to clipboard

a simple SSO PHP Application to authenticate against Docker Services - README follows...

Traefik SSO

A lightweight PHP-based single sign-on authentication service designed to work seamlessly with Traefik ForwardAuth middleware.

Features

  • Simplified admin access without requiring username input
  • JWT-based authentication with configurable expiration
  • Multiple access lists for granular user permissions
  • Cookie-based session management for persistent authentication
  • Event system for custom authentication hooks
  • Global logout functionality to invalidate all sessions

Quick Start

Docker Compose

services:
  sso:
    image: robinmoser/sso:latest
    environment:
      HOSTNAME: sso.example.com
      WEB_ALIAS_DOMAIN: sso.example.com
    volumes:
      - ./config:/app/config:ro
    labels:
      - 'traefik.enable=true'
      - 'traefik.http.services.sso.loadbalancer.server.port=80'
      - 'traefik.http.routers.sso.rule=Host(`sso.example.com`)'

Configuration

  1. Copy configs/credentials.example.php to config/credentials.php
  2. Update user credentials and access lists

Users & Access Lists

$credentials = [

    'expire' => '14 day',
    'users' => [
        'admin' => '$1$password_hash...',
        'user2' => '$1$password_hash...',
        'user1' => '$1$password_hash...',
    ],

    'lists' => [
        // default access list for the admin user:
        'private' => ['admin'],
        'family' => ['admin', 'user2', 'user3'],
    ]
];
  1. Configure your Traefik Serivices to use the SSO service
services:
  myservice:
    image: my_service_image
    labels:
      - 'traefik.enable=true'
      - 'traefik.http.services.myservice.loadbalancer.server.port=80'
      - 'traefik.http.routers.myservice.middlewares=auth'
      - 'traefik.http.routers.myservice.rule=Host(`service.example.com`)'
       - 'traefik.http.middlewares.auth.forwardauth.address=http://sso.example.com/'

Authentication Modes

Admin Mode (Default)

When no ?list= parameter is provided, only a password is required, as the only allowed user is admin. This provides simplified access for admin-only services.

- 'traefik.http.middlewares.auth.forwardauth.address=http://sso.example.com/'

With Access Lists

When configuring Traefik ForwardAuth with a ?list= parameter, users must provide both username and password:

- 'traefik.http.middlewares.auth.forwardauth.address=http://sso.example.com/?list=family'

This gives access to all users defined in the specified access list.

Global Logout

To invalidate all active JWT tokens and force all users to re-authenticate, enter logout in the password field on the SSO login page. This immediately expires all existing sessions across all services.

Custom Events

The SSO service includes an event system that triggers on authentication actions. You can create custom event handlers by placing PHP files in the events/ directory.

Available Events

  • user.login.success - Triggered after successful authentication
  • user.login.failure - Triggered after failed authentication attempts
  • user.logout - Triggered when global logout is performed

Event Handler Example

Create a file in events/ directory to handle authentication events:

<?php
// events/pushover.php

Event::bind('user.login.failure', function($args = array()) {
    pushover("Login failed! (IP: " . $_SERVER['HTTP_X_REAL_IP'] . ")\n"
     . "User: " . $args[0] . "@" . $args[1] . "\n" . $_GET['service']);
});

Event::bind('user.login.success', function($args = array()) {
    pushover("Login succeeded! (IP: " . $_SERVER['HTTP_X_REAL_IP'] . ")\n"
     . "User: " . $args[0] . "@" . $args[1] . "\n" . $_GET['service']);
});

function pushover($message) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'https://api.pushover.net/1/messages.json');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, array(
        'token' => 'YOUR_APP_TOKEN',
        'user' => 'YOUR_USER_KEY',
        'message' => $message
    ));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_exec($ch);
    curl_close($ch);
}

All PHP files in the events/ directory are automatically loaded and executed.

How It Works

  1. User accesses a protected service behind Traefik
  2. Traefik forwards auth request to SSO service
  3. If not authenticated, user is redirected to login page
  4. After successful login, JWT token is issued and user redirected back
  5. Subsequent requests use local cookies for authentication

License

Created by Robin Moser, 2020