Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
en:shibidp:plugin-fudiscr [2022/06/20 10:00] – [WebAuthn (experimental)] hofmann@fu-berlin.deen:shibidp:plugin-fudiscr [2024/11/18 10:07] (current) – Update english page for new fudiscr docs hardtl01@fu-berlin.de
Line 2: Line 2:
  
 ===== General ===== ===== General =====
 +The plugin can be used as an additional factor for Multi-Factor Authentication (MFA) by the [[https://shibboleth.atlassian.net/wiki/spaces/IDP5/overview|Shibboleth Identity Provider (IdP)]].
 +It supports token-based authentication and fundamentally follows the Challenge-Response pattern.
 +A username is determined as a basis from one of the previous factors in the MFA sequence.
 +A common case is a preceding authentication with username and password against LDAP using the authn/Password-Flow.
  
-This plugin can be used as an additional factor for multi-factor authentication (MFA) by the [[https://shibboleth.atlassian.net/wiki/spaces/IDP4/overview|Shibboleth Identity Provider (IdP)]]. +The plugin itself has no functions for token management. 
-It supports token-based authentication and at its core follows the challenge-response pattern+It also contains no special algorithms for token validation. 
-The username has to be determined by one of the previous factors in the MFA chain. +A token system can be connected via a generic ChallengeResponseClientInterface. 
-A common use-case is the preceding authentication with username/password against an LDAP using the authn/password flow.+The plugin already includes an implementation of this interface for [[https://edumfa.io/|eduMFA]] and [[https://www.privacyidea.org/|privacyIDEA]]. 
 +Additionally, a rudimentary mockup implementation for testing is included. 
 +An external implementation for [[https://www.fortinet.com/de/products/identity-access-management/fortiauthenticator|Fortinet]] also already exists
 +The primary development work was carried out by Steffen Hofmann from the [[https://www.fu-berlin.de|Free University of Berlin]]. 
 +He is an employee of the Computing Center [[https://www.zedat.fu-berlin.de|(FUB-IT)]] and responsible for the Identity Management area. The Identity Management System of the Free University of Berlin is called FUDIS (FU Directory and Identity Service). For this reason, the abbreviation fudiscr is used in configuration parameters for the Challenge-Response-Plugin.
  
-The plugin itself does not contain functions for token administration nor special algorithms for validating tokens. +With versions 1.4.0/2.0.0, a collaboration in the area of [[https://fidoalliance.org/passkeys/|Passkeys]] with the [[https://www.hm.edu|Munich University of Applied Sciences]] was established. From these versions onward, the plugin contains an additional authentication method called fudispasskeys. Instead of two-step authentication using e.g., username/password and token validation with fudiscr, a single authentication with [[https://fidoalliance.org/passkeys/|Passkeys]] can be performed.
-An external token system can be connected via the generic ChallengeResponseClientInterface. +
-An implementation of this interface for [[https://www.privacyidea.org/|privacyIDEA]] is included as well as +
-mock-up implementation for testing purposes. +
-Also an external implementation for Fortinet already exists.+
  
  
-So far the development has been done by Steffen Hofmann of [[https://www.fu-berlin.de|Freien Universität Berlin]]He is an employee at the university's IT department [[https://www.zedat.fu-berlin.de|(ZEDAT – Zentraleinrichtung für Datenverarbeitung)]] and in charge of identity managementBecause the identity management at FU is called FUDIS (FU Directory and Identity Service), for the challenge-response plugin the name 'fudiscr' is used for configuration parameters, etc. +===== Versions for Shibboleth Identity Provider v4 ===== 
-In the future the support for the plugin will be provided by [[https://www.fu-berlin.de|Freie Universität Berlin]].  +<alert type="warning">End of life since 09/01/2024</alert> 
-In case this can no longer be ensured by the university anymore, partner organizations will ensure it.+^ Plugin Version ^ IdP Version            ^ eduMFA Version ^ privacyIDEA Version ^ Support Level               ^ 
 +| 1.0.0          min4.1.2 and < 4.3.0 | N/A            | min3.7            | no longer use               | 
 +| 1.1.0          min. 4.1.and < 4.3.0 | N/A            | min. 3.7            | no longer use               | 
 +| 1.1.1          | min. 4.1.2 and < 4.3.0 | N/A            | min3.7            | no longer use               | 
 +1.2.0          | min. 4.1.2 and < 4.3.0 | N/A            | min. 3.7            | no longer use               | 
 +| 1.3.0          | min. 4.3.0 and < 5.0.0 | N/A            | min. 3.7            | no longer use               | 
 +| 1.4.0          | min. 4.3.0 and < 5.0.0 | min. 2.0.0     | min. 3.9.2          | no longer use               |
  
-===== Prerequisites ===== +===== Versions for Shibboleth Identity Provider v5 ===== 
-Installation of privacyIDEA: https://gitlab.daasi.de/training/privacyidea+^ Plugin Version ^ IdP Version            ^ eduMFA Version ^ privacyIDEA Version ^ Support Level               ^ 
 +| 2.0.0          | min. 5.0.0             | min. 2.0.0     | min. 3.9.2          | no longer use               | 
 +| 2.1.0           | min. 5.1.0            | min. 2.0.0     | min. 3.9.2          | current                     |
  
-===== Supported token methods from privacyIDEA ===== +===== Supported Token Methods from eduMFA and privacyIDEA ===== 
-Currently the following token methods from privacyIDEA ([[https://privacyidea.readthedocs.io/en/latest/tokens/tokentypes.html|Token types in privacyIDEA]]) are supported: +Currentlythe following token methods from eduMFA ([[https://edumfa.readthedocs.io/en/latest/tokens/tokentypes.html|Token types in eduMFA]]) and privacyIDEA ([[https://privacyidea.readthedocs.io/en/latest/tokens/tokentypes.html|Token types in privacyIDEA]]) are supported: 
-  Email +^ Token Method          ^ Type Designation in Plugin  ^ min. Plugin Version ^ Limitations / Notes                                       ^ 
-  HOTP Token +Email                | mail                        | 1.0.0                                                                        | 
-  Indexed Secret Token +HOTP Token           | hotp                        | 1.0.0                                                                        | 
-  mOTP Token +Indexed Secret Token | indexed_secret              | 1.0.0                                                                        | 
-  Paper Token (PPR) +mOTP Token           | motp                        | 1.0.0                                                                        | 
-  Questionnaire Token (Limitation: //If only one answer is requested per directive.//) +Paper Token (PPR)    | indexed_tan                 | 1.0.0                                                                        | 
-  SMS Token +Questionnaire Token  | question                    | 1.0.0               | Only one answer may be required by policy              | 
-  TAN Token +| Registration         | registration_code           | 1.3.0                                                                        | 
-  TOTP +| Remote               //referenced token type//   | 1.3.0               | Only referenced tokens of type //Email//, //HOTP Token//, //mOTP Token//, //Paper Token (PPR)//, //Registration//, //SMS Token//, //TAN Token, TOTP//, //Yubico// and //Yubikey// are supported. | 
-  WebAuthn (from version 1.2.0)+SMS Token            | sms                         | 1.0.0                                                                        | 
 +| Spass                | simple_pass_token           | 1.4.0 / 2.0.0                                                                | 
 +TAN Token            | tan                         | 1.0.0                                                                        | 
 +TOTP                 | totp                        | 1.0.0                                                                        | 
 +WebAuthn             | web_authn                   1.2.0               |                                                          | 
 +| Yubico               | yubico_otp                  | 1.3.0                                                                        | 
 +| Yubikey              | yubikey_aes                 | 1.3.0                                                                        |
  
-Support of //Push Token// is currently in development.+===== Preliminary Work in the Token Management System ===== 
 + 
 +==== eduMFA ==== 
 +see [[de:shibidp:plugin-fudiscr:edumfa_setup|Installation and Configuration of eduMFA]] 
 + 
 +==== privacyIDEA ==== 
 +see [[de:shibidp:plugin-fudiscr:privacyidea_setup|Installation and Configuration of privacyIDEA]]
  
 ===== Installation ===== ===== Installation =====
  
-The plugin can be used with Shibboleth IdP version >= 4.1.2.+==== Activation of MFA Module ==== 
 +The fudiscr plugin requires the MFA module. This should be activated as follows: 
 +<code> 
 +%{idp.home}/bin/module.sh -e idp.authn.MFA 
 +</code> 
 +With the MFA module, the configuration file ''%{idp.home}/conf/authn/mfa-authn-config.xml'' is also stored.
  
-Installation and updates are done via the Shibboleth plugin mechanism (see official docs [[https://shibboleth.atlassian.net/wiki/spaces/IDP4/pages/1294074003/PluginInstallation|PluginInstallation]])+(see also [[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199505534/MultiFactorAuthnConfiguration|Shibboleth-IdP MultiFactorAuthnConfiguration]]) 
 +\\
  
 +==== Installation of fudiscr Plugin ====
 +The installation and updates are performed via the Shibboleth Plugin mechanism (see official documentation [[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199500688/PluginInstallation|PluginInstallation]])
  
-**Warning:** The Shibboleth Identity Provider will restart after plugin installation.+**Attention:** The Shibboleth Identity Provider automatically performs a restart after plugin installation.
  
-Plugin is installed using the following command:+The plugin is installed and activated with the following command:
 <code> <code>
 %{idp.home}/bin/plugin.sh -i https://identity.fu-berlin.de/downloads/shibboleth/idp/plugins/authn/fudiscr/current/fudis-shibboleth-idp-plugin-authn-fudiscr-current.tar.gz %{idp.home}/bin/plugin.sh -i https://identity.fu-berlin.de/downloads/shibboleth/idp/plugins/authn/fudiscr/current/fudis-shibboleth-idp-plugin-authn-fudiscr-current.tar.gz
 </code> </code>
  
-Future updates can be installed like this:+Future updates will be automatically installed with the following command:
 <code> <code>
 %{idp.home}/bin/plugin.sh -u de.zedat.fudis.shibboleth.idp.plugin.authn.fudiscr %{idp.home}/bin/plugin.sh -u de.zedat.fudis.shibboleth.idp.plugin.authn.fudiscr
 </code> </code>
  
-For unattended installations the PGP keys can be downloaded upfront and supplied on installation like this:+For a fully automatic installation, the PGP keys can be downloaded in advance and specified during installation:
 <code> <code>
 wget -O %{idp.home}/PGP_KEYS_FUDIS https://identity.fu-berlin.de/downloads/shibboleth/idp/plugins/PGP_KEYS wget -O %{idp.home}/PGP_KEYS_FUDIS https://identity.fu-berlin.de/downloads/shibboleth/idp/plugins/PGP_KEYS
 %{idp.home}/bin/plugin.sh -i https://identity.fu-berlin.de/downloads/shibboleth/idp/plugins/authn/fudiscr/current/fudis-shibboleth-idp-plugin-authn-fudiscr-current.tar.gz --truststore %{idp.home}/PGP_KEYS_FUDIS %{idp.home}/bin/plugin.sh -i https://identity.fu-berlin.de/downloads/shibboleth/idp/plugins/authn/fudiscr/current/fudis-shibboleth-idp-plugin-authn-fudiscr-current.tar.gz --truststore %{idp.home}/PGP_KEYS_FUDIS
 </code> </code>
 +\\
  
-===== Configuration ===== +===== MFA Configuration ===== 
- +(For the REFEDS Multi-Factor Authentication Profile, see [[de:aai:refeds_authn_profiles_idp|REFEDS AuthN Profiles - Information for Identity Providers]])
-==== Connecting privacyIDEA ==== +
- +
-=== Adding a system user in privacyIDEA === +
- +
-The Shibboleth plugin communicates with privacyIDEA by its API. The following three end points are used: +
- +
-  * /token/ (request a list of tokens) +
-  * /validate/triggerchallenge (initiate token challenge) +
-  * /validate/check (check an OTP, possibly in combination with a PIN) +
- +
-Therefore the user has to have sufficient rights to carry out all the actions that are triggered by those request and  +
-ideally no additional rights. +
- +
- +
-== Setting up an admin user == +
- +
-First we need to set up an admin user. It is recommended to set up a separate (administrative) realm as well in order to be able to differentiate between different types of rights for administrative users later on. The user account can be supplied by any external source and be imported by a resolver defined in PrivacyIdea. +
- +
-The setup of realms and resolvers os not part of this documentation but for the sake of simplicity and clarity we will set up the privacyIDEA internal user //idp-admin//+
- +
-<code> +
-pi-manage admin add idp-admin +
-</code> +
- +
-Furthermore we assume that the initial admin super user //admin// exists. +
- +
- +
-== Granting permissions == +
- +
-The required permissions are granted in privacyIDEA via policy. +
- +
-**Warning**: Admins in privacyIDEA get all permissions by default. +
-This holds as long as no admin policy is defined. +
-Once a policy is defined with scope  'admin', all admin users are restricted by the rights in this policy. +
-In case there is no admin policy yet, make sure not to lock yourself out of the Web UI. +
-That's why privacyIDEA informs you, if you define an admin policy, but the rights to edit policies are not granted in this (or any other) policy. +
- +
-At first we create the functionally required policy for the super user and assign it to user //admin//+
- +
-Then we add a new policy for our //idp-admin// user. +
- +
- +
-Therefore we create a new file //idp-admin-policy//, which contains parameters for the policy as a python dictionary. +
-The content should be like this: +
- +
-<code> +
-+
-  'action': {'tokenlist':True, 'triggerchallenge':True}, +
-  'active': True, +
-  'adminuser': ['idp-admin'], +
-  'name': 'idp-admin-policy', +
-  'scope': 'admin' +
-+
-</code> +
- +
-The policy can then be created by using the file template like this: +
- +
-<code> +
-pi-manage policy create -f idp-admin-policy name scope action +
-</code> +
- +
- +
-== Creating an API-Token == +
- +
-In order to successfully authenticate against the API an authorization token hast to be supplied. This token can be requested either by an API call to the //auth// endpoint or created by using //pi-manage//. By using the //pi-manage//-script you can create a token with an arbitrary expiry time in days (default 365). Tokens requested from the API are only valid for one hour. Therefore we use //pi-manage//: +
- +
-<code> +
-pi-manage api createtoken -r admin -u idp-admin +
-</code> +
- +
-=== Configuration of privacyIDEA === +
- +
-The connection to privacyIDEA is set up by the configuration options in ''%{idp.home}/conf/authn/fudiscr.properties'' +
- +
- +
-<file properties ./conf/authn/fudiscr.properties> +
-fudiscr.privacyidea.base_uri=<e.g. https://localhost> +
-fudiscr.privacyidea.authorization_token=<from previous step> +
- +
-#System user from previous step. Can be use to extend the authorization token: +
-#fudiscr.privacyidea.service_username= +
-#fudiscr.privacyidea.service_realm= +
-#fudiscr.privacyidea.service_password= +
- +
-#Realm which is added to the user by default: +
-#fudiscr.privacyidea.default_realm= +
- +
-#In case the server certificate should not be validated by the API, set this value to 'false" +
-#fudiscr.privacyidea.check_connection_certificate=true +
-</file> +
- +
-==== MFA configuration ==== +
-(For REFEDS Multi-Factor Authentication profile see [[de:aai:refeds_authn_profiles_idp|REFEDS AuthN Profiles - Hinweise für Identity Provider]] (in German)+
 \\ \\
- +The following settings need to be made in ''%{idp.home}/conf/authn/authn.properties'':
-To use this plugin with MFA, the MFA module itself has to be enabled in the Identity Provider. +
- +
-This is done by: +
-<code> +
-%{idp.home}/bin/module.sh -e idp.authn.MFA +
-</code> +
- +
-In ''%{idp.home}/conf/authn/authn.properties'' the following settings should be done:+
  
 <file properties ./conf/authn/authn.properties> <file properties ./conf/authn/authn.properties>
Line 184: Line 115:
  
 ''idp.authn.MFA.supportedPrincipals'' is already activated by default. ''idp.authn.MFA.supportedPrincipals'' is already activated by default.
-We only add the [[https://docs.oasis-open.org/security/saml/v2.0/saml-authn-context-2.0-os.pdf|AuthenticationContextClass]] ''saml2/urn:de:zedat:fudis:SAML:2.0:ac:classes:CR''+Only the [[https://docs.oasis-open.org/security/saml/v2.0/saml-authn-context-2.0-os.pdf|AuthenticationContextClass]] ''saml2/urn:de:zedat:fudis:SAML:2.0:ac:classes:CR'' is added
-Instead of ''saml2/urn:de:zedat:fudis:SAML:2.0:ac:classes:CR'' you can set a different or additional [[https://docs.oasis-open.org/security/saml/v2.0/saml-authn-context-2.0-os.pdf|AuthenticationContextClass]] +Instead of ''saml2/urn:de:zedat:fudis:SAML:2.0:ac:classes:CR'', another [[https://docs.oasis-open.org/security/saml/v2.0/saml-authn-context-2.0-os.pdf|AuthenticationContextClass]] 
-using ''idp.authn.fudiscr.supportedPrincipals'' AND ''idp.authn.MFA.supportedPrincipals''+or additional ones can be entered under ''idp.authn.fudiscr.supportedPrincipals'' AND ''idp.authn.MFA.supportedPrincipals''
-It is recommended to set at least one additional class by which the multi factor authentication can be triggered. +It is recommended to define at least one additional class through which multi-factor authentication can be explicitly triggered. 
-This is not mandatory because multi factor authentication might be triggered by other mechanisms as well.+However, there is no obligation, as multi-factor authentication can also be triggered through other mechanisms.
  
 +The sequence of individual factors is controlled via the transitions in ''%{idp.home}/conf/authn/mfa-authn-config.xml''.
 +Different mechanisms can be used here to formulate the conditions for transitions to the next factors.
 +You can find the official documentation here:
 +[[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199505534/MultiFactorAuthnConfiguration|MultiFactorAuthnConfiguration]]
  
-By using the transitions in ''%{idp.home}/conf/authn/mfa-authn-config.xml'' the order of the individual factors is specified. +==== MFA Configuration Examples ====
-You can use various mechanisms here to define conditions for transitions to the following factors.  +
-The official documentation can be found here: +
-[[https://shibboleth.atlassian.net/wiki/spaces/IDP4/pages/1265631610/MultiFactorAuthnConfiguration|MultiFactorAuthnConfiguration]]+
  
-=== Examples ===+Below are three examples of MFA configuration.
  
-Now we will look at three examples for MFA configuration. +**Example 1:** After authentication with username and password, token-based authentication with fudiscr always follows.
- +
-**Example 1**After authentication with username and password, token based authentication using fudiscr is done in any case.+
 <file xml ./conf/authn/mfa-authn-config.xml> <file xml ./conf/authn/mfa-authn-config.xml>
 <?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
Line 216: Line 146:
        default-destroy-method="destroy">        default-destroy-method="destroy">
  
-    <!-- most parts copied from https://shibboleth.atlassian.net/wiki/spaces/IDP4/pages/1265631610/MultiFactorAuthnConfiguration -->+    <!-- most parts copied from https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199505534/MultiFactorAuthnConfiguration -->
  
     <util:map id="shibboleth.authn.MFA.TransitionMap">     <util:map id="shibboleth.authn.MFA.TransitionMap">
Line 230: Line 160:
 </file> </file>
  
-**Example 2**After authentication with username and password we request a token based authentication using fudiscr if the AuthenticationContextClass required by the service provider is not sufficient.+**Example 2:** After authentication with username and passwordtoken-based authentication follows if the AuthenticationContextClass required by the ServiceProvider is insufficient.
 <file xml ./conf/authn/mfa-authn-config.xml> <file xml ./conf/authn/mfa-authn-config.xml>
 <?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
Line 246: Line 176:
        default-destroy-method="destroy">        default-destroy-method="destroy">
  
-    <!-- most parts copied from https://shibboleth.atlassian.net/wiki/spaces/IDP4/pages/1265631610/MultiFactorAuthnConfiguration -->+    <!-- most parts copied from https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199505534/MultiFactorAuthnConfiguration -->
  
     <util:map id="shibboleth.authn.MFA.TransitionMap">     <util:map id="shibboleth.authn.MFA.TransitionMap">
Line 278: Line 208:
 </file> </file>
  
-**Example 3**After authentication with username and password we request a token based authentication using fudiscr if the AuthenticationContextClass required by the service provider is not sufficient or if the user belongs to the group 'employeeaccording to eduPersonAffiliation. +**Example 3:** After authentication with username and passwordtoken-based authentication follows if the AuthenticationContextClass required by the ServiceProvider is insufficient or if the user belongs to the employee group according to eduPersonAffiliation.
 <file xml ./conf/authn/mfa-authn-config.xml> <file xml ./conf/authn/mfa-authn-config.xml>
 <?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
Line 295: Line 224:
        default-destroy-method="destroy">        default-destroy-method="destroy">
  
-    <!-- most parts copied from https://shibboleth.atlassian.net/wiki/spaces/IDP4/pages/1265631610/MultiFactorAuthnConfiguration -->+    <!-- most parts copied from https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199505534/MultiFactorAuthnConfiguration -->
  
     <util:map id="shibboleth.authn.MFA.TransitionMap">     <util:map id="shibboleth.authn.MFA.TransitionMap">
Line 346: Line 275:
 </file> </file>
  
-**Example 4**+**Example 4:** After authentication with username and passwordtoken-based authentication follows if the AuthenticationContextClass required by the ServiceProvider is insufficient or if the user already has at least one token. The token status is not checked. A blocked token would, for example, cause the ''fudiscr.UserHasTokenPredicate'' to return ''true''. This predicate was introduced specifically for rollout scenarios.
-<alert type="warning">version >=1.1.0</alert> +
-After authentication with username and password we request a token based authentication using fudiscr if the AuthenticationContextClass required by the service provider is not sufficient  +
-or if the user owns at least one token. The state of the tokens is not checked here, so a deactivated token would result in ''fudiscr.UserHasAnyTokenPredicate'' returning ''true''. This predicate +
-was introduced primarily for rollout scenarios. +
 <file xml ./conf/authn/mfa-authn-config.xml> <file xml ./conf/authn/mfa-authn-config.xml>
 <?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
Line 376: Line 300:
     </util:map>     </util:map>
  
-    <bean id="checkSecondFactor" parent="shibboleth.ContextFunctions.Scripted" factory-method="inlineScript" p:customObject-ref="fudiscr.UserHasAnyTokenPredicate">+    <bean id="checkSecondFactor" parent="shibboleth.ContextFunctions.Scripted" factory-method="inlineScript" p:customObject-ref="fudiscr.UserHasTokenPredicate">
         <constructor-arg>         <constructor-arg>
             <value>             <value>
Line 401: Line 325:
 </file> </file>
  
-=== Reuse Condition ===+\\
  
-For authentication methods on Shibboleth Identity Provider a //reuse condition// can be defined. +**Example 5:** Optional authn/Password and authn/SPNEGO as first factor -> [[de:aai:mfa_mit_passwd_spnego_first|here]].
-In general the default value is ''shibboleth.Conditions.TRUE'' which makes this condition be fulfilled in any case. +
-You can define your own functions as //reuse conditions//.+
  
-For multi factor authentication special rules apply. You can find a description in the official documentation: [[https://shibboleth.atlassian.net/wiki/spaces/IDP4/pages/1265631610/MultiFactorAuthnConfiguration|MultiFactorAuthnConfiguration]]+\\
  
-Using the following configuration you can achieve that username and password is requested only once inside a SSO session, but token based authentication is requested once on every service provider authentication.+=== Reuse Condition ===
  
 +A //Reuse Condition// can generally be defined for authentication procedures in the Shibboleth Identity Provider.
 +Usually, the default value is ''shibboleth.Conditions.TRUE''.
 +Thus, the condition is always fulfilled.
 +Custom functions can also be defined as //Reuse Conditions//.
 +
 +Special rules apply to multi-factor authentication. A description can be found in the official documentation under
 +[[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199505534/MultiFactorAuthnConfiguration|MultiFactorAuthnConfiguration]].
 +
 +With the following configuration in ''%{idp.home}/conf/authn/authn.properties'', you achieve that username and password are only requested once within a single sign-on session, but token-based authentication with fudiscr is required for each Service Provider authentication.
 <file properties ./conf/authn/authn.properties> <file properties ./conf/authn/authn.properties>
 idp.authn.MFA.reuseCondition=shibboleth.Conditions.FALSE idp.authn.MFA.reuseCondition=shibboleth.Conditions.FALSE
 idp.authn.Password.reuseCondition=shibboleth.Conditions.TRUE idp.authn.Password.reuseCondition=shibboleth.Conditions.TRUE
 idp.authn.fudiscr.reuseCondition=shibboleth.Conditions.FALSE idp.authn.fudiscr.reuseCondition=shibboleth.Conditions.FALSE
 +</file>
 +Accordingly, the MFA authentication result must not be reused, but within the multi-factor authentication, the existing successful result of the username-password authentication (//Password//) may be used, while the result of //fudiscr// may not.
 +<alert type="warning">It is recommended to set ''idp.authn.MFA.reuseCondition=shibboleth.Conditions.FALSE'' so that the logic in ''./conf/authn/mfa-authn-config.xml'' is executed for each authentication request. In the reuse case, for example, with an existing SSO session, it is not checked whether a user belongs to a specific affiliation.</alert>
 +<alert type="warning">
 +Special caution is required when using ''mfaCtx.isAcceptable()'' in connection with Reuse Conditions. This function does not consider Reuse Conditions. If a requested [[https://docs.oasis-open.org/security/saml/v2.0/saml-authn-context-2.0-os.pdf|AuthenticationContextClass]] has been previously fulfilled, the function returns ''true''.
 +<file xml>
 +<?xml version="1.0" encoding="UTF-8"?>
 +<beans ...>
 +    ... 
 +    <!-- 
 +        For example, if a second factor is requested with 'urn:de:zedat:fudis:SAML:2.0:ac:classes:CR',
 +        it will be requested for the first Service Provider.
 +        If 'idp.authn.MFA.reuseCondition=shibboleth.Conditions.FALSE' is set, 'checkSecondFactor' is always executed for additional Service Providers.
 +        However, the function 'mfaCtx.isAcceptable()' returns 'true' for subsequent Service Providers and the second factor is not requested again.
 +        'idp.authn.fudiscr.reuseCondition' is therefore ineffective at this point.
 +    -->
 +    <bean id="checkSecondFactor" parent="shibboleth.ContextFunctions.Scripted" factory-method="inlineScript">
 +        <constructor-arg>
 +            <value>
 +                <![CDATA[
 +                    nextFlow = "authn/fudiscr";
 +            
 +                    authCtx = input.getSubcontext("net.shibboleth.idp.authn.context.AuthenticationContext");
 +                    mfaCtx = authCtx.getSubcontext("net.shibboleth.idp.authn.context.MultiFactorAuthenticationContext");
 +                    if (mfaCtx.isAcceptable()) {
 +                        nextFlow = null;
 +                    }
 +                    nextFlow;
 +                ]]>
 +            </value>
 +        </constructor-arg>
 +    </bean>
 +    ...
 +</beans>
 </file> </file>
  
-This means the result of the MFA authentication can not be reused. Inside of a multi factor authentication the existing successful result of the username/password authentication (//password//can be reusedbut the result of //fudiscr// can not.+The following example extends the previous example and forces the call of the second factor with fudiscr when it is requested via [[https://docs.oasis-open.org/security/saml/v2.0/saml-authn-context-2.0-os.pdf|AuthenticationContextClass]] 'urn:de:zedat:fudis:SAML:2.0:ac:classes:CR'
 +<file xml> 
 +<?xml version="1.0" encoding="UTF-8"?> 
 +<beans ...> 
 +... 
 +<!--  
 +     (The following extended logic can also be represented differently.) 
 +     If 'urn:de:zedat:fudis:SAML:2.0:ac:classes:CR' is requestedthen 'fudiscr' is always executed 
 +     and the Reuse Condition 'idp.authn.fudiscr.reuseCondition' is evaluated. 
 +     With 'idp.authn.fudiscr.reuseCondition=shibboleth.Conditions.FALSE', a token is requested for each Service Provider 
 +     that requires a second factor. With 'idp.authn.fudiscr.reuseCondition=shibboleth.Conditions.TRUE', 
 +     there is no difference in the login behavior for users compared to the previous example. 
 + --> 
 +    <bean id="checkSecondFactor" parent="shibboleth.ContextFunctions.Scripted" factory-method="inlineScript"> 
 +        <constructor-arg> 
 +            <value> 
 +                <![CDATA[ 
 +            nextFlow = "authn/fudiscr";
  
-<alert type="warning">It is recommended to set ''idp.authn.MFA.reuseCondition=shibboleth.Conditions.FALSE'' in case on every authentication request the logic in ''./conf/authn/mfa-authn-config.xml'' is gone throughIn the reuse case for instance during a valid SSO session, it is not checked whether a user has a certain affiliation.</alert>+            authCtx input.getSubcontext("net.shibboleth.idp.authn.context.AuthenticationContext"); 
 +            mfaCtx = authCtx.getSubcontext("net.shibboleth.idp.authn.context.MultiFactorAuthenticationContext"); 
 +            if (mfaCtx.isAcceptable()) { 
 +                AuthnContextClassRefPrincipal Java.type("net.shibboleth.idp.saml.authn.principal.AuthnContextClassRefPrincipal"); 
 +                refPrincipal = new AuthnContextClassRefPrincipal("urn:de:zedat:fudis:SAML:2.0:ac:classes:CR"); 
 +                rpCtx = authCtx.getSubcontext("net.shibboleth.idp.authn.context.RequestedPrincipalContext");
  
-==== Further Configuration ====+                if (rpCtx == null || !rpCtx.getRequestedPrincipals().contains(refPrincipal)) { 
 +                    nextFlow null; 
 +                } 
 +            }
  
-You can find further configuration options in ''%{idp.home}/conf/authn/fudiscr.properties''+            nextFlow; 
-This document might be of help [[https://identity.fu-berlin.de/downloads/shibboleth/idp/plugins/authn/fudiscr/doc/ChallengeResponseFlow.pdf|ChallengeResponseFlow.pdf]].+        ]]> 
 +            </value> 
 +        </constructor-arg> 
 +    </bean> 
 +    ... 
 +</beans> 
 +</file> 
 +</alert> 
 +When 'ForceAuthn' is requested via SAML, the function ''mfaCtx.isAcceptable()'' always returns ''false''. 
 +\\
  
-===== WebAuthn ===== +===== AuthenticationFlowDescriptor for fudiscr ===== 
-Starting from version 1.2.0 WebAuthn token can be used.+Each authentication method in the Shibboleth Identity Provider is based on an abstract Flow with an AuthenticationFlowDescriptor, see [[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199505085/AuthenticationConfiguration|AuthenticationConfiguration]].
  
-<alert type="warning"> +The properties of the AuthenticationFlowDescriptor are usually set for all flows in ''%{idp.home}/conf/authn/authn.properties''. As a templatethese are commented out in ''%{idp.home}/conf/authn/fudiscr.properties'' to be provided after plugin installation: 
-The fudiscr plugin offers some options which permit multiple selection of tokens. If multiple tokens are selected during login it is assumed that the parameters  +<file properties> 
-//rpId// (relying party Id), //challenge////userVerification// and //timeout// are identical.+#idp.authn.fudiscr.order=1000 
 +#idp.authn.fudiscr.nonBrowserSupported=true 
 +#idp.authn.fudiscr.passiveAuthenticationSupported=true 
 +#idp.authn.fudiscr.forcedAuthenticationSupported=true 
 +#idp.authn.fudiscr.proxyRestrictionsEnforced=%{idp.authn.fudiscr.forcedAuthenticationSupported:true} 
 +#idp.authn.fudiscr.proxyScopingEnforced=false 
 +#idp.authn.fudiscr.discoveryRequired=false 
 +#idp.authn.fudiscr.lifetime=%{idp.authn.defaultLifetime:PT1H} 
 +#idp.authn.fudiscr.inactivityTimeout=%{idp.authn.defaultTimeout:PT30M} 
 +#idp.authn.fudiscr.reuseCondition=shibboleth.Conditions.TRUE 
 +#idp.authn.fudiscr.activationCondition=shibboleth.Conditions.TRUE 
 +#idp.authn.fudiscr.subjectDecorator= 
 +#idp.authn.fudiscr.errorMessageFunction = DefaultPasswordErrorFunction 
 +#idp.authn.fudiscr.genericMessageID = authn 
 +#idp.authn.fudiscr.addDefaultPrincipals=true 
 +#idp.authn.fudiscr.trimUsernamePrincipal=true 
 +#idp.authn.fudiscr.lowercaseUsernamePrincipal=false 
 +#idp.authn.fudiscr.uppercaseUsernamePrincipal=false 
 +#idp.authn.fudiscr.supportedPrincipals= \ 
 +#    saml2/urn:de:zedat:fudis:SAML:2.0:ac:classes:CR 
 +</file> 
 +'idp.authn.fudiscr.supportedPrincipals' was already introduced in https://doku.tid.dfn.de/de:shibidp:plugin-fudiscr#mfa-konfiguration. 
 +\\
  
-If a user owns multiple active WebAuthn tokens and you set ''fudiscr.user_token_selection=multipleToken'' or ''fudiscr.user_token_selection=multipleTokenTypeGroup'' in ''%{idp.home}/conf/authn/fudiscr.properties'', +===== fudiscr Configuration ===== 
-you have to set ''fudiscr.privacyidea.single_trigger_challenges=false'' as well+ 
-</alert>+==== Note for older IdP configurations ==== 
 +If you maintain an IdP configuration from before version 4.1.0, please ensure that the file ''%{idp.home}/conf/idp.properties'' contains the following line at the beginning so that all ''.properties'' files below the ''%{idp.home}/conf'' folder (such as ''%{idp.home}/conf/fudiscr.properties'') are automatically read. 
 +<file properties> 
 +idp.searchForProperties=true 
 +</file> 
 + 
 +==== Configuration files ==== 
 +With the installation of the fudiscr plugin, the configuration file ''%{idp.home}/conf/authn/fudiscr.properties'' is created. Changes in this file usually only take effect after restarting the Identity Provider. 
 + 
 +Additionally, the configuration file ''%{idp.home}/conf/authn/fudiscr.xml'' is created. The configuration beans contained in this file are managed by the [[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199507931/ReloadableServices|ReloadableService]] mechanism of the Shibboleth Identity Provider (see also [[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199507931/ReloadableServices|ReloadableServices]]). 
 + 
 +The service can be reloaded as follows: 
 +<code> 
 +%{idp.home}/bin/reload-service.sh -id fudiscr.ConfigurationBeansService 
 +</code> 
 + 
 +Alternatively, the reload can be triggered by directly calling the URL and avoids errors from the wrapper in ''reload-service.sh''
 +<code> 
 +GET http(s)://[idp-base-url]/idp/profile/admin/reload-service?id=fudiscr.ConfigurationBeansService 
 +</code> 
 + 
 +Similar to the parameters for other [[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199507931/ReloadableServices|ReloadableServices]] from the Shibboleth Identity Provider, the following exist for the fudiscr plugin: 
 +<file properties> 
 +fudiscr.service.failFast=false 
 +fudiscr.service.checkInterval=PT0S 
 +fudiscr.service.resources=fudiscr.ConfigurationResources 
 +</file> 
 + 
 +If configuration changes in ''%{idp.home}/conf/authn/fudiscr.xml'' should be loaded automatically, set the check interval with ''fudiscr.service.checkInterval''. By default (PT0S), regular checking of the timestamp change of ''%{idp.home}/conf/authn/fudiscr.xml'' is disabled. 
 + 
 +==== General Configuration Options ==== 
 +The following general configuration options can be set via the configuration file ''%{idp.home}/conf/authn/fudiscr.properties''
 +^Option^Default Value^Description^ 
 +|''fudiscr.challengeResponseClient''|''EduMfaChallengeResponseClient''|This option determines which token backend should be addressed. Since version 2.1.0, the default value is ''EduMfaChallengeResponseClient'', previously ''PrivacyIdeaChallengeResponseClient''. There is also the possibility to use ''PrivacyIdeaChallengeResponseClient'' that works without a backend and writes all information as DEBUG messages to the log files when starting the IdP.| 
 +|''fudiscr.default_users_realm''|//empty//|If no realm can be determined from the username, this option can be used to set a realm that will be added when missing in the fudiscr plugin. In most cases, no realm is needed, so by default no realm is added.| 
 +|''fudiscr.filter_tokens.id_exclude_regex''|//empty//|This option can be used to exclude tokens based on their ID/serial number for use in the fudiscr plugin. For example, //^HOTP.*$// ignores all HOTP tokens that were created as software tokens in privacyIDEA and received a serial number starting with HOTP. By default, the filter is not used. The regular expression is not defined.| 
 +|''fudiscr.filter_tokens.type_exclude_regex''|//empty//|This option can be used to exclude token types for use in the fudiscr plugin. For example, //^totp$// ignores all TOTP tokens. By default, the filter is not used. The regular expression is not defined.| 
 +|''fudiscr.on_failed_restart_completely_mfa''|''shibboleth.Conditions.FALSE''|This [[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199508946/PredefinedBeans|Predicate]] determines whether a restart of authentication from the fudiscr plugin only restarts the //fudiscr// factor in the MFA flow (default) or restarts the entire authentication. If the [[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199508946/PredefinedBeans|Predicate]] returns ''TRUE'', the results of previous factors are reset. This means username and password, among others, will be requested again.| 
 +|''fudiscr.max_retries''|''10''|Number of failed attempts for validation. When this value is reached, validation ends unsuccessfully. This value is independent of the allowed failed attempts in privacyIDEA. If only the error counters from privacyIDEA should take effect, it is recommended to increase the value for ''fudiscr.max_retries'' accordingly (> max. failcounter in privacyIDEA).| 
 +|''fudiscr.restart_allowed.max_retries_exceeded''|''shibboleth.Conditions.TRUE''|This [[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199508946/PredefinedBeans|Predicate]] determines whether a restart of authentication in the fudiscr plugin is allowed when ''fudiscr.max_retries'' is reached.| 
 +|''fudiscr.restart_allowed.selected_tokens_not_available''|''shibboleth.Conditions.TRUE''|This [[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199508946/PredefinedBeans|Predicate]] determines whether a restart of authentication in the fudiscr plugin is allowed when the tokens selected by users are no longer available (e.g., due to being blocked in privacyIDEA).| 
 +|''fudiscr.restart_allowed.within_response_page''|''shibboleth.Conditions.TRUE''|This [[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199508946/PredefinedBeans|Predicate]] determines whether restarting fudiscr authentication is allowed via the response input page (OTP, TAN, etc.).|| 
 +|''fudiscr.result_idp_attribute_principal_attribute_name''|//empty//|If an attribute name is specified with this option, an [[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199503198/PrincipalNameAttributeDefinition|IdpAttributePrincipal]] with this attribute name is added to the successful authentication result of the fudiscr plugin. The attribute value contains the ID/serial number of the token used for authentication.| 
 +|''fudiscr.result_idp_attribute_principal_attribute_name_for_token_type''|//empty//|If an attribute name is specified with this option, an [[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199503198/PrincipalNameAttributeDefinition|IdpAttributePrincipal]] with this attribute name is added to the successful authentication result of the fudiscr plugin. The attribute value contains the token type of the token used for authentication.| 
 +|''fudiscr.result_with_realm_in_username_principal''|''shibboleth.Conditions.FALSE''|When a [[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199505212/AttributePostLoginC14NConfiguration|UsernamePrincipal]] is generated with ''fudiscr.result_with_username_principal'', this [[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199508946/PredefinedBeans|Predicate]] determines whether the realm is included. ''TRUE'' (default) generates e.g., //dummy@fu-berlin.de//, ''FALSE'' only generates //dummy// as username.| 
 +|''fudiscr.result_with_username_principal''|''shibboleth.Conditions.TRUE''|This [[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199508946/PredefinedBeans|Predicate]] determines whether a [[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199505212/AttributePostLoginC14NConfiguration|UsernamePrincipal]] is added to the Subject after successful authentication. By default, the authentication result contains a [[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199505212/AttributePostLoginC14NConfiguration|UsernamePrincipal]] after successful authentication with the fudiscr plugin.| 
 +|''fudiscr.username_realm_split_regex''|''@''|A username is generated from a previous factor during authentication. This can also contain a realm, e.g., //dummy@fu-berlin.de//. This option sets the separator used to split the username and realm. The default value is ''@''
 +|''fudiscr.user_token_selection''|''none''|This option determines whether tokens can be selected by users. Possible values are: ''none''=no selection, ''singleToken''=selection of a single token (by ID/serial number), ''multipleToken''=selection of multiple tokens (by serial number), ''singleTokenTypeGroup''=selection of a single token type (e.g., totp), ''multipleTokenTypeGroup''=selection of multiple token types. By default (''none''), a challenge is generated for all active tokens.| 
 + 
 +==== Configuration Options for eduMFA/privacyIDEA ==== 
 +=== eduMFA === 
 +See [[en:shibidp:plugin-fudiscr:edumfa_setup|Installation and Configuration of eduMFA]] 
 +=== privacyIDEA === 
 +See [[en:shibidp:plugin-fudiscr:privacyidea_setup|Installation and Configuration of privacyIDEA]] 
 +\\ 
 + 
 + 
 +==== Token Filtering ==== 
 +Tokens can be filtered based on properties such as token ID/serial number, status, type, and others. Additionally, properties from SAML or OIDC requests can be used for filtering. These include, for example, the entityID of the Service Provider, the Authentication Context Class, or the user's IP address. 
 + 
 +=== General Filtering via Regular Expressions === 
 +Generally, tokens can be excluded based on their type or ID/serial number using the (above-mentioned) configuration options ''fudiscr.filter_tokens.type_exclude_regex'' and ''fudiscr.filter_tokens.id_exclude_regex'' in ''%{idp.home}/conf/authn/fudiscr.properties''
 + 
 +<file properties> 
 +fudiscr.filter_tokens.type_exclude_regex=^(sms|web_authn)$ 
 +</file> 
 +In this example, all SMS and WebAuthn tokens are filtered out. 
 + 
 +<file properties> 
 +fudiscr.filter_tokens.id_exclude_regex=^(OATH|TOTP).+$ 
 +</file> 
 +In this example, all tokens with the prefix OATH or TOTP in their serial number are filtered out. This affects all HOTP and TOTP tokens in eduMFA and privacyIDEA. 
 + 
 +=== Filtering with Advanced Exclusion Conditions === 
 +Advanced exclusion conditions can be defined in ''%{idp.home}/conf/authn/fudiscr.xml''. The conditions are combined in the list ''fudiscr.ExcludeTokenPredicates'' and processed sequentially. 
 + 
 +<file xml> 
 +<util:list id="fudiscr.ExcludeTokenPredicates"> 
 +    <ref bean="fudiscr.ExcludeTokenPredicate1"/> 
 +    <ref bean="fudiscr.ExcludeTokenPredicate2"/> 
 +    <ref bean="fudiscr.ExcludeTokenPredicate3"/> 
 +    <!-- etc. --> 
 +</util:list> 
 +</file> 
 +This example shows how the exclusion list is generally defined. 
 + 
 +The exclusion conditions can be formulated as //Scripted// or using //Regular Expressions// related to token properties. 
 +\\ 
 +\\ 
 + 
 +== Scripted Example == 
 +<file xml> 
 +<util:list id="fudiscr.ExcludeTokenPredicates"> 
 +   <ref bean="fudiscr.ScriptedExcludeTokenPredicateExample1"/> 
 +</util:list> 
 + 
 +<!-- Input1: profileRequestContext (org.opensaml.profile.context.ProfileRequestContext) --> 
 +<!-- Input2: token (de.zedat.fudis.shibboleth.idp.plugin.authn.fudiscr.domain.Token) --> 
 +<!-- Output -> java.lang.Boolean / boolean --> 
 +<bean id="fudiscr.ScriptedExcludeTokenPredicateExample1" parent="fudiscr.Functions.ScriptedExcludeTokenPredicate" factory-method="inlineScript"> 
 +   <constructor-arg> 
 +      <value> 
 +      <![CDATA[ 
 +         // default is to keep the token 
 +         exclude = false; 
 + 
 +         relyingPartyId = profileContext.getSubcontext("net.shibboleth.profile.context.RelyingPartyContext").getRelyingPartyId(); 
 + 
 +         // if the service provider is not 'https://portal.local/shibboleth', tokens that are of type 'registration_code' are excluded 
 +         if (!relyingPartyId.equals("https://portal.local/shibboleth") && token.getType().toString().equalsIgnoreCase("registration_code")) { 
 +            exclude = true; 
 +         } 
 + 
 +         exclude; 
 +      ]]> 
 +      </value> 
 +   </constructor-arg> 
 +</bean> 
 +</file> 
 + 
 +== Example with Regular Expression == 
 +<file xml> 
 +<util:list id="fudiscr.ExcludeTokenPredicates"> 
 +   <ref bean="fudiscr.RegexExcludeTokenPredicateExample1"/> 
 +   <ref bean="fudiscr.RegexExcludeTokenPredicateExample2"/> 
 +</util:list> 
 + 
 +<bean id="fudiscr.RegexExcludeTokenPredicateExample1"   
 +      class="de.zedat.fudis.shibboleth.idp.plugin.authn.fudiscr.function.impl.RegexExcludeTokenPropertiesPredicate" 
 +      c:propertyName="rollout_state" 
 +      c:excludePattern="^verify$"/> 
 +<bean id="fudiscr.RegexExcludeTokenPredicateExample2"   
 +      class="de.zedat.fudis.shibboleth.idp.plugin.authn.fudiscr.function.impl.RegexExcludeTokenPropertiesPredicate" 
 +      c:propertyName="rollout_state" 
 +      c:excludePattern="^clientwait$"/> 
 +</file> 
 +In this example, tokens are filtered based on a token property. In eduMFA and privacyIDEA, active tokens can exist that require initial validation before they can be effectively used. For example, it should be enforced that users scan the QR code with the authenticator when setting up a TOTP token and confirm this process with an OTP. Until confirmation, the tokens have the property //rollout_state// with the values //verify// or //clientwait//. The two predicates used in the example can also be represented with one predicate and the regular expression //^(clientwait|verify)$//. The example is only meant to illustrate the list property of ''fudiscr.ExcludeTokenPredicates''
 + 
 +(The constructor parameter ''c:negateResult="true"'' can be used to negate the result of an //ExcludeTokenPredicate//.) 
 +\\ 
 +\\ 
 + 
 +==== Function fudiscr.UserHasTokenPredicate ==== 
 +The bean 'fudiscr.UserHasTokenPredicate' provides a function to determine whether users have generally been set up for the second factor or for a token procedure. This function can be particularly useful during the rollout phase. However, the decision whether users are activated for a second factor can also be controlled through groups in an LDAP directory service. 
 +This function also offers the previously mentioned filtering options via beans in '%{idp.home}/conf/authn/fudiscr.xml'. The filter list used has the id 'fudiscr.UserHasTokenExcludeTokenPredicates'. If the filter lists 'fudiscr.ExcludeTokenPredicates' and 'fudiscr.UserHasTokenExcludeTokenPredicates' should be identical, an alias can be defined for 'fudiscr.UserHasTokenExcludeTokenPredicates': 
 +<file xml> 
 +<alias name="fudiscr.ExcludeTokenPredicates" alias="fudiscr.UserHasTokenExcludeTokenPredicates"/> 
 +</file> 
 +\\ 
 + 
 +==== Preselected Tokens ==== 
 +Equivalent to the filters 'fudiscr.ExcludeTokenPredicates' and 'fudiscr.UserHasTokenExcludeTokenPredicates', a filter can be defined that filters out a user's preferred tokens. If the exclude filter list 'fudiscr.PreferredExcludeTokenPredicates' is defined, only the preferred tokens will be used initially. If the filtering results in all tokens being excluded, the filtering is reset. If the filtering reduces the initial list, users will be offered a button on the token selection page and the response input page to access the complete token selection. If selection by users is no longer necessary after filtering with 'fudiscr.PreferredExcludeTokenPredicates', the challenge is generated immediately. For example, if filtering results in only //TOTP// tokens remaining and 'fudiscr.user_token_selection=singleTokenTypeGroupis configured, a challenge for the //TOTP// tokens is immediately triggered and the response input page is displayed. However, users will still have the option to select other token methods as mentioned before. 
 + 
 +=== Example Preferred === 
 +<file xml> 
 +<util:list id="fudiscr.PreferredExcludeTokenPredicates"> 
 +    <bean class="de.zedat.fudis.shibboleth.idp.plugin.authn.fudiscr.function.impl.RegexExcludeTokenPropertiesPredicate" 
 +          c:propertyName="info:fudis_preferred" 
 +          c:excludePattern="^(?i)no$" 
 +          p:defaultValueForMissingProperty="no"/> 
 +    <bean class="de.zedat.fudis.shibboleth.idp.plugin.authn.fudiscr.function.impl.RegexExcludeTokenPropertiesPredicate" 
 +          c:propertyName="type" 
 +          c:excludePattern="^totp$" 
 +          c:negateResult="true"/> 
 +</util:list> 
 +</file> 
 +This example filters out all tokens that do not have the token info attribute 'fudis_preferred' with the value 'true' (case-insensitive) and are not of type 'totp'. 'p:defaultValueForMissingProperty="no"' causes the //RegexExcludeTokenPropertiesPredicate// to return //no// when a token (info) attribute is missing. Please note that 'c:negateResult="true"' turns an exclude into an include. In this example, unlike the previous filter examples, the beans are defined directly in the list and not as references. 
 +\\ 
 +\\ 
 + 
 +==== Realm-Transformation ==== 
 +It can happen that users are distributed across multiple data sources in Identity Management. For example, students and employees might be managed in two separate LDAP servers. This in turn means that two realms must be created in eduMFA or privacyIDEA, and these realms must be distinguished in API requests. For the User object in the fudiscr plugin, the following logic is followed to determine the realm: 
 + 
 +- Using the Java class 'net.shibboleth.idp.session.context.navigate.CanonicalUsernameLookupStrategy', the username is first determined from the previous authentication results according to Shibboleth standard. 
 +- Using 'fudiscr.username_realm_split_regex', an attempt is made to separate the realm as a separate attribute from the username. 
 +- If a list 'fudiscr.UserRealmTransformationStrategies' with realm transformation strategies is defined in '%{idp.home}/conf/authn/fudiscr.xml', these strategies are processed in the listed order. 
 +- If no realm exists yet, a default realm is assigned if it has been defined with 'fudiscr.default_users_realm'
 +The realm determined in this way is used by all classes in the fudiscr plugin that process a User object. 
 + 
 +If the realm in the User object from the fudiscr plugin is not defined (//null//), then a realm for the API request can be added with 'fudiscr.edumfa.default_realm' against eduMFA or with 'fudiscr.privacyidea.default_realm' against privacyIDEA. However, the realm added in this way is not incorporated into the general User object from the fudiscr plugin! 
 + 
 +=== Example UserRealmTransformationStrategies === 
 +<file xml> 
 +<util:list id="fudiscr.UserRealmTransformationStrategies"> 
 +   <!-- The attribute specified under 'ldapAttributeName' must also be included in the list of 'idp.authn.LDAP.returnAttributes'. --> 
 +   <bean class="de.zedat.fudis.shibboleth.idp.plugin.authn.fudiscr.function.impl.UserRealmFromLdapPrincipalTransformationStrategy" 
 +         p:activeAuthenticationResultKey="authn/Password" 
 +         p:ldapAttributeName="realm"/> 
 +    
 +   <!-- For ScriptedUserRealmTransformationStrategy: --> 
 +   <!-- Input1: profileRequestContext (org.opensaml.profile.context.ProfileRequestContext) --> 
 +   <!-- Input2: currentUserRealm (java.lang.String) --> 
 +   <!-- Output -> java.lang.String -->          
 +   <bean class="de.zedat.fudis.shibboleth.idp.plugin.authn.fudiscr.function.impl.ScriptedUserRealmTransformationStrategy" factory-method="inlineScript"> 
 +      <constructor-arg> 
 +         <value> 
 +            <![CDATA[ 
 +            newUserRealm = null; 
 + 
 +            if (currentUserRealm == null) { 
 +               newUserRealm = "idp-users"; 
 +            } 
 + 
 +            newUserRealm; 
 +            ]]> 
 +         </value> 
 +      </constructor-arg> 
 +   </bean> 
 +</util:list> 
 +</file> 
 +In this example, it checks whether an //LdapPrincipal// exists in the active authentication result from the authentication with username and password (//authn/Password//) and whether this //LdapPrincipal// contains the attribute //realm//. The first value from //realm// is adopted as the realm. Subsequently, a //Scripted// strategy is applied. 
 +\\ 
 +\\ 
 + 
 +==== Subject Customizers ==== 
 +The [[https://refeds.org/assurance|REFEDS Assurance Framework]] defines, among other things, profiles for multi-factor authentication. Generally, Service Providers can require properties via Authentication Context Class that only apply to specific tokens. Filtering of matching tokens is possible with ''fudiscr.ExcludeTokenPredicates'', but this filtering is not helpful when determining whether an authentication result in an SSO session can be used for another Service Provider. 
 + 
 +Authentication Context Classes are mapped as Principals in the Shibboleth Identity Provider. Each authentication method has the properties ''idp.authn.<flowid>.supportedPrincipals'' and ''idp.authn.<flowid>.addDefaultPrincipals'' (Default: true). The ''idp.authn.<flowid>.supportedPrincipals'' determine whether the respective authentication method matches the requested Authentication Context Class. With ''idp.authn.<flowid>.addDefaultPrincipals=true'', the ''idp.authn.<flowid>.supportedPrincipals'' are added to the authentication result. 
 + 
 +The list bean ''fudiscr.SubjectCustomizers'' allows modifying the Principals for the Authentication Context Class. 
 + 
 +Additionally, two functions are offered as Reuse-Conditions. 
 + 
 +''fudiscr.FlowSpecificRequestedPrincipalsReuseCondition'' requires the single (second) factor again if the existing Authentication Context Classes are insufficient. ''fudiscr.GeneralRequestedPrincipalsReuseCondition'' requires all factors if the existing Authentication Context Classes are insufficient. 
 + 
 +The following example shows the interaction of the configuration elements. 
 + 
 +=== Example SubjectCustomizers with supportedPrincipals and ReuseConditions === 
 +In ''%{idp.home}/conf/authn/authn.properties'', the ''supportedPrincipals'' are defined for the authentication procedure ''fudiscr'': 
 +<file properties> 
 +idp.authn.fudiscr.supportedPrincipals= \ 
 +    saml2/urn:de:zedat:fudis:SAML:2.0:ac:classes:CR,
 +    saml2/urn:de:zedat:fudis:SAML:2.0:ac:classes:CR:IAP:LOW,
 +    saml2/urn:de:zedat:fudis:SAML:2.0:ac:classes:CR:IAP:HIGH 
 +</file> 
 + 
 +For the MFA flow, all supportedPrincipals must be defined that are covered by the individual factors used in total. If the first factor consists of the usual query for user name and password (flowid=password), then the entry in ''%{idp.home}/conf/authn/authn.properties'' should look like this: 
 + 
 +<file properties> 
 +idp.authn.MFA.supportedPrincipals = \ 
 +    saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocol,
 +    saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport,
 +    saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:Password,
 +    saml1/urn:oasis:names:tc:SAML:1.0:am:password,
 +    saml2/urn:de:zedat:fudis:SAML:2.0:ac:classes:CR,
 +    saml2/urn:de:zedat:fudis:SAML:2.0:ac:classes:CR:IAP:LOW,
 +    saml2/urn:de:zedat:fudis:SAML:2.0:ac:classes:CR:IAP:HIGH 
 +</file> 
 + 
 +A subject customizer is now defined in ''%{idp.home}/conf/authn/fudiscr.xml'', which always adds the authentication context class ''saml2/urn:de:zedat:fudis:SAML:2.0:ac:classes:CR'' for ''fudiscr''. Depending on the properties of the successfully used token, either only ''saml2/urn:de:zedat:fudis:SAML:2. 0:ac:classes:CR:IAP:LOW'' or ''saml2/urn:de:zedat:fudis:SAML:2.0:ac:classes:CR:IAP:LOW'' and ''saml2/urn:de:zedat:fudis:SAML:2.0:ac:classes:CR:IAP:HIGH'' are added. 
 + 
 +<file xml> 
 +<util:list id="fudiscr.SubjectCustomizers"> 
 +    <ref bean="fudiscr.ScriptedAuthenticationMethodAndContextPrincipalsTokenBasedSubjectCustomizer"/> 
 +</util:list> 
 + 
 +<bean id="fudiscr.ScriptedAuthenticationMethodAndContextPrincipalsTokenBasedSubjectCustomizer" parent="fudiscr.Functions.ScriptedAuthenticationMethodAndContextPrincipalsSubjectCustomizer" factory-method="inlineScript"> 
 +    <constructor-arg> 
 +        <value> 
 +            <![CDATA[ 
 +            var logger = Java.type( "org.slf4j.LoggerFactory" ).getLogger("fudiscr.ScriptedAuthenticationMethodAndContextPrincipalsSubjectCustomizer"); 
 +            logger.trace("Input 1, principals: '{}'", principals); 
 +            logger.trace("Input 2, token: '{}'", token) 
 +            var HashSet = Java.type("java.util.HashSet"); 
 +            var newPrincipals = new HashSet(); 
 + 
 +            var AuthnContextClassRefPrincipal = Java.type("net.shibboleth.idp.saml.authn.principal.AuthnContextClassRefPrincipal"); 
 +            var standardPrincipal = new AuthnContextClassRefPrincipal("urn:de:zedat:fudis:SAML:2.0:ac:classes:CR"); 
 +            newPrincipals.add(standardPrincipal); 
 +            if (token.getProperties().get("description") != null && token.getProperties().get("description").toString().equalsIgnoreCase("IAP=high")) { 
 +                var lowPrincipal = new AuthnContextClassRefPrincipal("urn:de:zedat:fudis:SAML:2.0:ac:classes:CR:IAP:LOW"); 
 +                newPrincipals.add(lowPrincipal); 
 +                var highPrincipal = new AuthnContextClassRefPrincipal("urn:de:zedat:fudis:SAML:2.0:ac:classes:CR:IAP:HIGH"); 
 +                newPrincipals.add(highPrincipal); 
 +            } 
 +                 
 +            if (token.getProperties().get("description") != null && token.getProperties().get("description").toString().equalsIgnoreCase("IAP=low")) { 
 +                var lowPrincipal = new AuthnContextClassRefPrincipal("urn:de:zedat:fudis:SAML:2.0:ac:classes:CR:IAP:LOW"); 
 +                newPrincipals.add(lowPrincipal); 
 +            } 
 + 
 +            logger.trace("Result, newPrincipals: '{}'", newPrincipals); 
 +            newPrincipals; 
 +            ]]> 
 +        </value> 
 +    </constructor-arg> 
 +</bean>                                                 
 +</file> 
 + 
 +The two variants for the reuse conditions can now be set in ''%{idp.home}/conf/authn/authn.properties''
 + 
 +Variant 1: Only the second factor is required again if the previous Authentication Context Classes are not sufficient. 
 +<file properties> 
 +idp.authn.MFA.reuseCondition=shibboleth.Conditions.FALSE 
 +idp.authn.Password.reuseCondition=shibboleth.Conditions.TRUE 
 +idp.authn.fudiscr.reuseCondition=fudiscr.FlowSpecificRequestedPrincipalsReuseCondition 
 +</file> 
 + 
 +Variant 2: All factors are required again if the previous Authentication Context Classes are not sufficient. 
 +<file properties> 
 +idp.authn.MFA.reuseCondition=shibboleth.Conditions.FALSE 
 +idp.authn.Password.reuseCondition=fudiscr.GeneralRequestedPrincipalsReuseCondition 
 +idp.authn.fudiscr.reuseCondition=fudiscr.GeneralRequestedPrincipalsReuseCondition 
 +</file> 
 +\\ 
 + 
 +==== Subject Canonicalization ==== 
 +As an additional feature, a flow based on ''de.zedat.fudis.shibboleth.idp.plugin.authn.fudiscr.domain.ChallengeResponseTokenIdPrincipal'' can be activated for the [[https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199512211/SubjectCanonicalization|SubjectCanonicalization]] process in the Shibboleth Identity Provider. This additional Principal generated by the fudiscr-Plugin contains the ID/serial number of the successfully used token. 
 + 
 +To activate the flow, the reference ''<ref bean=“c14n/fudiscr” />'' must be added to the list ''shibboleth.PostLoginSubjectCanonicalizationFlows'' in the configuration file ''%{idp.home}/conf/c14n/subject-c14n.xml''
 + 
 +In addition, transformation options can be specified as for other principals, e.g. in ''%{idp.home}/conf/c14n/subject-c14n.properties'': 
 +<file properties> 
 +idp.c14n.fudiscr.lowercase=false 
 +idp.c14n.fudiscr.uppercase=false 
 +idp.c14n.fudiscr.trim=true 
 +</file> 
 +\\ 
 + 
 +===== fudispasskeys Configuration (eduMFA only) ===== 
 +Fudispasskeys provides an authentication method that integrates into the login page for username and password authentication and enables direct authentication with a security key or passkeys. The configuration is done in the following steps: 
 +\\ 
 +=== Use of the EduMfaChallengeResponseClient === 
 +The procedure is only supported by the ''EduMfaChallengeResponseClient'' in conjunction with eduMFA. The following property must therefore be set in ''%{idp.home}/conf/authn/fudiscr.properties'': 
 +<file properties> 
 +fudiscr.challengeResponseClient=EduMfaChallengeResponseClient 
 +</file> 
 + 
 +=== Definition of the Relying Party Id for WebAuthn/Passkeys === 
 +In addition, the Relying Party Id for WebAuthn/Passkeys must be set in ''%{idp.home}/conf/authn/fudiscr.properties'' in accordance with the enrollment policy [[https://edumfa.readthedocs.io/en/v2.2.0/policies/enrollment.html#policy-webauthn-enroll-relying-party-id|webauthn_relying_party_id]] from eduMFA: 
 +<file properties> 
 +fudispasskeys.relying_party_id=<same value here as in the enrollment policy 'webauthn_relying_party_id' in eduMFA> 
 +</file> 
 + 
 +=== Definition/extension of the shibboleth.CustomViewContext bean === 
 +To be able to access special functions in the views, the bean ''shibboleth.CustomViewContext'' must be defined or extended in ''%{idp.home}/conf/global.xml''. This is a list that requires at least one entry for the ''fudispasskeys.ChallengeGenerationStrategy'': 
 +<file xml> 
 +<util:map id="shibboleth.CustomViewContext"> 
 +    <!-- hier die bisherigen Einträge --> 
 +    <entry key="fudispasskeys.ChallengeGenerationStrategy" value-ref="fudispasskeys.ChallengeGenerationStrategy" /> 
 +</util:map> 
 +</file> 
 + 
 +=== Adaptation of authn-events-flow.xml === 
 +The following extensions must be made in ''%{idp.home}/conf/authn/authn-events-flow.xml'': 
 + 
 +<file xml> 
 +<flow xmlns="http://www.springframework.org/schema/webflow" 
 +      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 +      xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow.xsd" 
 +      abstract="true"> 
 +       
 +    <!-- Custom error events to reflect back from user-supplied login subflows. --> 
 +    <!-- <end-state id="MyCustomEvent" /> --> 
 +    <end-state id="fudispasskeys" /><!-- add this for fudispasskeys --> 
 + 
 +    <global-transitions> 
 +        <!-- <transition on="MyCustomEvent" to="MyCustomEvent" /> --> 
 +        <transition on="fudispasskeys" to="fudispasskeys" /><!-- add this for fudispasskeys --> 
 +        <transition on="#{!'proceed'.equals(currentEvent.id)}" to="InvalidEvent" /> 
 +    </global-transitions> 
 + 
 +</flow> 
 +</file> 
 + 
 +=== Adaptation of mfa-authn-config.xml === 
 +In the existing ''%{idp.home}/conf/authn/mfa-authn-config.xml'', the ''shibboleth.authn.MFA.TransitionMap'' must be extended: 
 + 
 +<file xml> 
 +<util:map id="shibboleth.authn.MFA.TransitionMap"> 
 +    <entry key=""> 
 +         <bean parent="shibboleth.authn.MFA.Transition" p:nextFlow="authn/fudispasskeys"/> 
 +    </entry> 
 +    <entry key="authn/fudispasskeys"> 
 +        <bean parent="shibboleth.authn.MFA.Transition"> 
 +            <property name="nextFlowStrategyMap"> 
 +                <map> 
 +                    <entry key="NoCredentials" value="authn/Password" /> 
 +                    <entry key="InvalidCredentials" value="authn/Password" /> 
 +                </map> 
 +            </property> 
 +        </bean> 
 +    </entry> 
 +    <entry key="authn/Password"> 
 +        <bean parent="shibboleth.authn.MFA.Transition"> 
 +            <property name="nextFlowStrategyMap"> 
 +                <map> 
 +                    <entry key="fudispasskeys" value="authn/fudispasskeys" /><!-- add this for fudispasskeys --> 
 +                    <entry key="proceed" value-ref="checkSecondFactor" /><!-- or the previous entry for the second factor --> 
 +                </map> 
 +            </property> 
 +        </bean> 
 +    </entry> 
 +</util:map> 
 +</file> 
 + 
 +=== Adaptation of login.vm === 
 +In ''%{idp.home}/views/login.vm'' the following line must be inserted outside the login form: 
 +<file xml> 
 +#parse("fudispasskeys/login-passkeys.vm"
 +</file> 
 + 
 +In addition, the attribute ''autocomplete'' with the value ''webauthn'' can be inserted or added to the input fields for user name and password, e.g. 
 +<file xml> 
 +autocomplete="webauthn" 
 +</file> 
 + 
 +This means that additional passkey authentication is offered when these input fields are selected. 
 + 
 +=== Policies in eduMFA === 
 +According to [[https://doku.tid.dfn.de/de:shibidp:plugin-fudiscr:edumfa_setup#richtlinien_fuer_fudispasskeys|eduMFA guidelines for fudispasskeys]], the following authentication and enrollment policies must be set in eduMFA: 
 + 
 +for the scope authentication: 
 +<file properties> 
 +webauthn_user_verification_requirement = required 
 +webauthn_usernameless_authn = True 
 +</file> 
 + 
 +for scope enrollment: 
 +<file properties> 
 +webauthn_relying_party_id = <domain of your institution> 
 +webauthn_relying_party_name = <name of the relying party> 
 +webauthn_resident_key = required 
 +webauthn_user_verification_requirement = required 
 +</file> 
 + 
 +==== AuthenticationFlowDescriptor für fudispasskeys ==== 
 +Analog zum [[https://doku.tid.dfn.de/de:shibidp:plugin-fudiscr#authenticationflowdescriptor_fuer_fudiscr|AuthenticationFlowDescriptor für fudiscr]] existiert auch ein AuthenticationFlowDescriptor für fudispasskeys: 
 + 
 +<file properties> 
 +#idp.authn.fudispasskeys.order=1000 
 +#idp.authn.fudispasskeys.nonBrowserSupported=true 
 +#idp.authn.fudispasskeys.passiveAuthenticationSupported=true 
 +#idp.authn.fudispasskeys.forcedAuthenticationSupported=true 
 +#idp.authn.fudispasskeys.proxyRestrictionsEnforced=%{idp.authn.fudispasskeys.forcedAuthenticationSupported:true} 
 +#idp.authn.fudispasskeys.proxyScopingEnforced=false 
 +#idp.authn.fudispasskeys.discoveryRequired=false 
 +#idp.authn.fudispasskeys.lifetime=%{idp.authn.defaultLifetime:PT1H} 
 +#idp.authn.fudispasskeys.inactivityTimeout=%{idp.authn.defaultTimeout:PT30M} 
 +#idp.authn.fudispasskeys.reuseCondition=shibboleth.Conditions.TRUE 
 +#idp.authn.fudispasskeys.activationCondition=shibboleth.Conditions.TRUE 
 +#idp.authn.fudispasskeys.subjectDecorator= 
 +#idp.authn.fudispasskeys.errorMessageFunction = DefaultPasswordErrorFunction 
 +#idp.authn.fudispasskeys.genericMessageID = authn 
 +#idp.authn.fudispasskeys.addDefaultPrincipals=true 
 +#idp.authn.fudispasskeys.trimUsernamePrincipal=true 
 +#idp.authn.fudispasskeys.lowercaseUsernamePrincipal=false 
 +#idp.authn.fudispasskeys.uppercaseUsernamePrincipal=false 
 +#idp.authn.fudispasskeys.supportedPrincipals= \ 
 +#    saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocol,
 +#    saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport,
 +#    saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:Password,
 +#    saml1/urn:oasis:names:tc:SAML:1.0:am:password,
 +#    saml2/urn:de:zedat:fudis:SAML:2.0:ac:classes:CR 
 +</file> 
 + 
 +===== Logging ===== 
 +To obtain detailed logging information from the fudiscr-Plugin, the following line can be added to ''%{idp.home}/conf/logback.xml'': 
 +<file xml> 
 +<logger name="de.fu.dis" level="DEBUG"/> 
 +<logger name="de.zedat.fudis" level="DEBUG"/> 
 +</file> 
 + 
 +If all API requests against privacyIDEA are to be logged separately, the following additional configuration is suggested: 
 +<file xml> 
 +<logger name="de.fu.dis.rest.interceptors" level="TRACE"> 
 +    <appender-ref ref="IDP_FUDIS_REQUEST"/> 
 +</logger> 
 +<logger name="de.zedat.fudis.rest.interceptors" level="TRACE"> 
 +    <appender-ref ref="IDP_FUDIS_REQUEST"/> 
 +</logger> 
 +<logger name="de.fu.dis.edumfa.client" level="WARN"> 
 +    <appender-ref ref="IDP_FUDIS_REQUEST"/> 
 +</logger> 
 +<logger name="de.zedat.fudis.privacyidea.client" level="WARN"> 
 +    <appender-ref ref="IDP_FUDIS_REQUEST"/> 
 +</logger> 
 + 
 +<!-- FUDIS-Interceptor log. --> 
 +<appender name="IDP_FUDIS_REQUEST" class="ch.qos.logback.core.rolling.RollingFileAppender"> 
 +   <File>${idp.logfiles}/idp-fudis-request.log</File> 
 +   <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 
 +      <fileNamePattern>${idp.logfiles}/idp-request-%d{yyyy-MM-dd}.log.gz</fileNamePattern> 
 +      <maxHistory>${idp.loghistory}</maxHistory> 
 +   </rollingPolicy> 
 +   <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> 
 +      <charset>UTF-8</charset> 
 +      <Pattern>%msg%n</Pattern> 
 +   </encoder> 
 +</appender> 
 +</file> 
 +\\ 
 + 
 +===== Extension for Fortinet (FortiAuthenticator) ===== 
 +The Fortinet extension currently supports the token types //FortiToken (Mobile and Hardware)//, //SMS// and //Email//. //FIDO2 (WebAuthn)// is currently not supported by the FortiAuthenticator API. 
 + 
 +The extension is available under the Apache 2.0 License and is provided by DAASI International GmbH [[https://gitlab.daasi.de/shibboleth-identity-provider/shibboleth-idp-plugin-authn-fudiscr-fortinetclient|here]]. DAASI also offers software maintenance contracts for the extension. Please send inquiries to [[info@daasi.de|info@daasi.de]]. 
 +\\ 
 + 
 +===== Additional Materials =====
  
-In general it applies that the domain of the Identity Provider has to either be identical to the //rpId// from WebAuthn or a subdomain of it. +    * Flow: [[https://identity.fu-berlin.de/downloads/shibboleth/idp/plugins/authn/fudiscr/doc/ChallengeResponseFlow.pdf|ChallengeResponseFlow.pdf]] 
-There is no preliminary filtering done in order to check if the domain of the Identity Provider is compatible to the //rpId// of the WebAuthn token+    Materials from the [[de:aai:events:ws2022|Shibboleth Workshops February 2022]]
-===== Further resources ==== +
-  Documents from the [[de:aai:events:ws2022|Shibboleth Workshops February 2022]] (in German)+
  
-{{tag>2FA MFA two-factor-authentication multi-factor-authentication}}+{{tag>2FA MFA Two-Factor-Authentication Multi-Factor-Authentication}}
  
 +==== Source Code =====
 +Universities and other public institutions can get access to the source code upon request. Please send an email to [[fudis@fu-berlin.de|fudis@fu-berlin.de]]. Work is in progress to publish all components of the fudiscr-Plugin under the Apache 2.0 License. We ask for (continued) patience.
 ===== Contact ===== ===== Contact =====
-Please email [[fudis@zedat.fu-berlin.de|fudis@zedat.fu-berlin.de]] for corrections, questions and suggestions.+Please send bugs, questions, suggestions etc. via email to [[fudis@fu-berlin.de|fudis@fu-berlin.de]].
  • Last modified: 3 years ago