simplesamlphp/simplesamlphp-module-webauthn

PHP实现的FIDO2 / WebAuthn身份验证代理

安装: 822

依赖: 0

建议者: 0

安全: 0

星标: 15

关注者: 10

分支: 8

开放问题: 2

类型:simplesamlphp-module

v2.1.1 2023-09-20 14:55 UTC

README

Build Status Coverage Status Scrutinizer Code Quality Type Coverage Psalm Level

该模块实现为身份验证处理过滤器。这意味着它可以在全局config.php文件或SP远程或IdP托管元数据中进行配置。

安装

您可以使用composer安装此模块

% composer require simplesamlphp/simplesamlphp-module-webauthn

如果您使用的是PHP 7,则需要安装GMP扩展(推荐)或BCMath扩展。

如何将webauthn模块设置为第二因素(authprocfilter)

您需要启用模块的authprocfilter并在优先级级别上,以便它在第一因素认证之后进行。例如,在100,如果使用独立的注册和name2oid,那么WebAuthn auth proc过滤器必须在name2oid之后运行。

authproc过滤器接受一些可选参数,以控制哪些用户将被强制进行双因素认证。

100 => [
    'class' => 'webauthn:WebAuthn',

    /* should FIDO2 be enabled by default for all users? If not, users need to
     * be white-listed in the database - other users simply pass through the
     * filter without being subjected to 2FA.
     *
     * defaults to "disabled by default" === false
     */
    'default_enable' => false,

    /* only if default_enable is false:
     * the toggle to turn on 2FA can either be a database lookup in the module's
     * internal database or be dependent on the existence or absence of a
     * user attribute as retrieved in the first-factor auth. The following
     * options control which variant to use.
     */

    /*
     * this parameter determines if the database will be used to check
     * whether to trigger second factor authentication or use the "attrib_toggle" instead.
     * Default value of this attribute is true
     */
    'use_database' => true,

    /* this parameter is used only if "use_database" is false. If the value of
     * "force" is true then we trigger WebAuthn only if "attrib_toggle" from the
     * user is not empty. If the value of "force" is false then we switch the value of
     * "default_enable" only if "attrib_toggle" from the user is not empty.
     * Default falue is true.
     */
    'force' => true,

    /* this parameter stores the name of the attribute that is sent with user and which
     * determines whether to trigger WebAuthn.
     * Default value is 'toggle'
     */
    'attrib_toggle' => 'toggle',

    /**
     * The module can be configured to assert that MFA was executed towards the
     * SP by setting an appropriate <AuthnContextClassRef> tag in the response.
     * The original SAML 2.0 spec in that regard contains only contexts which
     * are rather useless in a FIDO2 context.
     *
     * FIDO alliance has its own to indicate that a FIDO key was used, and it
     * is the default if unset. The semantics does not indicate then that an
     * additional authentication besides the FIDO key was used (i.e. your
     * first-factor authsource authentication). Thus, you may want to consider
     * setting the more accurate REFEDS identifier below instead.
     *
     * Defaults to 'urn:rsa:names:tc:SAML:2.0:ac:classes:FIDO' if not set
     *
     * If you authenticate towards Microsoft 365 SPs which may trigger their
     * own variant of 2FA, then you can tell them to skip this by
     * - setting the SP tenant parameter "supportsMFA" to "true"
     * - returning the AuthnContextClassRef
     *   "http://schemas.microsoft.com/claims/multipleauthn"
     */

    // 'authncontextclassref' => 'https://refeds.org/profile/mfa',
],

然后您需要将config-templates/module_webauthn.php复制到您的配置目录,并相应地调整设置。请参阅文件以了解参数描述。

如何设置(纯)无密码认证

在无密码模式下,模块提供了一个AuthSource,在simpleSAMLphp的config/authsources.php中进行配置,就像通常一样。

用户的FIDO2密钥需要与“无密码”复选框一起注册 - 这会触发与密钥本身内在的第二因素强制注册(指纹、面部识别、交易PIN等)。

由于认证发生在用户名已知之前,因此此认证源需要很少的配置 - 因此不可能进行特定用户的配置。

该认证源在authsources.php中接受以下参数

'name-your-source' => [
    'webauthn:Passwordless',
    /*
     * Defaults to 'urn:rsa:names:tc:SAML:2.0:ac:classes:FIDO' if not set
     *
     * If you authenticate towards Microsoft 365 SPs which may trigger their
     * own variant of 2FA, then you can tell them to skip this by
     * - setting the SP tenant parameter "supportsMFA" to "true"
     * - returning the AuthnContextClassRef
     *   "http://schemas.microsoft.com/claims/multipleauthn"
     */

    // 'authncontextclassref' => 'https://refeds.org/profile/mfa',
],

如何同时设置无密码和传统的双因素

在此模式下,认证提示同时允许触发无密码认证或输入用户名/密码作为传统的第一因素。

配置几乎与上面的无密码相同,但需要一个额外的必需配置参数:如果用户提供了用户名/密码,则应使用该认证源进行验证。

该认证源在authsources.php中接受以下参数

