Dynamic authenticators are authenticators that delegate authentication execution to another authenticator which can be configured dynamically.
The dynamic configuration for the delegate authenticator may be obtained by Curity from an external source, as we’ll see later, rather than from the Configuration Service as with conventional authenticators.
The main use-case for dynamic authenticators is supporting Federation-based authentication. For example, it is possible to configure a dynamic authenticator that, depending on the username of the user starting an authentication flow (which can be collected by a pre-requisite username authenticator), uses a different OpenID Connect provider or Credential Manager to actually authenticate the user.
Dynamic authenticators have a static Authenticator Base Configuration, as all authenticators, but also:
The Authenticator Base Configuration is inherited by the delegate authenticator, while the Shared Delegate Authenticator Settings are made available to the delegate authenticator’s configuration loader, which may then use that to transform the loaded configuration.
These settings are meant to be used by the delegate plugin configuration loader to transform the loaded configuration. In other words, they are not part of the delegate authenticator’s configuration.
Currently, this includes only one setting:
This setting allows a delegate plugin whose dynamic configuration includes a keystore to keep the password to decrypt such keystore in the Dynamic Authenticator’s configuration, rather than together with the dynamic configuration.
Note
Keeping the password together with the encrypted keystore in the dynamically loaded configuration would make the password pointless.
As with all secrets, Curity automatically encrypts the value of this setting when exporting its configuration.
Currently, only the SAML2 plugin uses this setting.
The Dynamic Authenticator requires the following settings to identify and load a delegate plugin:
The following sections explain these settings in more detail.
The delegate authenticator is responsible for performing the actual user authentication and is configured according to the dynamic configuration fetched for it for each federation.
The following authenticator types are currently supported:
The configuration for the delegate authenticator must be provided by an external source.
The following can provide dynamic authenticator’s configuration:
In both cases, two parameters are provided as “keys” for fetching the configuration to be used:
The federation ID is expected to be part of the subject attributes under a key called dynamic-authenticator-federation-id. If not present, the value default is used.
See Example Use-case for an example of how to set this attribute.
The response must be provided using the configuration schema for the relevant delegate authenticator, excluding the base settings (the Dynamic Authenticator’s Base Settings are always used for all delegate authenticators).
The plugin-specific configuration should be the root of the response object. See an example in the Web Service section below.
Curity caches responses for a particular combination of federation ID and implementation-type few hours to avoid reloading configuration too often.
The parameters are provided as follows:
Web Services must provide the response using the application/json media type.
Example request for dynamic configuration:
GET https://example.org:8888/dynamic-conf?fid=default&imp=oidc Accept: application/json
Example JSON response body for a oidc delegate authenticator:
{ "configuration-url": "https://example.org:8888/.well-known/openid-configuration", "client-id": "oauth-client-id", "client-secret": "data:text/plain;aes,v:S.TTdUVGFTUG1PSWJNN3B1Zg==.NmvU8FRhq0kTj-wguiCZxg==.e_a3d6iTdUpVK0rzBDRh4Q==.5tKEIn_chCo_1pjE9FuZy1MZ4qt_6c1i-Y_F2cI2ogM=", "http-client": "http-client-id", }
GET https://example.org:8888/dynamic-conf?fid=samlfederation&imp=saml2 Accept: application/json
Example JSON response body for a saml2 delegate authenticator:
{ "issuer-entity-id": "https://curity.example.com/sp", "force-auth": "always", "idp-entity-id": "https://external.example.com/idp", "idp-url": "https://external.example.com/idp/authenticate", "signature-verification-key": "default-signature-verification-key" }
the easiest way to find out what the configuration object looks like for a particular authenticator type is to configure the authenticator using the Web UI, then click on View XML at the top-right of the screen, then customize the data as needed.
Care must be taken to ensure that any elements referenced to from the dynamic configuration actually exist in the server configuration. For example, the configuration above would require that there exists a http-client with ID http-client-id in the static server configuration. If that is not the case, the configuration will fail validation and all authentication attempts will result in an error.
<authenticator> <id>dyn1</id> <description>Dynamic authentication</description> <previous-authenticator>collect-username</previous-authenticator> <dynamic xmlns="https://curity.se/ns/conf/authenticators/dynamic"> <delegate-implementation-type>oidc</delegate-implementation-type> <!-- could be a configuration-bucket instead --> <configuration-web-service> <hostname>example.org</hostname> <port>8888</port> <context>/dynamic-conf</context> <http-client>http-client-id</http-client> </configuration-web-service> </dynamic> </authenticator>
An example use-case for Dynamic Authenticators could go like this:
function result(context) { var attributes = context.attributeMap; var sub = attributes.subject; var indexOfAt = sub.indexOf('@'); // federationId which will be sent to the external configuration source var federationId = indexOfAt >= 0 ? sub.substring(indexOfAt + 1) : 'default'; // the dynamic authenticator will look at this attribute for the federation ID, // or use 'default' if it's not found. attributes['dynamic-authenticator-federation-id'] = federationId; return attributes; }
When the Dynamic Authenticator executes, it will load the configuration (from the cache if available) for the particular federation ID added by the script transformer (which should have run after the previous-authenticator), generate an instance of the OIDC Authenticator with that configuration, and then delegate the authentication flow to the newly-configured OIDC Authenticator.