Apache2 与 mod_auth_openidc

Apache2 与 mod_auth_openidc(Apache2 with mod_auth_openidc)

目录

mod_auth_openidc 让 Apache2 直接处理完整的 OIDC 认证流程——无需单独的代理容器(OAuth2 Proxy、Authentik Outpost)。Apache 针对你的身份提供方对用户进行认证,并通过 HTTP 请求头把 JWT 访问令牌传给 Wavelog。

架构

Browser  →  Apache2 (mod_auth_openidc)  →  Wavelog (PHP-FPM)
                        ↕
              Identity Provider (OIDC)

前置条件

安装模块

apt install libapache2-mod-auth-openidc
a2enmod auth_openidc headers
systemctl reload apache2

配置身份提供方

在你的 IdP 中创建一个 OAuth2/OpenID Connect 客户端,包含:

  • 重定向 URI: https://wavelog.example.org/redirect_uri
  • 客户端类型: 机密(Confidential)
  • 记下 Client ID、Client Secret 与 Issuer URL

特定提供方的设置参见:

  • Keycloak:Issuer URL 为 https://auth.example.org/realms/example
  • Authentik:Issuer URL 为 https://auth.example.org/application/o/wavelog/

为会话 cookie 生成一个加密口令:

openssl rand -base64 32

Apache2 虚拟主机

<VirtualHost *:443>
    ServerName wavelog.example.org

    DocumentRoot /var/www/wavelog

    SSLEngine on
    SSLCertificateFile    /etc/ssl/certs/wavelog.pem
    SSLCertificateKeyFile /etc/ssl/private/wavelog.key

    # --- mod_auth_openidc ---
    OIDCProviderMetadataURL https://auth.example.org/application/o/wavelog/.well-known/openid-configuration
    OIDCClientID            <your-client-id>
    OIDCClientSecret        <your-client-secret>
    OIDCRedirectURI         https://wavelog.example.org/redirect_uri
    OIDCCryptoPassphrase    <your-random-passphrase>
    OIDCScope               "openid email profile wavelog_callsign" # scope depends on your identity provider

    # Make the access token available as Apache environment variable
    OIDCPassAccessToken     On

    # The redirect URI callback must be handled by mod_auth_openidc, not by CodeIgniter.
    # Without this block, CodeIgniter's .htaccess rewrites /redirect_uri to index.php → 404.
    <Location "/redirect_uri">
        AuthType openid-connect
        Require valid-user
    </Location>

    # Protect only the SSO login endpoint — all other paths remain publicly accessible
    <Location "/index.php/header_auth/login">
        AuthType openid-connect
        Require valid-user
        # mod_auth_openidc sets OIDC_access_token as an Apache env var.
        # This directive forwards it as an HTTP request header so PHP can read it.
        RequestHeader set X-Access-Token "%{OIDC_access_token}e" env=OIDC_access_token
    </Location>

    <Directory /var/www/wavelog>
        Options FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    <FilesMatch \.php$>
        SetHandler "proxy:unix:/run/php/php8.4-fpm.sock|fcgi://localhost"
    </FilesMatch>
</VirtualHost>

重要

只有 /index.php/header_auth/login 受保护。Wavelog 的其他所有路径仍可公开访问——这是标准登录表单、API 集成与 ADIF 导入正常工作所必需的。

注意(为何需要 RequestHeader)

OIDCPassAccessToken On 会让 mod_auth_openidc 把访问令牌存入 Apache 环境变量 OIDC_access_token。当 Wavelog 通过 SetHandler 由 PHP-FPM 提供服务时,该环境变量不会自动作为 HTTP 请求头转发。RequestHeader 指令会把它显式转换为 X-Access-Token 请求头,PHP 将其暴露为 HTTP_X_ACCESS_TOKEN。

注意(为何 /redirect_uri 需要独立的 Location 块)

CodeIgniter 的 .htaccess 会把所有未知 URL 重写到 index.php。如果没有专门的 <Location "/redirect_uri"> 块,Apache 根本不会给 mod_auth_openidc 处理 OIDC 回调的机会——请求会被重写规则捕获并返回 404。加上带 AuthType openid-connect 的 Location 块,就能告诉 Apache 在重写规则运行之前先把请求交给 mod_auth_openidc。


Wavelog 的 sso.php

mod_auth_openidc 以 X-Access-Token 转发访问令牌,PHP 将其暴露为 HTTP_X_ACCESS_TOKEN:

<?php
// Access token header forwarded by mod_auth_openidc via RequestHeader
$config['auth_header_accesstoken'] = "HTTP_X_ACCESS_TOKEN";

// Logout: redirect to the IdP end-session endpoint
// Keycloak:
// $config['auth_header_url_logout'] = 'https://auth.example.org/realms/example/protocol/openid-connect/logout';
// Authentik:
$config['auth_header_url_logout'] = 'https://auth.example.org/application/o/wavelog/end-session/';

// JWKS endpoint for JWT signature verification
// Keycloak:
// $config['auth_header_jwks_uri'] = 'https://auth.example.org/realms/example/protocol/openid-connect/certs';
// Authentik:
$config['auth_header_jwks_uri'] = 'https://auth.example.org/application/o/wavelog/jwks/';

sso.php 的其他所有设置(声明映射、自动创建等)与各提供方专页中所述相同。


故障排查

/redirect_uri 上返回 404 : CodeIgniter 的重写规则在 mod_auth_openidc 处理之前就捕获了 OIDC 回调。按上文所示添加带 AuthType openid-connect 的 <Location "/redirect_uri"> 块。

SSO Authentication: Missing access token header : X-Access-Token 请求头没有到达 PHP。请确认已设置 OIDCPassAccessToken On,并且 RequestHeader set X-Access-Token "%{OIDC_access_token}e" env=OIDC_access_token 指令位于 <Location "/index.php/header_auth/login"> 块内。还要确认已启用 mod_headers(a2enmod headers)。

JWT 验证失败 : 检查 auth_header_jwks_uri 是否指向正确的 JWKS 端点,以及 Apache 服务器能否通过网络访问它。在 sso.php 中启用调试日志以查看原始令牌。

Wavelog 手册(中文版) / Apache2 与 mod_auth_openidc 0 字 0 行 bg8lng
2026-10-21T12:42:36.092463895Z 2026-10-21T12:43:43.519466871Z