'name-your-source' => [
    'webauthn:Supercharged',
    'password_authsource' => 'whatever-authsource',
    // 'authncontextclassref' => 'https://refeds.org/profile/mfa',

],

使用存储

数据库模式在首次使用时自动设置。该模式可在src/WebAuthN/Store/Database.php (__construct)中找到。

如果您想限制数据库用户的权限,以下是需要的最小权限集

GRANT SELECT,INSERT,UPDATE,DELETE ON ...credentials TO '...dbuser'@'1.2.3.4' IDENTIFIED BY '...dbpass';


GRANT SELECT ON ...userstatus TO '...dbuser'@'1.2.3.4' IDENTIFIED BY '...dbpass';

webauthn:Database后端存储具有以下选项

class : 必须设置为webauthn:Database

database.dsn : 数据源名称必须符合PHP PDO层的语法。

database.username : 用于连接的数据库用户名。

database.password : 用于连接的数据库用户的密码。

timeout : 等待连接到数据库服务器的时间(秒数)。此选项是可选的。如果未设置,则使用数据库驱动程序的默认值。

使用PostgreSQL数据库的示例配置

100 => [
    'class' => 'webauthn:WebAuthn',
    'store' => [
        'webauthn:Database',
        'database.dsn' => 'pgsql:host=sql.example.org;dbname=fido2',
        'database.username' => 'simplesaml',
        'database.password' => 'sdfsdf',
    ],
],

使用MySQL数据库的示例配置

100 => [
    'class' => 'webauthn:WebAuthn',
    'store' => [
        'webauthn:Database',
        'database.dsn' => 'mysql:host=db.example.org;dbname=fido2',
        'database.username' => 'simplesaml',
        'database.password' => 'sdfsdf',
    ],
],

选项

auth proc过滤器的选项

default_enable : WebAuthn是否默认对所有用户启用?如果不是,则需要在数据库中列出用户 - 其他用户只需通过过滤器,而不受双因素认证的影响。默认为“默认禁用”=== false

force : 当 "use_database" 为 false 时才使用此参数。如果 "force" 的值为 true,则只有当用户提供的 "attrib_toggle" 不为空时才触发 WebAuthn。如果 "force" 的值为 false,则只有当用户提供的 "attrib_toggle" 不为空时才切换 "default_enable" 的值。默认值为 true。

attrib_toggle : 此参数存储与用户一起发送的属性名称,并决定是否触发 WebAuthn。默认值为 'toggle'。

use_database : 此参数确定是否使用数据库来检查是否触发二次因素认证,或使用 "attrib_toggle"。此属性的默认值为 true。

module_webauthn.php 中的选项

