Authentik
Authentik
目录
- 架构
- 步骤 1:创建 OAuth2 提供方
- 步骤 2:创建应用
- 步骤 3:添加呼号声明
- 步骤 4:配置 OAuth2 Proxy
- 步骤 5:配置 Web 服务器
- 步骤 6:配置 Wavelog
- 步骤 7:验证
- 故障排查
提示:已经在运行 Apache2?改用 mod_auth_openidc
如果 Apache2 是你的 Web 服务器,推荐使用
mod_auth_openidc——它原生处理 OIDC 流程,无需单独的 OAuth2 Proxy 容器。参见 Apache2 配合 mod_auth_openidc。
本指南介绍如何将 Authentik 配置为身份提供方,并使用 OAuth2 Proxy 作为认证反向代理。
架构
Browser → Webserver (nginx / Apache2) → OAuth2 Proxy → Wavelog
↕
Authentik (JWKS)
OAuth2 Proxy 负责与 Authentik 之间的 OIDC 流程,并将 JWT 访问令牌以 HTTP 请求头的形式转发给 Wavelog。Wavelog 使用 Authentik 的 JWKS 端点校验该令牌。
步骤 1:创建 OAuth2 提供方
在 Authentik 管理界面中:
- 进入 应用 → 提供方 → 创建
- 选择 OAuth2/OpenID 提供方
- 配置:
- 名称:
wavelog - 授权流程: 选择你的默认授权流程
- 客户端类型:
Confidential - 重定向 URI:
https://wavelog.example.org/oauth2/callback
- 名称:
- 保存
保存后,从提供方详情页复制 客户端 ID 和 客户端密钥。
步骤 2:创建应用
- 进入 应用 → 应用 → 创建
- 配置:
- 名称:
Wavelog - Slug:
wavelog - 提供方: 选择步骤 1 中创建的 OAuth2 提供方
- 名称:
- 保存
步骤 3:添加呼号声明
默认情况下,Authentik 不会在令牌中包含自定义用户属性。你需要将呼号存储为用户属性,并创建一个 Scope Mapping 将其加入 JWT。
3a. 添加用户属性
- 进入 目录 → 用户 → 选择一个用户 → 编辑
-
在 属性 字段(JSON 编辑器)中添加:
json { "callsign": "N0CALL" } -
保存
注意
Authentik 将自定义属性存储为 JSON 数据块。管理界面中没有专门用于自定义属性的表单字段——这是 Authentik 的标准行为。属性会被正确存储,并按下文 Scope Mapping 的配置出现在 JWT 中。
3b. 创建 Scope Mapping
- 进入 定制 → 属性映射 → 创建
- 选择 Scope Mapping
-
配置:
- 名称:
Wavelog Callsign - Scope 名称:
wavelog_callsign -
表达式:
python return { "callsign": request.user.attributes.get("callsign", None) }
- 名称:
-
保存
提示
用同样的方法,通过创建额外的 Scope Mapping 将其他用户属性(例如
locator)映射为 JWT 声明。
3c. 将 Scope Mapping 添加到提供方
- 返回你的 OAuth2 提供方(
Applications→Providers→ 选择wavelog) - 编辑 → 高级协议设置 → 作用域
- 在列表中添加
Wavelog Callsign - 保存
步骤 4:配置 OAuth2 Proxy
OAuth2 Proxy 充当认证反向代理。它负责与 Authentik 之间的 OIDC 登录流程,并将 JWT 访问令牌转发给 Wavelog。
重要
OAuth2 Proxy 只能保护
/index.php/header_auth/login。Wavelog 的其他所有路径都必须直通,不得要求认证。
Docker Compose
services:
oauth2-proxy:
container_name: oauth2-proxy
image: quay.io/oauth2-proxy/oauth2-proxy:latest
command: --config /oauth2-proxy.cfg
hostname: oauth2-proxy
volumes:
- "./oauth2-proxy.cfg:/oauth2-proxy.cfg"
restart: unless-stopped
networks:
- proxy-net
nginx:
container_name: nginx-proxy
image: nginx:alpine
volumes:
- "./nginx.conf:/etc/nginx/conf.d/default.conf:ro"
- "./ssl:/etc/nginx/ssl:ro"
ports:
- "80:80"
- "443:443"
depends_on:
- oauth2-proxy
restart: unless-stopped
networks:
- proxy-net
networks:
proxy-net:
driver: bridge
oauth2-proxy.cfg
详细说明请参阅 OAuth2 Proxy 官方文档。
http_address = "0.0.0.0:4180"
cookie_secret = "your-random-cookie-secret" # see below how to generate
provider = "oidc"
email_domains = ["*"]
client_id = "your-client-id"
client_secret = "your-client-secret"
redirect_url = "https://wavelog.example.org/oauth2/callback"
oidc_issuer_url = "https://authentik.example.org/application/o/wavelog/"
scope = "openid email profile wavelog_callsign"
insecure_oidc_allow_unverified_email = true
code_challenge_method = "S256"
pass_user_headers = true
set_xauthrequest = true
pass_access_token = true
# See https://oauth2-proxy.github.io/oauth2-proxy/configuration/session_storage
cookie_refresh = "4m"
cookie_expire = "30m"
skip_provider_button = true
whitelist_domains = "authentik.example.org"
使用以下命令生成 cookie 密钥:
openssl rand -base64 32 | tr -- '+/' '-_'
注意(与 Keycloak 的主要差异)
- 使用
provider = "oidc"而非keycloak-oidc——Authentik 使用通用 OIDC 提供方scope必须显式包含wavelog_callsign,才能请求该自定义作用域- 必须设置
insecure_oidc_allow_unverified_email = true,因为 Authentik 默认不会将用户邮箱标记为已验证。若要移除该设置,请进入 目录 → 用户,编辑该用户并手动启用 邮箱已验证oidc_issuer_url遵循 Authentik 的格式:https://<authentik-domain>/application/o/<application-slug>/
步骤 5:配置 Web 服务器
nginx
server {
listen 80;
server_name wavelog.example.org;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name wavelog.example.org;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.key;
# oauth2-proxy endpoints — OIDC flow (callback, sign-in, etc.)
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;
# Recommended buffer settings for larger JWTs to prevent 502 errors
proxy_buffer_size 16k;
proxy_buffers 4 16k;
proxy_busy_buffers_size 16k;
}
# Auth subrequest endpoint (internal, used by auth_request only)
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;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_buffer_size 16k;
proxy_buffers 4 16k;
proxy_busy_buffers_size 16k;
}
# SSO login endpoint — oauth2-proxy authenticates, JWT is forwarded to Wavelog
location ^~ /index.php/header_auth/ {
auth_request /oauth2/auth;
# Not authenticated → start Authentik login directly (no splash screen)
error_page 401 = @sso_start;
# Forward JWT access token from oauth2-proxy to Wavelog
auth_request_set $access_token $upstream_http_x_auth_request_access_token;
proxy_set_header X-Authentik-Jwt $access_token;
proxy_pass http://wavelog:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Trigger Authentik login flow
location @sso_start {
return 302 /oauth2/start?rd=/index.php/header_auth/login;
}
# All other routes — no authentication required, Wavelog manages sessions itself
location / {
proxy_pass http://wavelog:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
重要
转发给 Wavelog 的请求头是
X-Authentik-Jwt(而非 Keycloak 所用的X-Forwarded-Access-Token)。该名称必须与sso.php中的auth_header_accesstoken一致(参见步骤 6)。
步骤 6:配置 Wavelog
application/config/config.php:
<?php
$config['auth_header_enable'] = true;
application/config/sso.php(从 sso.sample.php 复制):
<?php
$config['auth_header_create'] = true;
$config['auth_header_allow_direct_login'] = false;
$config['auth_header_hide_password_field'] = true;
// Authentik JWT is forwarded by nginx as X-Authentik-Jwt
$config['auth_header_accesstoken'] = "HTTP_X_AUTHENTIK_JWT";
$config['auth_header_text'] = "Login with SSO";
// Redirect to Authentik end-session on logout
$config['auth_header_url_logout'] = 'https://authentik.example.org/application/o/wavelog/end-session/';
// Authentik JWKS endpoint — enables cryptographic JWT verification
$config['auth_header_jwks_uri'] = 'https://authentik.example.org/application/o/wavelog/jwks/';
$config['auth_headers_claim_config'] = [
'user_name' => [
'claim' => 'preferred_username',
'override_on_update' => true,
'allow_manual_change' => false,
],
'user_email' => [
'claim' => 'email',
'override_on_update' => true,
'allow_manual_change' => false,
],
'user_callsign' => [
'claim' => 'callsign',
'override_on_update' => true,
'allow_manual_change' => false,
],
'user_locator' => [
'claim' => 'locator',
'override_on_update' => true,
'allow_manual_change' => true,
],
'user_firstname' => [
'claim' => 'given_name',
'override_on_update' => true,
'allow_manual_change' => true,
],
'user_lastname' => [
'claim' => 'family_name',
'override_on_update' => true,
'allow_manual_change' => true,
],
];
将 authentik.example.org 和 wavelog(应用 slug)替换为你的实际值。
步骤 7:验证
- 在浏览器中打开 Wavelog——应出现 SSO 登录按钮
- 点击该按钮并完成 Authentik 登录
- 你应被重定向到 Wavelog 仪表盘
如果出现问题,可在 sso.php 和 config.php 中启用调试日志,以便检查 JWT 声明:
<?php
// sso.php
$config['auth_header_debug_jwt'] = true;
// config.php
$config['log_threshold'] = 2;
在 application/logs/log-YYYY-MM-DD.php 中查看解码后的 JWT 载荷。确认 callsign、email 和 preferred_username 均存在,且与你的声明映射一致。
警告
排查完成后请再次关闭
auth_header_debug_jwt。
故障排查
email in id_token isn't verified
: Authentik 默认不会将邮箱标记为已验证。可以在 oauth2-proxy.cfg 中添加 insecure_oidc_allow_unverified_email = true(上文示例中已包含),或进入 目录 → 用户,编辑该用户并启用 邮箱已验证。
callsign 声明未出现在 JWT 中
: 令牌中未包含 wavelog_callsign 作用域。请确认:
- 在 定制 → 属性映射 下存在 Scope Mapping
Wavelog Callsign - 该作用域已在 高级协议设置 → 作用域 下分配给提供方
oauth2-proxy.cfg中的scope显式包含wavelog_callsign- 用户已在 目录 → 用户 → 属性 下设置了
callsign属性
SSO Authentication: Missing access token header
: nginx 没有转发令牌请求头。请确认:
/index.php/header_auth/配置块中存在auth_request_set $access_token $upstream_http_x_auth_request_access_token;- 同一配置块中设置了
proxy_set_header X-Authentik-Jwt $access_token; sso.php中设置了auth_header_accesstoken = "HTTP_X_AUTHENTIK_JWT"