定制 cesnet/simplesamlphp-module-authswitcher 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

cesnet/simplesamlphp-module-authswitcher

Composer 安装命令:

composer require cesnet/simplesamlphp-module-authswitcher

包简介

A SimpleSAMLphp module for applying 2FA modules to specific users

README 文档

README

maintenance status: end of life

This project has reached end of life, which means no new features will be added. Security patches and important bug fixes will end as of 2024. Check out Apereo CAS instead.

Description

Module for switching between different MFA modules and honoring + setting AuthnContextClassRef, both for IdP and proxy. Tested with PrivacyIDEA.

It is assumed that the auth source is password based, then secondary authentication (based on a token) is performed via this module. The following authentication contexts are supported for password (single factor) authentication:

The following authentication contexts are supported for multi-factor authentication:

Install

You have to install this module using Composer together with SimpleSAMLphp so that dependencies are installed as well.

The module is enabled by default.

The modules that are going to be controlled by authswitcher need to be installed separately.

Security consideration: It is assumed that none of the auth proc modules allows user to skip the verification in other way than using the method switching/skipping of this module. If there is such option, you need to disable it, otherwise users can bypass MFA while asserting the REFEDS MFA profile.

GetMfaTokensPrivacyIDEA auth proc filter

Use this filter to read user mfa tokens from PrivacyIDEA server to state attributes.

52 => [
    'class' => 'authswitcher:GetMfaTokensPrivacyIDEA',
    'config' => [
        'tokens_Attr' => 'privacyIDEATokens',
        'privacy_idea_username' => 'admin',
        'privacy_idea_passwd' => 'secret',
        //'privacy_idea_realm' => 'superadminrealm', // optional
        'privacy_idea_domain' => 'https://mfa.id.muni.cz',
        'tokens_type' => [
            'TOTP',
            'WebAuthn',
        ],
        'user_attribute' => 'eduPersonPrincipalName',
        'token_type_attr' => 'type',
        //'connect_timeout' => 10, // optional, connect timeout in seconds
        //'timeout' => 10, // optional, timeout in seconds
    ],
],

To enable caching of the privacyIDEA auth token, add:

    // ...
        'enable_cache' => true, // defaults to false
        'cache_expiration_seconds' => 30 * 60, // defaults to 55 minutes
    // ...

Use (configure as auth proc filter)

Add an instance of the auth proc filter with example configuration authswitcher:SwitchAuth:

54 => [
      'class' => 'authswitcher:SwitchAuth',
      'config' => [
          'type_filter_array' => [
              'TOTP' => 'privacyidea:PrivacyideaAuthProc',
              'WebAuthn' => 'privacyidea:PrivacyideaAuthProc',
          ],
          'token_type_attr' => 'type',
          'preferred_filter' => 'privacyidea:PrivacyideaAuthProc',
          'max_user_capability_attr' => 'maxUserCapability',
          'max_auth' => 'https://id.muni.cz/profile/maxAuth',
          'mfa_excluded_sps' => [
                [1] => 'example_entity_id1',
                [2] => 'example_entity_id2',
          ],
          'setup_mfa_redirect_url' => 'mfa.id.muni.cz',
          'remove_authn_context_class_ref_prefixes' => ['prefix1', 'prefix2']
          //'password_contexts' => array_merge(AuthSwitcher::PASSWORD_CONTEXTS, [
          //    'my-custom-authn-context-for-password',
          //    '/^my-regex-.*/',
          //]),
          //'mfa_contexts' => array_merge(AuthSwitcher::MFA_CONTEXTS, [
          //    'my-custom-authn-context-for-mfa',
          //]),
          //'contexts_regex' => true,
          //'entityID' => function($request){
          //    return empty($request["saml:RequesterID"]) ? $request["SPMetadata"]["entityid"] : $request["saml:RequesterID"][0];
          //},
      ],
      'configs' => [
            'totp:Totp' => [
                'secret_attr' => 'totp_secret',
                'enforce_2fa' => true,
                'skip_redirect_url' => 'https://simplesaml/module.php/authswitcher/switchMfaMethods.php',
            ],
            'webauthn:WebAuthn' => [
                'redirect_url' => 'https://webauthn/authentication_request',
                'api_url' => 'https://webauthn/request',
                'signing_key' => '/var/webauthn_private.pem',
                'user_id' => 'eduPersonPrincipalName',
                'skip_redirect_url' => 'https://simplesaml/module.php/authswitcher/switchMfaMethods.php',
            ],
            'privacyidea:PrivacyideaAuthProc' => [
                'privacyideaServerURL' => 'https://mfa.id.muni.cz',
                'realm'                => 'muni.cz',
                'uidKey'               => 'eduPersonPrincipalName',
                'sslVerifyHost'        => 'true',
                'sslVerifyPeer'        => 'true',
                'serviceAccount'       => 'admin',
                'servicePass'          => 'secret',
                'doEnrollToken'        => 'false',
                'tokenType'            =>  [
                    'webauthn',
                    'totp',
                ],
                'doTriggerChallenge'   => 'true',
            ],
        ],
    ],
