Authelia 基于时间的一次性密码(TOTP)二次因素配置全指南
【免费下载链接】autheliaThe Single Sign-On Multi-Factor portal for web apps. OpenID Certified™ and Post-Quantum Cryptography Ready.项目地址: https://gitcode.com/GitHub_Trending/au/authelia
Authelia 采用基于时间的一次性密码算法(Time-Based One-Time Password Algorithm,TOTP,[RFC6238])作为可选的二次认证(2FA)手段,它是基于 HMAC 的一次性密码算法(HOTP,[RFC4226])的扩展。本文以官方配置文档为骨架,结合当前仓库中的配置 Schema、校验器与处理器源码,完整讲解totp配置段下的每一个参数、默认值与合法取值范围,并深入剖析注册、校验、防重放、数据库加密等底层机制,帮助你在生产环境中安全、兼容地部署 TOTP 二次因素。
TOTP 在 Authelia 中的定位
TOTP 属于 Authelia 第二因素(Second Factor)体系中的一种方法,与 WebAuthn(Passkey)、Duo Push 并列。用户启用后,登录流程变为:先通过用户名密码完成第一因素认证,再输入由 Authenticator 应用(如 Google Authenticator、Bitwarden、1Password 等)生成的 6 位动态验证码完成第二因素认证。
Authelia 的默认配置参数是为了最大兼容性而选择的:许多 Authenticator 应用只支持 6 位数字,并且只支持 SHA1 算法。因此在调整任何与生成算法相关的参数前,务必先确认你的用户群体所使用的应用是否支持对应选项。
完整配置示例
以下是一份完整的totp配置段(位于主配置文件configuration.yml中),包含了当前版本支持的全部配置项及其默认值:
totp: disable: false issuer: 'authelia.com' algorithm: 'sha1' digits: 6 period: 30 skew: 1 secret_size: 32 allowed_algorithms: - 'SHA1' allowed_digits: - 6 allowed_periods: - 30 disable_reuse_security_policy: false其中issuer一项请替换为你自己的域名或服务标识。下面逐项说明每个配置选项的含义、默认值与校验规则。
配置选项详解
disable
- 类型:
boolean - 默认值:
false - 是否必填:否
设置为true时,完全禁用一次性密码(TOTP)二次因素功能。在源码层面,当disable为true时,配置校验器会直接跳过 TOTP 配置的校验与默认值填充,见 internal/configuration/validator/totp.go 中的ValidateTOTP函数。
issuer
- 类型:
string - 默认值:
Authelia - 是否必填:否
生成一次性密码的 Authenticator 应用通常会显示一个 issuer(签发者),用于区分用户注册的多个不同服务。Authelia 允许自定义 issuer,使 Authelia 创建的条目与其他应用区分开。
从源码看,issuer 会被写入生成的 otpauth URI 与二维码中,并持久化到数据库。在 internal/totp/totp.go 的GenerateCustom方法中,Issuer作为totp.GenerateOpts的一部分传入;同时在 internal/configuration/schema/totp.go 的DefaultTOTPConfiguration中,默认 issuer 为"Authelia"。
algorithm
- 类型:
string - 默认值:
sha1 - 是否必填:否
- 合法取值(不区分大小写):
sha1、sha256、sha512
algorithm指定生成 TOTP 密钥所使用的 HMAC 哈希算法。需要注意:
重要提醒:很多 TOTP 应用不支持该选项。强烈建议你先了解用户使用的应用并逐一测试后再修改此选项。仅仅验证应用能否添加密钥是不够的,还必须验证它能否用 Authelia 完成实际认证——因为有些应用会静默忽略这些参数。已测试应用清单参见 TOTP 应用参考指南。
修改该值只影响新注册的 TOTP 密钥,详见下文 注册机制 一节。
源码层面,校验器会将该值统一转为大写并与SHA1/SHA256/SHA512白名单比对,非法值会直接报错,例如配置为sha3时会得到错误:totp: option 'algorithm' must be one of 'SHA1', 'SHA256', or 'SHA512' but it's configured as 'SHA3',参见 internal/configuration/validator/totp.go 与对应测试用例 internal/configuration/validator/totp_test.go。
digits
- 类型:
integer - 默认值:
6 - 是否必填:否
- 合法取值:
6或8
digits表示用户执行认证时需要输入的数字位数。一般不建议修改,因为很多 TOTP 应用只支持 6 位;更糟的是部分应用虽然允许添加密钥,却不会按密钥指定的位数生成验证码。
重要提醒:部分 TOTP 应用不支持该选项,修改前务必测试用户的常用应用能否真正完成认证,参见 TOTP 应用参考指南。
校验器对digits有严格限制:只接受6或8,配置为其他值(如20)会得到错误totp: option 'digits' must be 6 or 8 but it's configured as '20',参见 internal/configuration/validator/totp.go。
period
- 类型:
integer - 默认值:
30 - 是否必填:否
- 最小值:
15
period是两次密钥轮换之间的时间间隔(秒),即 TOTP 算法中的时间步长(time step)。它与skew共同决定验证码的有效时长,相互作用关系见下文 输入校验 一节。
官方建议保持30秒,最小值为15。校验器会在period < 15时报错:totp: option 'period' option must be 15 or more but it's configured as '5'。注意,修改period只影响新注册的密钥。
skew
- 类型:
integer - 默认值:
1 - 是否必填:否
skew表示当前有效验证码前后各多少个时间步长内的验证码也一并视为有效。默认值1意味着有 3 个验证码同时有效(当前步长前后各 1 个);设置为2则同时有效 5 个。以默认period=30计算,分别对应 90 秒和 150 秒的有效窗口。
与前面几个参数不同,修改skew会影响所有 TOTP 校验,而不仅仅是新注册的密钥。在源码中,skew 被保存在 provider 实例上而非数据库中的密钥配置里,见 internal/totp/totp.go 与 internal/totp/totp.go 的Validate方法——校验时Skew直接取自运行时的 provider 配置。
secret_size
- 类型:
integer - 默认值:
32 - 是否必填:否
- 最小值:
20
secret_size是生成的共享密钥(shared secret)的字节长度。最小值是 20 字节(160 位),默认 32 字节(256 位)。大多数场景下 32 字节已经足够,不过有些 Authenticator 对超过最小值的密钥可能存在兼容性问题。
说明:RFC4226(HOTP)推荐的最小值是 20 字节,而规范在技术层面允许低至 16 字节(128 位)。Authelia 选择了更保守的 20 字节作为下限,参见 internal/configuration/schema/totp.go 中
SecretSize的minimum=20约束,以及 internal/configuration/validator/totp.go 中对小于 20 的配置直接报错的逻辑。
allowed_algorithms
- 类型:
list(string) - 默认值:
SHA1 - 是否必填:否
与algorithm类似,但该选项的作用是:允许用户在注册 TOTP 设备时,从该列表中自行选择算法(在 Web 界面注册流程中)。该列表始终会包含algorithm选项配置的值——即使你未在列表中显式写出,校验器也会自动追加,见 internal/configuration/validator/totp.go。
allowed_digits
- 类型:
list(integer) - 默认值:
6 - 是否必填:否
与digits类似,允许用户在注册时从列表中自行选择位数(6或8)。列表始终会包含digits配置的值,校验器会保证默认值一定在允许列表中,见 internal/configuration/validator/totp.go。
allowed_periods
- 类型:
list(integer) - 默认值:
30 - 是否必填:否
与period类似,允许用户在注册时从列表中自行选择时间步长(每个值必须 ≥ 15)。列表始终会包含period配置的值。
disable_reuse_security_policy
- 类型:
boolean - 默认值:
false - 是否必填:否
设置为true时,禁用防止 TOTP 验证码重放的安全策略。该策略是一项额外的安全措施:在验证码的有效窗口期内,同一个验证码(即同一个时间步长 step)不允许被使用两次。
源码中该策略在登录处理器中落地:在 internal/handlers/handler_sign_totp.go 处调用ctx.Providers.TOTP.Validate完成密码学校验后,若发现同一 step 已被使用过,会依据ctx.Configuration.TOTP.DisableReuseSecurityPolicy决定是仅记录警告还是直接拒绝认证(internal/handlers/handler_sign_totp.go)。配合 internal/model/totp_configuration.go 中的UpdateSignInInfo方法更新最近使用时间,从而实现防重放。该策略只会影响在有效期内被使用超过一次的验证码,正常的一次性使用不受影响,一般无需关闭。
注册机制(Registration)
当用户首次注册 TOTP 设备时,Authelia 会使用当前的issuer、algorithm、digits、period等配置生成 TOTP 链接(otpauth URI)和二维码,并将这些值一并保存到数据库中,供后续校验使用。
这意味着:之后即使修改了配置项,已注册用户的密钥也不会失效、无需重新注册。该功能自 4.33.0 版本起生效;在此之前的版本中,修改配置会导致旧密钥校验失败。
如果你希望强制某用户重新注册设备,无论是否修改了配置,都可以使用以下命令删除该用户的旧设备:
authelia storage user totp delete <username>从源码看,注册流程由 internal/handlers/handler_register_totp.go 中的两个处理器实现:
TOTPRegisterGET:返回当前允许的注册选项(算法、位数、时间步长的可选列表),数据来自ctx.Providers.TOTP.Options()(internal/handlers/handler_register_totp.go),对应 internal/totp/totp.go 的Options方法,其内部即NewTOTPOptionsFromSchema从配置映射出的TOTPOptions(internal/totp/totp.go)。TOTPRegisterPUT:接收用户在允许列表中选定的参数,调用GenerateCustom生成新的 TOTP 配置并入库。
GenerateCustom(internal/totp/totp.go)内部通过totp.Generate生成密钥:秘密字节使用secret_size指定长度、经 Base32 无填充编码,连同Issuer、AccountName(用户名)、Period、Digits、Algorithm一起构成 otpauth URI 与二维码。
输入校验(Input Validation)
period与skew两个参数会互相影响,共同决定验证码的有效时长。默认值组合为period=30、skew=1,官方强烈建议不要修改这两个参数,除非你确实想将skew设为0。
它们通过改变验证码的有效时间窗来影响安全性。有效时长的计算公式为:
有效时长 = period + (period × skew × 2)例如:
| period | skew | 有效时长 | 同时有效的验证码数 |
|---|---|---|---|
| 30 | 1 | 90 秒 | 3 |
| 30 | 2 | 150 秒 | 5 |
需要说明的是,虽然增大skew可以缓解客户端与服务端之间的时间偏差问题,但同时也拉长了验证码的可重放窗口,安全性随之下降。这也是默认skew=1且建议不要随意调大的原因。
系统时间准确性(System Time Accuracy)
TOTP 是基于时间的算法,因此服务器与客户端两侧的时间准确性都至关重要:如果服务器系统时间不够精确,客户端生成的验证码将看起来"永远不正确";反之亦然,客户端时间偏差同样会导致校验失败。
Authelia 默认在启动时会将系统时间与 NTP 服务器 进行比对(相关配置见ntp配置段),帮助规避服务器侧的时间同步问题。但对于客户端,目前没有有效且可靠的手段进行检查——这也是skew参数存在的意义之一:在合理范围内容忍轻微的时钟偏差。
加密与密钥导出(Encryption)
自4.33.0版本起,TOTP 密钥在数据库中以加密形式存储(加密密钥相关说明见 存储层介绍)。这样即使攻击者获得了数据库的完全访问权限,也无法轻易破解你的二次认证机制。
但加密存储也给"将 TOTP 密钥从 Authelia 迁移导出到其他服务"带来了不便。为此 Authelia 提供了专门的 TOTP 导出命令,这些命令要求提供完整配置,或至少包含存储后端连接信息与加密密钥的最小配置:
# 导出为 YAML 文件(默认文件名 authelia.export.totp.yml) authelia storage user totp export --file example.yml # 导出为 CSV authelia storage user totp export csv --file users.csv # 导出为 otpauth URI 列表 authelia storage user totp export uri # 导出为二维码 PNG 图片(输出到指定目录) authelia storage user totp export png --directory example/dir对应的命令实现与更多示例位于 internal/commands/storage.go 以及 internal/commands/const.go。完整的 CLI 文档参见 authelia storage user totp export。
此外,命令还支持为指定用户生成TOTP 密钥(可用于预置用户或测试):
authelia storage user totp generate john authelia storage user totp generate john --period 90 authelia storage user totp generate john --digits 8 authelia storage user totp generate john --algorithm SHA512 --config config.yml authelia storage user totp generate john --algorithm SHA512 --config config.yml --path john.png以及导入已导出的 TOTP 配置:
authelia storage user totp import authelia.export.totp.yml authelia storage user totp import --config config.yml authelia.export.totp.yml导出/导入的数据结构定义在 internal/model/totp_configuration.go:TOTPConfigurationDataExport以totp_configurations为顶层键承载配置列表,每条配置包含算法、位数、周期、issuer、用户名、Base32 密钥等字段。
校验流程与 Provider 实现
综合来看,TOTP 的运行时核心是 internal/totp/totp.go 中的TimeBased结构体,它实现了 internal/totp/provider.go 定义的Provider接口(Generate、GenerateCustom、Validate、Options):
- 初始化:
NewTimeBasedProvider从配置构造 provider,读取 issuer、默认算法、默认位数、默认周期、secret_size,并在skew >= 0时采用配置值、否则回退为1(internal/totp/totp.go)。 - 生成:
Generate/GenerateCustom依据用户选择(或默认)的算法、位数、周期生成密钥与 URI。 - 校验:
Validate使用数据库中保存的Period、Digits、Algorithm(而非当前配置)执行totp.ValidateCustomStep,skew 则取运行时配置(internal/totp/totp.go)。这正是"修改算法/位数/周期不影响已注册密钥、而修改 skew 影响所有校验"这一行为差异的根源。
配置层则遵循"Schema 定义默认值 → 校验器填充与纠错"的两段式处理:默认配置定义在 internal/configuration/schema/totp.go,校验与归一化逻辑见 internal/configuration/validator/totp.go,覆盖算法大写归一化、period 最小值、digits 合法值、secret_size 下限、allowed 列表自动包含默认值等规则,并通过 internal/configuration/validator/totp_test.go 中的表驱动测试逐一验证。
最佳实践小结
- 保持默认参数:
algorithm: sha1、digits: 6、period: 30、skew: 1是为了最大兼容性而选择的默认值,绝大多数 Authenticator 应用都支持该组合。 - 修改生成参数前先测试:如果必须修改算法或位数,务必确认用户使用的应用能真正完成认证(而非仅仅能添加密钥),参考已测试应用清单 TOTP 应用参考指南。
- 保持系统时间准确:启用 NTP 同步,避免服务器时钟漂移导致验证码大面积失效,相关配置见 NTP 文档。
- 不要轻易关闭防重放策略:
disable_reuse_security_policy保持默认false,以阻止验证码在有效窗口内被重放。 - 善用导出命令:需要迁移或备份 TOTP 密钥时,使用
authelia storage user totp export系列命令,并妥善保管加密密钥。
【免费下载链接】autheliaThe Single Sign-On Multi-Factor portal for web apps. OpenID Certified™ and Post-Quantum Cryptography Ready.项目地址: https://gitcode.com/GitHub_Trending/au/authelia
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考