应用集成 Authentik OAuth 认证指南
本文整合了多个常用应用集成 Authentik OAuth 认证的配置方法,包括 Airflow、Grafana 和 JupyterHub。
通用 Authentik 配置
在 Authentik 中创建 OAuth2/OpenID 应用时,需要配置以下端点:
| 端点 | URL 格式 |
|---|---|
| 授权 | https://authentik.example.com/application/o/authorize/ |
| Token | https://authentik.example.com/application/o/token/ |
| UserInfo | https://authentik.example.com/application/o/userinfo/ |
| 元数据 | https://authentik.example.com/application/o/{app}/.well-known/openid-configuration |
重要提示:userinfo 端点的路径必须带斜杠 /userinfo/,否则会报错。
Airflow 集成
版本信息
- App Version: 2.8.3
- Chart Version: 1.13.1
OAuth 认证配置
webserver_config.py:
from flask_appbuilder.security.manager import AUTH_OAUTH
from airflow.auth.managers.fab.security_manager.override import FabAirflowSecurityManagerOverride
AUTH_TYPE = AUTH_OAUTH
AUTH_USER_REGISTRATION = True
AUTH_USER_REGISTRATION_ROLE = "User" # 默认角色
OAUTH_PROVIDERS = [
{
"name": "OAuth",
"icon": "fa-circle-o",
"token_key": "access_token",
"remote_app": {
"client_id": "your-client-id",
"api_base_url": "https://authentik.example.com/application/o/",
"client_secret": "your-client-secret",
"client_kwargs": {"scope": "openid email profile"},
"server_metadata_url": "https://authentik.example.com/application/o/oauth/.well-known/openid-configuration",
},
}
]
PERMANENT_SESSION_LIFETIME = 259200 # 3 天
class CustomSecurityManager(FabAirflowSecurityManagerOverride):
def get_oauth_user_info(self, provider, resp):
if provider != "OAuth":
return {}
# 关键:必须是 userinfo/ 而不是 userinfo
me = self.appbuilder.sm.oauth_remotes[provider].get("userinfo/")
data = me.json()
return {
"email": data["email"],
"username": data.get("name", ""),
"first_name": data.get("given_name", ""),
"role_keys": data.get("groups", []), # 支持组映射
}
SECURITY_MANAGER_CLASS = CustomSecurityManager
LDAP 认证配置(备选)
from flask_appbuilder.security.manager import AUTH_LDAP
AUTH_TYPE = AUTH_LDAP
AUTH_LDAP_SERVER = "ldap://ldap.example.com"
AUTH_LDAP_USE_TLS = False
AUTH_USER_REGISTRATION = True
AUTH_USER_REGISTRATION_ROLE = "Admin"
AUTH_LDAP_LASTNAME_FIELD = "cn"
AUTH_LDAP_EMAIL_FIELD = "mail"
AUTH_LDAP_SEARCH = "ou=foo,ou=People,dc=example,dc=com"
AUTH_LDAP_UID_FIELD = "uid"
AUTH_LDAP_BIND_USER = "cn=admin,dc=example,dc=com"
AUTH_LDAP_BIND_PASSWORD = "adminPassword"
AUTH_ROLES_MAPPING = {
"cn=g-admin,ou=Group,dc=example,dc=com": ["Admin"],
}
AUTH_LDAP_GROUP_FIELD = "memberOf"
AUTH_ROLES_SYNC_AT_LOGIN = True
PERMANENT_SESSION_LIFETIME = 86400
API 认证
config:
api:
auth_backends: "airflow.api.auth.backend.basic_auth"
Grafana 集成
OAuth 认证配置
grafana.ini:
grafana:
grafana.ini:
auth:
oauth_allow_insecure_email_lookup: true
auth.generic_oauth:
enabled: true
name: "OAuth"
client_id: "your-client-id"
client_secret: "your-client-secret"
scopes: "openid email profile offline_access"
auth_url: "https://authentik.example.com/application/o/authorize/"
token_url: "https://authentik.example.com/application/o/token/"
api_url: "https://authentik.example.com/application/o/userinfo/"
use_pkce: true
use_refresh_token: true
allow_sign_up: false
allow_assign_grafana_admin: true
auto_login: true
skip_org_role_sync: true
server:
root_url: "https://grafana.example.com/" # 必须正确配置
关键配置说明
| 配置项 | 说明 | 注意事项 |
|---|---|---|
root_url | Grafana 访问地址 | 必须与实际域名一致,否则会重定向失败 |
oauth_allow_insecure_email_lookup | 邮箱查找 | 使用邮箱匹配用户时需设为 true |
use_pkce | PKCE 支持 | 增强安全性 |
LDAP 认证配置(备选)
grafana:
ldap:
enabled: true
config: |
verbose_logging = true
[[servers]]
host = "ldap.example.com"
port = 389
use_ssl = false
bind_dn = "cn=admin,dc=example,dc=com"
bind_password = "examplePassword"
search_filter = "(uid=%s)"
search_base_dns = ["ou=foo,dc=example,dc=com"]
[servers.attributes]
name = "cn"
surname = "sn"
username = "uid"
email = "mail"
[[servers.group_mappings]]
group_dn = "cn=g-admin,ou=Group,dc=example,dc=com"
org_role = "Editor"
JupyterHub 集成
OAuth 认证配置
values.yaml:
hub:
config:
Authenticator:
admin_users:
- "admin"
allow_all: true
auto_login: true
GenericOAuthenticator:
client_id: "your-client-id"
client_secret: "your-client-secret"
login_service: "OAuth"
authorize_url: "https://authentik.example.com/application/o/authorize/"
token_url: "https://authentik.example.com/application/o/token/"
userdata_url: "https://authentik.example.com/application/o/userinfo/"
oauth_callback_url: "https://jupyter.example.com/hub/oauth_callback"
scope:
- "openid"
- "email"
- "profile"
username_claim: "sub"
JupyterHub:
authenticator_class: "generic-oauth"
admin_access: true
配置说明
| 配置项 | 说明 | 可选值 |
|---|---|---|
allow_all | 是否允许所有用户 | true / false |
username_claim | 用户名字段 | sub / email / preferred_username |
oauth_callback_url | 回调地址 | 必须在 Authentik 中配置 |
LDAP 认证配置(备选)
hub:
config:
LDAPAuthenticator:
server_address: "ldap.example.com"
use_ssl: true
bind_dn_template:
- "uid={username},ou=foo,ou=People,dc=example,dc=com"
escape_userdn: true
JupyterHub:
authenticator_class: "ldapauthenticator.LDAPAuthenticator"
OAuth vs LDAP 对比
| 特性 | OAuth | LDAP |
|---|---|---|
| 配置复杂度 | 简单 | 中等 |
| 统一登录(SSO) | ✅ 支持 | ❌ 不支持 |
| 离线访问 | ✅ Refresh Token | ❌ 需在线验证 |
| 安全性 | ✅ PKCE 增强 | 一般 |
| 适用场景 | 现代 SSO 架构 | 传统 LDAP 环境 |
常见问题
userinfo 路径问题
Authentik 的 userinfo 端点必须是 /userinfo/(带斜杠),否则会报错:
ERROR - OAUTH userinfo does not have username or email {}
重定向 URI 不匹配
Grafana 报错 redirect_uri_mismatch:确保 root_url 与实际访问域名一致。
回调地址配置
JupyterHub 的 oauth_callback_url 必须在 Authentik 应用的”重定向 URI”中添加。