ServiceProviderState
Introduction and overview
The AuthState ServiceProviderState acts as a SAML 2.0 service provider (SP). It handles the following protocols according to the OASIS specification:
- Authentication Request Protocol (AuthnRequest, Response)
- SingleLogout (SP-initiated and IdP-initiated)
For information on assertions and protocols for the OASIS Security Assertion Markup Language (SAML) v2.0, see(http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf)Supported
bindings:
- HTTP POST (as sender and receiver)
- HTTP Redirect (as sender and receiver)
- HTTP Artifact (as receiver)
- Additional, proprietary bindings
The ServiceProviderState verifies the SubjectConfirmations of incoming SAML assertions as mandated by the SAML specification. As explained in chapter Prospect verification, the prospect verification setting covers some use cases where a SubjectConfirmation may not be verifiable by the ServiceProviderState itself.
This AuthState replaces the Consumer AuthState in new setups. It is more flexible and more compliant to the SAML 2 specifications (for a description of the Consumer AuthState, see Consumer (SAML 2.0 service provider).
The underlying engine used in this AuthState (ServiceProviderState) is openSAML 2.0, which requires the most recent XML parser functionality. In certain deployments, this dependency may lead to the exception "This parser does not support specification 'null' version 'null'" being thrown during startup. If you encounter this problem, add the following line to vmargs.conf: -Djava.endorsed.dirs=/opt/nevisauth/lib/endorsed
Description
The following table describes the characteristics of the AuthState.
Topic | Description |
---|---|
Class | ch.nevis.esauth.auth.states.saml.ServiceProviderState |
Logging | Saml |
Auditing | none |
Marker | SAML:federation |
Properties(generic) | consumerURL (string, -)URL of the SAML consumer location. Messages to the IdP will request responses to be sent to this URL. The value of this property will be used as the AssertionConsumerServiceURLelement of the generated AuthnRequest |
consumerIndex (int, -1)The consumerIndex is used to uniquely identify the service provider using a non-negative integer. The value is substituted before being forwarded in the AssertionConsumerServiceIndex element of the AuthnRequestWhen this attribute is set, then the value of consumerURL will be ignored: AssertionConsumerServiceURL will not be included in the generated AuthnRequest. | |
idpURL (string, -)URL of the IdP. Messages to the IdP will use this as destination address. This property is required if the ServiceProviderState may send a request to an IdP. | |
logoutCompletedURL (string, -)URL to which a redirect will be issued when a SingleLogout was completed. | |
limitSessionLifetime (boolean, false)When activated, this feature limits the maximum lifetime of the user session to the validity period of the consumed SAML assertion (the validity period of a SAML assertion is determined by the optional attributes NotBefore and NotOnOrAfter). When the assertion becomes invalid, the session will automatically become invalid as well. | |
soap.*For outgoing communication with the artifact resolution protocol, HTTP properties can be configured with the prefix "soap.". A list of valid properties can be found in chapter AuthHttpClient. | |
relayState (string, ${request:resource})relayState to be sent to the IdP. The user is redirected to this URL after the SAML operation is completed successfully. | |
Properties (input) | in.binding ({auto,http-post,http-redirect,http-artifact, internal, internal-assertion, none}, "auto")Defines the accepted SAML binding. Set to auto to have the AuthState guess the incoming binding.A more fine-grained configuration allows incoming messages to use only specific bindings, depending on the type of message. This can be defined as follows:<messageType>:<binding> , <messageType>:<binding> , ...The following example will accept SAML Responses only if transmitted using artifact binding and LogoutRequests only if transmitted using redirect binding while accepting all other messages irrespective of the bindings used.Response:http-artifact, LogoutRequest:http-redirect, autoThe binding none effectively disables processing of incoming messages such that input is ignored and only SP-initiated profiles are initiated.In internal and internal-assertion binding, the AuthState expects the incoming message at the location configured in in.internalBindingSource. internal-assertion causes the AuthState to expect and consume a SAML assertion instead of a SAML response. The state can handle plain or base64-encoded internal messages and will try to base64-decode if it suspects that an encoded SAML message was received.Be aware that for the binding "http-artifact", hostname verification is enabled by default. The relevant property is soap.checkHostname (boolean, true). When establishing an HTTPS connection, the client will check the hostname in the HTTPS server certificate against the actual server hostname by default. To disable hostname verification, set the property soap.checkHostname to "false". For more information about the prefix soap.**, see the description of the property soap.** further above in this table. |
in.internalBindingSource (string, -)If in.binding is configured to internal or internal-assertion, this property indicates the location of incoming messages. | |
in.tolerance (int (seconds), 5)Sets the tolerance for time constraints regarding the validation of incoming messages. This value should be set to the maximum expected clock skew between involved servers.When the Service Provider receives an assertion, it will make the following checks: Validation of theAuthnInstantof theAuthnStatementsin the assertion, by usingin.tolerance + in.max_age. Validation of the IssueInstant of the assertion, by using in.tolerance + in.max_age. Validation of theNotBeforeandNotAftersettings of the assertion, by usingin.tolerance + <server currentTime> .For a description of thein.max_age* property, see further on in this table. | |
in.prospectVerification (string, -)Comma-separated list of object types for which verification requirements are loosened. The precise nature of the verification done depends on the object type: Any signable object (likeAuthnRequests,Assertions):prospectVerificationmeans that the certificate of the signer may not be known in the configured truststore. This implies that the signature contains the signer's certificate or that it could not be verified. SubjectConfirmation: A HolderOfKey SubjectConfirmation is accepted even if it does not contain a reference to the client certificate of the request. The data of the SubjectConfirmation element is propagated in the notes with the prefix saml.holder-of-key (see the topic Notes in this table). See the chapter Prospect verification for more details about the prospect verification feature. | |
in.audience (string, -)Specifies the expected value of the audience attribute of an AudienceRestriction. | |
in.audienceRegex (string, -)Similar to in.audience, but allows to configure a regular expression, which is matched against the audience attribute of an AudienceRestriction. | |
in.audience.checkrequired (boolean, false)Defines whether the audience check is required or not. If set to true, SAML assertions that do not contain AudienceRestriction elements will be rejected. | |
in.max_age (int (seconds), 10)Defines the maximum time passed since the authentication of the subject took place (AuthnInstant) and the assertion was generated (assertion IssueInstant). To disable the max age check, set the property value to "-1" (this is not recommended). | |
in.allowed_attributes (string (list), -)Comma-separated list of allowed attributes of incoming assertions. If defined, this list functions as white-list for the attributes of incoming assertions. | |
in.required_attributes (string (list), -)Comma-separated list of required attributes of incoming assertions. If defined, only assertions with all required attributes will be accepted. | |
in.artifact_sources (string (map), required for artifact binding)List of sources for artifact resolution. The entries in the list have the following form:[<sourceID> :]<sourceURL> **SourceID can be specified in hex (starting with 0x), base64 (exactly 28 characters length) or as a string that must match the issuer ID. If the sourceID is omitted, the SHA-1 hash of the sourceURL will be used as the sourceID. | |
in.otu.class (string, -)Defines a class implementing the interface ch.nevis.esauth.auth.states.saml.OneTimeUseGuard to handle one-time use of SAML assertions.Supported implementations are: ch.nevis.esauth.auth.states.saml.SimpleOneTimeUseGuard: File-based (local) assertion cache. The classnevis.esauth.auth.states.saml.SimpleOneTimeUseGuard* consumes the following configuration properties: in.otu.interval (number, 300): Assertion reaper run interval. **in.otu.dir (strong, "/tmp/SAML-OneTimeUse-cache"): Cache directory for processed assertions. This class uses internal data structures to keep track of seen assertions and maintains files in the configured directory for persistency of this list in case of a shutdown or a crash. A reaper thread clears away entries and files of outdated assertions. | |
in.map_issuer_certificate (boolean, "false")If set to true, the issuer of the incoming message will be used as keyobjectref for the configured in.keystoreref. This allows a secure consumption of SAML assertions from different IdPs. | |
in.verify ". | |
in.verifyUniqueness (boolean, "false")If set to true, the assertion will be checked for uniqueness, even if HTTP POST binding is not used. | |
in.keystoreref, in.keyobjectref ".Ifin.map_issuer_certificateis on,in.keyobjectrefshould not be configured. Instead, thekeyobjectwhose name matches the issuer of the incoming message will be used. If in.map_issuer_certificate is off and in.ketobjectref is not defined, the appropriate certificate will be searched in the keystore. In this case, one of the following must hold for the verification: As part of the signature validation, trust, non-expiration and non-revocation is verified for all certificates involved in the trusted certificate chain. A configuration example can be found at the end of this table. | |
in.decrypt.*Properties for configuring decryption of incoming SAML messages. See also chapter Encryption and decryption. | |
in.relayState (string, "${inargs:RelayState}"This property defines the source of theRelayStateand may be used to manipulate or check incomingRelayStates. | |
Properties (output) | out.binding ({auto, http-post,http-redirect, http-post-deferred, http-redirect-deferred, propagate, internal}, "http-post")Defines the SAML binding for outgoing SAML messages.The deferred bindings will prepare the necessary data, but instead of initiating the binding right away, will place those values in the followingOutArg fields: *nevis.deferred-transfer.destination: The destination of the deferred binding * nevis.deferred-transfer.field.<fieldname> : The request, response and RelayState with field names SAMLRequest, SAMLResponse and RelayState respectively. The internal binding may be used to propagate a SAML message (typically a SAML response) to a back end using nevisProxy's delegation mechanisms. The OutArgs saml.SAMLResponse, saml.SAMLRequest and saml.RelayState will be set if applicable.In auto binding, the AuthState will attempt to use the binding of the incoming request. In that case, the configuration should ensure that there is always an incoming SAML request and that the same binding may be used to send the response.As with in.binding, this setting may be further refined by defining different output bindings for different message types. For example: AuthnRequest:http-post, LogoutResponse:auto, LogoutRequest: http-redirect |
out.issuer (string, "${request:EsAuthId}")The issuer name to be used in outgoing SAML messages. | |
out.subject (string, -)The subject in the AuthnRequest that will be stored in the saml2:NameID element. | |
out.subject.nameQualifier (string, -)The name qualifier in the AuthnRequest. | |
out.subject.spNameQualifier (string, -)The name qualifier of the SP in the AuthnRequest. | |
out.subject.format (string, -)The format definition in the AuthnRequest. | |
out.subject. spProviderId(string, -)The SP provider ID in the AuthnRequest. | |
out.forceAuthn (boolean, false)If set to true, the attribute ForceAuthn in the AuthnRequest will be set to true. | |
out.isPassive (boolean, false)If set to true, the attribute IsPassive in the AuthnRequest will be set to true. | |
out.providerName (string, -)The providerName in the AuthnRequest. | |
out.authnContextClassRef (string, -)AuthnContextClassRef to be used in the authentication request protocol, e.g., "urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified" | |
out.authnContextDeclRef (string, -)The authentication context declaration provided by a URI to be used in the authentication request protocol. | |
out.authnContextComparison (string, -)Specifies the comparison method used to evaluate the requested context classes or statements. Possible values are: exact minimum maximum better | |
out.ttl (int (seconds), 10)The time-to-live of generated SAML messages. | |
out.sign ". | |
out.sign.hashAlgorithm ". | |
out.signatureKeyInfo (comma-separated list of {SKI,Certificate,CertificateChain,Subject,IssuerSerial,CRLs,SubjectDN,SubjectCN,KeyNames,PublicKey}, SKI)List of KeyInfo content to add to signatures. One, several or none of the listed options may be configured. Note that some of the options require non-mandatory fields within signer certificate used. E.g., SKI may not add anything to the KeyInfo if the signer certificate does not contain an SKI.nevisAuth currently requires one SKI, Certificate or IssuerSerial to identify the correct verification certificate when several are configured. Similarly, NINJA only supports SKI when several verification certificates are configured. | |
out.keystorerefout.keyobjectrefThese properties configure the key materials used to sign SAML messages whose type is listed in out.sign. Refer to chapter Certificates keys and public key infrastructure. The key material is validated for trust, non-expiration and non-revocation before the SAML message is signed. | |
out.encrypt.*Properties for configuring encryption of outgoing SAML messages. See also chapter Encryption and decryption. | |
out.artifactSourceId (string, issuer)The artifact source ID can optionally be set to define which identifier should be used in order for the other endpoint to identify the artifact resolution service. Usually, the issuer ID is used. | |
in.extension.<extension-name> (string, <classname> )<extension-name>.<property-name> (string)This syntax specifies plug-ins that will be called to process incoming messages. Properties may be passed to the plug-ins using the second syntax shown.Currently, only the input-extenderch.nevis.esauth.auth.states.saml.extensions.SuisseIDAttributeExtractor is implemented. This extension extracts SuisseID attributes from incoming assertions. It takes the following properties:*<extension-name> .keystoreref The keystore to use for verification of QC-signed SuisseID attributes. * <extension-name> .keyobjectref The key object to use for verification of QC-signed SuisseID attributes (this property is optionally). Example configuration for SuisseIDAttributeExtractor: <property name="in.extension.SuisseIDattr" value="ch.nevis.esauth.auth.states.saml.extensions.SuisseIDAttributeExtractor" /> / <property name="SuisseIDattr.keystoreref" value="AttributeSigners" /> | |
Properties (plug-ins) | out.extension.<extension-name> (string, <classname> )<extension-name>.<property-name> (syntax)This syntax specifies plug-ins that will be called to extend outgoing messages. Properties may be passed to the plug-ins using the second syntax shown.Currently, only the output extender ch.nevis.esauth.auth.states.saml.extensions.SuisseIDAttributeServiceExtender is implemented for AuthnRequests. This extension adds requests for SuisseID attributes to outgoing messages. It takes the following properties:*<extension-name> .Attribute Comma-separated list of attributes to request in the issued message. Example configuration for SuisseIDAttributeServiceExtender: <property name="out.extension.SuisseID" value="ch.nevis.esauth.auth.states.saml.extensions.SuisseIDAttributeServiceExtender" /> / <property name="SuisseID.Attribute" value="${inargs:attributes}" /> |
Methods | authenticate: Tries to consume any incoming SAML responses and, if successful, redirects to the location indicated by RelayState. If no SAML response is found and the user is already authenticated, it will transition to ok. Otherwise, it will use the configured out.binding to forward a generated AuthnRequest to the configured idpURL. |
stepup: Same as authenticate, but can also initiate a logout if a LogoutRequest has been consumed successfully. It will use the configured out.binding to forward a generated AuthnRequest to the configured idpURL if the user does not have roles required by a SecurityRolesFilter. | |
logout: Will use the configured out.binding to forward a generated LogoutRequest to the configured idpURL. This is the first step in an SP-initiated SingleLogout protocol. | |
Input | All inputs used to resolve SAML bindings according to SAML specification: inargs: SAMLRequest, SAMLResponse, RelayState etc. |
Transitions | ok: Successfully consumed incoming assertion or user is already authenticated. |
logout: LogoutRequest was consumed. | |
logoutCompleted: A SingleLogout was completed and the final SingleLogoutResponse received. | |
status-: Thestatus-transitions are based on status codes out of SAML response messages. The system traces such response status codes in the error log file and turns them into transitions. These transitions guide the authentication engine to the next AuthState in case something went wrong with the request.When creating thestatus- transitions, the system uses the following naming convention:status-<StatusCode>-<SubStatusCode> . For example, to react to the status codeurn:oasis:names:tc:SAML:2.0:status:Responder, the system configures a transitionstatus-Responder.The subordinate second-level status code (<SubStatusCode> ) is only added if it provides additional information on the error condition.Some examples of*status-transitions: *status-Responder: This transition comes into play if a request could not be performed due to an error on the part of the SAML responder or the SAML authority. * status-Responder-AuthnFailed: This transition becomes active if the responding provider was unable to successfully authenticate the principal. | |
failed: This transition is valid in case of an unsuccessful request to which none of the other transitions/status codes apply. | |
Output | none |
Errors | 99: authentication error |
Notes | saml.attributes.<attribute-name> : Attributes propagated in the SAML assertion |
saml.issuer: Issuer of the SAML assertion | |
saml.destination: Destination of the SAML assertion | |
saml.holder-of-key.keyNamesaml.holder-of-key.keyValuesaml.holder-of-key.encryptedKeyssaml.holder-of-key.certificatesaml.holder-of-key.skisaml.holder-of-key.issuerNamesaml.holder-of-key.serialNumbersaml.holder-of-key.subjectNamesaml.holder-of-key.nameIdsaml.holder-of-key.nameId.format:These notes are propagated if a SubjectConfirmation element with the method "Holder of Key" is present. For detailed conditions also see the paragraph on "Holder of Key" in chapter Prospect verification. | |
saml.request.***saml.assertion.*saml.response.**Key values of consumed SAML messages. The following values are propagated (with the appropriate prefix):id, issuer, issueInstant, notBefore, notOnOrAfter, oneTimeUse, consent, destination, inResponseTo, statusCode, secondaryStatusCode, statusDetail, statusMessage, assertionConsumerServiceUrl, assertionConsumerServiceIndex, authnContextClassRef, authnContextDeclRef, authnContextDecl, authenticatingAuthorities, authnContextComparison, subjectLocality, subject, subject.nameQualifier, subject.spNameQualifier, subject.spProvidedId, subject.format, providerName, isPassive, forceAuthn, sessionIndexExamples: To fetch the statusCode of a consumed response, use ${notes:saml.response.statusCode} * To get the issuer of a consumed assertion, use ${notes:saml.assertion.issuer} |
Examples
<AuthState name="IGB2BServiceProvider" class="ch.nevis.esauth.auth.states.saml.ServiceProviderState" final="false">
<ResultCond name="ok" next="AuthDone" authLevel="auth.weak"/>
<Response value="AUTH_ERROR">
<Gui name="AuthErrorDialog"/>
</Response>
<property name="consumerURL" value="https://igb2b.zh.adnovum.ch/igb2b-consume/" />
<property name="idpURL" value="https://adnovum.igb2b.ch/consume/" />
<property name="in.verify" value="Assertion" />
<property name="in.binding" value="auto"/>
<property name="in.max_age" value="30"/>
<property name="in.keystoreref" value="IGB2BIdentityProvider" />
<property name="in.keyobjectref" value="IGB2B" />
<property name="in.allowed_attributes" value="language,surname,givenname,email" />
<property name="out.sign" value="none" />
<property name="out.binding" value="http-redirect"/>
<property name="out.ttl" value="10"/>
<property name="out.issuer" value="adnovum.ch" />
</AuthState>
<KeyStore name="TrustStore">
<KeyObject name="TrustedCertificates" certificate="/var/opt/keybox/nevis/truststore.jks">
<property name="certPassPhrase" value="secret">
</KeyStore>
<AuthState name="ServiceProvider" class="ch.nevis.esauth.auth.states.saml.ServiceProviderState" final="false">
<ResultCond name="ok" next="AuthDone" authLevel="auth.weak"/>
<Response value="AUTH_ERROR">
<Gui name="AuthErrorDialog"/>
</Response>
<property name="consumerURL" value="https://serviceprovider.zh.adnovum.ch/consume/" />
<property name="idpURL" value="https://identityprovider.ch/" />
<property name="in.verify" value="Assertion" />
<property name="in.binding" value="auto"/>
<property name="in.max_age" value="30"/>
<property name="in.keystoreref" value="TrustStore" />
<property name="in.allowed_attributes" value="language,surname,givenname,email" />
<property name="out.sign" value="none" />
<property name="out.binding" value="http-redirect"/>
<property name="out.ttl" value="10"/>
<property name="out.issuer" value="adnovum.ch" />
</AuthState>