// as a safety precausion, remove the "secret" attributes
54 => [
    'class' => 'core:AttributeAlter',
    'subject' => 'totp_secret',
    'pattern' => '/.*/',
    '%remove',
],

You can override which AuthnContextClassRefs are treated as password authentication (password_contexts) and MFA authentication (mfa_contexts). It is recommended to keep the contexts supported by default, e.g. by merging arrays. If you set contexts_regex to true and a value in one of these options is a regular expression (wrapped in /), all contexts matching the expression are matched (but the regular expression is never used as a response).

Use setup_mfa_redirect_url for redirecting user without MFA tokens to page, where he can register it. User is redirected when MFA is enforced and service is not excluded from this behaviour by mfa_excluded_sps configuration option.

It's possible to filter out some ACRS by using remove_authn_context_class_ref_prefixes. ACRS starting with some of configured prefix will be filtered out and will not be forwarded to IdP.

MFA tokens

This module expects that there will be a user attribute ($attributes aka $state['Attributes']) with key "mfaTokens" filled with the tokens registered by the supported 2FA modules (array of arrays).

example of mfaTokens:

[
    [
        "added"   => "2021-09-06 14:40:06",
        "revoked" => false,
        "secret"  => "topsecret",
        "userId"  => "43215",
        "type"    => "TOTP",
    ],
    [
        // ...
    ],
]

When MFA is run, if there is at least one MFA token which is not revoked and MFA should be done according to "mfaEnforceSettings" or MFA is preferred by SP (from AuthnContext), the SwitchAuth auth proc filter runs one of the configured supported 2FA modules, decided by type of user's MFA tokens. If more than one token types are available, the 2FA method is decided by device type (TOTP is preferred for mobile devices, WebAuthn for desktops and laptops).

If the user has multiple token types, it is possible to switch between them. The supported MFA modules redirect to switchMfaMethods.php, which checks authentication result and if MFA has not completed, it runs the next 2FA method filter.

Running in proxy mode

In proxy mode, you need to make a couple of changes.

First, set the proxy_mode configuration option to true:

53 => [
    'class' => 'authswitcher:SwitchAuth',
    'config' => [
        'proxy_mode' => true,
        // ...
    ],
    //...
]

If you want to modify password_contexts or mfa_contexts, move the contents of the config array into a new file called config/module_authswitcher.php. See config-templates/module_authswitcher.php for an example. If you do not want to modify these two options, you can keep the config inside the auth proc filter.

You also need to call DiscoUtils::setUpstreamRequestedAuthnContext($state) before the user is redirected to upstream IdP, e.g. in the discovery page's code, so that correct AuthnContext is sent to the upstream IdP.

If you only modified the requested AuthnContextClassRef by using the AuthnContextClassRef option in config/authsources.php, the login at upstream IdP will work, but authswitcher won't be able to process the originally requested AuthnContextClassRefs (because they would be overwriten by the config option).