scope : FIDO2 通过将生成的凭据绑定到作用域来防止钓鱼攻击。浏览器只有在作用域与用户当前访问的主域名匹配时才会调用注册/认证。如果没有指定,作用域将是 IdP 的主机名,如其元数据所示。但可以将作用域扩展到主域名(例如,认证服务是 "saml.example.com" 则作用域可以扩展到 "example.com";但不能是 "examp1e.com"。注册的 FIDO2 令牌也可以在其他同一域名的服务器上使用。在配置此项目时,请确保认证服务器名称和所需的作用域是后缀匹配。

registration / use_inflow_registration : 可选参数,用于确定在认证过程中是否可以注册和管理令牌,或者是否要使用独立注册页面进行这些目的。如果设置为 false 则为独立注册页面,如果设置为 true 则为流入注册。如果没有明确设置此参数,则默认为 true。

registration / auth_source : 可选参数,用于定义用户如何对专用注册页面进行认证。默认为 "default-sp";如果已配置流入注册,则忽略。

registration / policy_2fa / minimum_certification_level : 必要参数,指定注册所需的 FIDO 认证级别,允许的值

  • CERTIFICATION_NOT_REQUIRED - 不检查证明
  • FIDO_CERTIFIED_L1 - FIDO L1 认证
  • FIDO_CERTIFIED_L1plus - FIDO L1+ 认证
  • FIDO_CERTIFIED_L2 - FIDO L2 认证
  • FIDO_CERTIFIED_L3 - FIDO L3 认证
  • FIDO_CERTIFIED_L3plus - FIDO L3+ 认证

registration / policy_2fa / aaguid_whitelist : 可选的 AAGUID 列表,这些 AAGUID 将从最低认证级别检查中排除。默认为空列表。当 minimum_certification_level 设置为 CERTIFICATION_NOT_REQUIRED 时,忽略。

registration / policy_2fa / attestation_format_whitelist : 可选的证明格式列表,这些证明格式将从中排除最低认证级别检查。默认为空列表。当 minimum_certification_level 设置为 CERTIFICATION_NOT_REQUIRED 时,忽略。

registration / policy_passwordless / minimum_certification_level : 必要参数,与 registration / policy_2fa / minimum_certification_level 的意义相同,但用于无密码认证

registration / policy_passwordless / aaguid_whitelist : 可选参数,与 registration / policy_2fa / aaguid_whitelist 的意义相同,但用于无密码认证

registration / policy_passwordless / attestation_format_whitelist : 可选参数,与 registration / policy_2fa / attestation_format_whitelist 的意义相同,但用于无密码认证

用户体验 / 工作流程

对于已启用 WebAuthn 的用户,如果没有 FIDO2 令牌则无法继续。UI 根据用户已注册的令牌数量不同而有所不同

  • 用户有0个令牌:UI要求用户注册令牌。用户可以选择一个方便的名称来识别令牌。如果设置了request_tokenmodel,则名称将附加令牌模型和供应商。注册成功后,authprocfilter执行完成(用户继续到SP)
  • 用户有1个令牌:UI要求用户进行身份验证。身份验证后,用户可以选择注册另一个令牌。
  • 用户有2个或更多令牌:UI要求用户进行身份验证。身份验证后,用户可以选择注册另一个令牌或删除一个过时的令牌。

如果用户启用但忘记了所有令牌,他需要联系管理员,并将账户暂时禁用以进行双因素身份验证。

只要用户账户有0个令牌,就没有任何好处;实际上它仍然是单因素认证,因为任何拥有用户密码的人都可以注册任何令牌。这是事物的本质。可以通过带外注册过程(在相同范围内)来避免。

如果使用独立注册页面,用户在登录时不能选择性地注册和管理令牌。独立注册页面可以在<basedir>module.php/webauthn/registration下找到,它需要身份验证(使用auth source registration_auth_source),然后您将被重定向到可以管理令牌的页面。

设备型号检测

可以使用选项registration / minimum_certification_level来获取令牌的所谓AAGUID,它唯一地标识模型和制造商(它不是序列号)。然后,您可以做出关于某些认证器模型可接受性的决定。

通过(或不)具有AAGUID的元信息将AAGUID映射到明文模型和制造商名称。FIDO联盟运营一个元数据服务(MDS),其中注册了许多AAGUID。然而,制造商不必将其AAGUID和元数据提交给该MDS,实际上,一些制造商缺失。

该模块包含从FIDO MDS中检索到的AAGUID和相关元数据的完整列表。此列表在config/webauthn-aaguid.json文件中,并且需要将该文件移动到您的SimpleSAMLphp配置目录。

如果您认为可能有新模型被列出,则可以手动更新此文件。为此,运行如下所示的bin/updateMetadata.php脚本

% php bin/updateMetadata.php <blob file>

其中<blob file>是从这里获取的元数据JWT blob。

因此,根据用户使用的令牌模型,即使AAGUID作为注册过程的一部分发送,设备也可能仍然存储为未知模型/未知供应商。

我联系了FIDO联盟,询问他们在MDS中信息不完整的问题。据称,在未来的FIDO认证中,MDS的列出可能会成为强制性。在此之前,没有好的解决方案来解决这个问题。

禁用WebAuthn

您可以通过不将其列为authprocfilter来完全禁用该模块。

您可以通过设置default_enable = false来默认禁用该模块。然后,您可以通过将状态为"FIDO2Enabled"的用户添加到userstatus表来为单个用户启用WebAuthn第二因素身份验证,或者如果您不想使用userstatus表,您可以为此发送一个存储在attrib_toggle中的名称。

如果模块默认启用,您可以有选择地禁用WebAuthn第二因素身份验证,通过将状态为FIDO2Disabled的用户名添加到userstatus表,或者如果您不想使用userstatus表,您可以为此发送一个存储在attrib_toggle中的名称。

限制/设计决策

此实现不验证令牌绑定,如果由身份验证器发送(§7.1 步骤 7 / §7.2 步骤 11 跳过令牌绑定信息验证,如果存在)。这是因为 Yubikeys 不支持令牌绑定,因此相应的功能没有测试用例。

用户出现和用户验证两种变体都足够成功地在双因素认证场景中进行认证(§7.1 步骤 11 和 12 合并为一个条件)。模块在凭证数据库中记录在注册时使用的是哪一个,并在认证期间不允许降级。无密码认证在注册和认证事务中始终需要用户验证。

此实现请求并支持 ECDSA 和 RSA 密钥(算法 -7,-257)。

此实现不请求任何客户端扩展。规范为实施提供了政策选择,即如果客户端发送扩展怎么办:此实现选择失败注册/认证。

此实现支持以下证明格式:

  • "none"(无证明)
  • "packed / x5c"(打包证明,X.509 证书)
  • "packed / self"(打包证明,自我证明)
  • "fido-u2f"(FIDO U2F 证明)
  • "apple"(苹果匿名证明)
  • "android-key"(Android 9 及以上版本使用 Keymaster 4 的 Android 密钥证明)其他证明格式会导致注册失败。

对于“packed / x5c”证明类型:

  • 不执行可选的 OCSP 检查(这是由于 FIDO MDS 中其他撤销检查手段而在规范中明确允许的)。

对于“packed / x5c”和“fido-u2f”:

  • 所有证明都被分类为“基本”(即没有“AttCA”级别);即不执行 §7.1 步骤 18 的验证。
  • 关于 §7.1 步骤 21:当配置了最低认证级别时,“自我”和“基本”证明级别被认为是可接受的;“无”不可接受。

如果实现检测到物理对象克隆的迹象(未增加签名计数器),则它将遵循失败认证的政策。