The last but very important requirement is that you need to modify SimpleSAMLphp by including this patch: https://github.com/simplesamlphp/simplesamlphp/pull/833/files which adds support for passing AuthnContextClassRef to upstream IdP and getting the returned one. To enable the patch, add 'proxymode.passAuthnContextClassRef' => true, to your config/config.php.

Enforce MFA per user

If a user should only use MFA, set mfaEnforceSettings user attribute to {"all":true}. You can fill this attribute any way you like, for example from LDAP or from a database.

If the user has no MFA tokens and mfaEnforceSettings is non-empty, it is ignored (to prevent lock-outs).

When the attribute is not empty, multi-factor authentication is always performed. Because it is assumed that the first factor is always password based, when a SP requests https://refeds.org/profile/sfa or PasswordProtectedTransport specifically, MFA is performed but one of the requested authentication contexts is returned.

When used with proxy mode, MFA is not forced if it was already done at upstream IdP.

Enforce MFA per user per service

If some user should use MFA for some services, set mfaEnforceSettings user attribute to one of the following JSON-encoded object types:

  • {"all":true} to force MFA for all services
  • {"include_categories":["category1","category2"]} to force MFA for all services from the listed categories
  • {"include_categories":["category1","category2"],"exclude_rps":["entityID1","entityID2"]} to force MFA for all services from the listed categories except services with entity ID entityID1 and entityID2

For this to work, you must also fill the rpCategory user attribute with the appropriate category. If this attribute is empty, the service is assumed to belong to a category named "other".

By default, entity ID is read from the metadata of the current SP. You can override this by specifying the entityID config option to either a string (which is used as is) or a callable in the form function getEntityID($state){return "str";}. See example configs for more.

Add additional attributes when MFA is performed

To add attributes only if MFA was performed, you can use a filter called AddAdditionalAttributesAfterMfa. This filter sets attributes based on whether MFA was in fact performed (at upstream IdP or locally) - not based on whether MFA is in the response AuthnContext.

AddAdditionalAttributesAfterMfa needs to run after the SwitchAuth filter.

In configuration, you just need to add a custom_attrs option which contains a map of additional attributes and their values.

55 => [
    'class' => 'authswitcher:AddAdditionalAttributesAfterMfa',
    'config' => [
        'custom_attrs' => [
            'attr1' => ['value1'],
            'attr2' => ['value2'],
            // ...
        ],
        // ...
    ],
    //...
]

Password entropy check

Without check, it is assumed that user password fulfill REFEDS SFA. If the check should be performed, set check_entropy to true. Also set sfa_alphabet_attr and sfa_len_attr configuration options, which represent names of attributes in $state. It is assumed that MFA always satisfies REFEDS SFA, that it contains TOTP, WebAuthn, or similar user verification. Therefore, there are two scenarios for a user with weak password. User with configured MFA must perform MFA, and user without configured MFA will be redirected to a page with additional information and with configurable button which leads to a password reset. Use change_weak_password_urls to configure redirect button.

sfa_alphabet represents number of characters which can be used in password

sfa_len represents length of password

54 => [
    'class' => 'authSwitcher:SwitchAuth',
    'config' => [
        'check_entropy' => true,
        'sfa_alphabet_attr' => 'sfa_alphabet',
        'sfa_len_attr' => 'sfa_len'
        'change_weak_password_urls' => [
            'en' => 'https://example.org/en/change_password',
            'cs' => 'https://example.org/cs/zmena_hesla',
        ],
        //...
    ]
]

Copyright

© 2017-2022 Pavel Břoušek, Institute of Computer Science, Masaryk University and CESNET, z. s. p. o. All rights reserved.

cesnet/simplesamlphp-module-authswitcher 适用场景与选型建议

cesnet/simplesamlphp-module-authswitcher 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 8.99k 次下载、GitHub Stars 达 0, 最近一次更新时间为 2022 年 01 月 27 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 cesnet/simplesamlphp-module-authswitcher 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 cesnet/simplesamlphp-module-authswitcher 我们能提供哪些服务?
定制开发 / 二次开发

基于 cesnet/simplesamlphp-module-authswitcher 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 8.99k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 5
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: BSD-3-Clause
  • 更新时间: 2022-01-27