All Downloads are FREE. Search and download functionalities are using the official Maven repository.

se.swedenconnect.opensaml.saml2.request.AuthnRequestGeneratorContext Maven / Gradle / Ivy

/*
 * Copyright 2016-2021 Sweden Connect
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package se.swedenconnect.opensaml.saml2.request;

import java.util.Comparator;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;

import org.opensaml.saml.common.xml.SAMLConstants;
import org.opensaml.saml.saml2.core.AuthnContextComparisonTypeEnumeration;
import org.opensaml.saml.saml2.core.AuthnRequest;
import org.opensaml.saml.saml2.core.NameID;
import org.opensaml.saml.saml2.core.NameIDPolicy;
import org.opensaml.saml.saml2.core.RequestedAuthnContext;
import org.opensaml.saml.saml2.metadata.AssertionConsumerService;
import org.opensaml.saml.saml2.metadata.AttributeConsumingService;
import org.opensaml.saml.saml2.metadata.NameIDFormat;
import org.opensaml.security.x509.X509Credential;
import org.opensaml.xmlsec.SecurityConfigurationSupport;
import org.opensaml.xmlsec.SignatureSigningConfiguration;

import se.swedenconnect.opensaml.saml2.core.build.NameIDPolicyBuilder;
import se.swedenconnect.opensaml.saml2.core.build.RequestedAuthnContextBuilder;

/**
 * Defines a context which can be used to control how
 * {@link AuthnRequestGenerator#generateAuthnRequest(String, String, AuthnRequestGeneratorContext)} creates an
 * authentication request.
 * 
 * @author Martin Lindström ([email protected])
 */
public interface AuthnRequestGeneratorContext {

  /**
   * Gets the binding to use when generating a request (redirect/POST).
   * 

* This binding will be used in all cases except when the IdP does not support the binding. *

*

* The default implementation returns {@value SAMLConstants#SAML2_REDIRECT_BINDING_URI}. *

* * @return the preferred binding */ default String getPreferredBinding() { return SAMLConstants.SAML2_REDIRECT_BINDING_URI; } /** * Gets the SP requirement for using the Holder-of-key profile. The default is that the SP does not support HoK. * * @return a HoK requirement */ default HokRequirement getHokRequirement() { return HokRequirement.DONT_USE; } /** * Gets the {@code ForceAuthn} attribute value. *

* The default implementation returns {@code true}. *

*

* If {@code null} is returned, the {@code ForceAuthn} attribute will not be included. *

* * @return the ForceAuthn attribute */ default Boolean getForceAuthnAttribute() { return Boolean.TRUE; } /** * Gets the {@code IsPassive} attribute value. *

* The default implementation returns {@code null}. *

*

* If {@code null} is returned, the {@code IsPassive} attribute will not be included. *

* * @return the IsPassive attribute */ default Boolean getIsPassiveAttribute() { return null; } /** * If a signature configuration, other than the default * ({@link SecurityConfigurationSupport#getGlobalSignatureSigningConfiguration()}) should be used to sign the request * this method should return this configuration. *

* The default implementation returns {@code null}. *

* * @return the signature configuration, or null */ default SignatureSigningConfiguration getSignatureSigningConfiguration() { return null; } /** * Gets the {@link AssertionConsumerServiceResolver} to use for resolving which {@link AssertionConsumerService} to * use and whether to produce an {@code AssertionConsumerServiceURL} or {@code AssertionConsumerServiceIndex} * attribute. *

* The default implementation will return a {@code AssertionConsumerServiceURL} based on (1) {@code isDefault} * attribute and (2) the lowest {@code Index}. *

* * @return a function for resolving AssertionConsumerService elements */ default AssertionConsumerServiceResolver getAssertionConsumerServiceResolver() { return (list) -> list.stream() .filter(a -> a.isDefault()) .map(AssertionConsumerService::getLocation) .findFirst() .orElse(list.stream() .min(Comparator.comparing(a -> a.getIndex() != null ? a.getIndex() : Integer.MAX_VALUE)) .map(AssertionConsumerService::getLocation) .orElse(list.get(0).getLocation())); } /** * Gets the resolver function for determining how to create the {@code AttributeConsumingServiceIndex} attribute. *

* The default implementation returns {@code null}, meaning that no attribute is added. *

* * @return a resolver function */ default AttributeConsumingServiceIndexResolver getAttributeConsumingServiceIndexResolver() { return (list) -> null; } /** * Gets the builder for creating a {@code NameIDPolicy} element. *

* The default implementation will use the first {@code NameIDFormat} in the list and create a {@code NameIDPolicy} * element with this value as the {@code Format} attribute and the {@code AllowCreate} set to true. If the supplied * list is empty, the format will be set to {@code urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified}. *

* * @return a builder function */ default NameIDPolicyBuilderFunction getNameIDPolicyBuilderFunction() { return list -> NameIDPolicyBuilder.builder() .allowCreate(true) .format(list.isEmpty() ? NameID.UNSPECIFIED : list.get(0).getURI()) .build(); } /** * Gets the builder function for creating the {@code RequestedAuthnContext} element to add to the * {@code AuthnRequest}. *

* The default implementation will create a {@code RequestedAuthnContext} object with exact matching and all assurance * certification URI:s included in the supplied list. *

* * @return a function that returns a RequestedAuthnContext (or null). */ default RequestedAuthnContextBuilderFunction getRequestedAuthnContextBuilderFunction() { return (list, hok) -> !list.isEmpty() ? RequestedAuthnContextBuilder.builder() .comparison(AuthnContextComparisonTypeEnumeration.EXACT) .authnContextClassRefs(list) .build() : null; } /** * Gets the {@link AuthnRequestCustomizer}. *

* The default implementation returns a NO-OP consumer, meaning no customizations are done. *

* * @return a consumer working on the AuthnRequest object being built */ default AuthnRequestCustomizer getAuthnRequestCustomizer() { return (a) -> { }; } /** * The {@link AuthnRequestGenerator} is normally configured with a signing credential * (AuthnRequestGenerator#getSignCredential()}. This method exist so that we may override the default credential. * Mainly for testing purposes. *

* The default implementation returns {@code null}. *

* * @return the signing credential to use, or null if no override should be done */ default X509Credential getOverrideSignCredential() { return null; } /** * When the generator is about to add the {@code AssertionConsumerServiceURL} or {@code AssertionConsumerServiceIndex} * attribute it will invoke the {@link AuthnRequestGeneratorContext#getAssertionConsumerServiceResolver()} method in * order to get a function that given all possible {@code AssertionConsumerService} elements (found in the SP * metadata) will either return a {@code String} (holding the {@code AssertionConsumerServiceURL} to use) or an * {@code Integer} (holding the {@code AssertionConsumerServiceIndex} to use). *

* Note: The function will be called even if there is only one possible {@code AssertionConsumerService}. In those * cases it is up to the function to decide whether to return a {@code String} or an {@code Integer}. *

*/ public interface AssertionConsumerServiceResolver extends Function, Object> { } /** * If the SP metadata contains one or more {@code AttributeConsumingService} elements, the generator needs to know * whether to include the {@code AttributeConsumingServiceIndex} attribute, and if so, which index to use. The * generator gets this resolver by invoking * {@link AuthnRequestGeneratorContext#getAttributeConsumingServiceIndexResolver()}. *

* If this function returns {@code null}, no {@code AttributeConsumingServiceIndex} attribute will be included. *

*/ public interface AttributeConsumingServiceIndexResolver extends Function, Integer> { } /** * A {@code NameIDPolicyBuilderFunction} is used by the generator to create the {@code NameIDPolicy} element. As input * to the function the generator supplies a list of {@code NameIDFormat} elements. This list is the intersection of * what is supported by the SP and the IdP (found in metadata). Note that this list may be empty. *

* The {@code NameIDPolicyResolver} will be invoked with a list where the order is the same order as the * {@code NameIDFormat} elements appear in the SP metadata. *

*

* If the resolver returns {@code null}, no {@code NameIDPolicy} will be included in the {@code AuthnRequest}. *

*/ public interface NameIDPolicyBuilderFunction extends Function, NameIDPolicy> { } /** * The generator will need to know how to build the {@code RequestedAuthnContext} element that is to be included in * the {@code AuthnRequest}. The {@link AuthnRequestGeneratorContext#getRequestedAuthnContextBuilderFunction()} method * returns the function, that given a list of IdP assurance certification URI:s and a boolean that tells whether the * Holder-of-key profile is active or not (could affect which URI that is chosen), creates a * {@code RequestedAuthnContext} element. *

* If the function returns {@code null} no {@code RequestedAuthnContext} is added to the {@code AuthnRequest}. *

*/ public interface RequestedAuthnContextBuilderFunction extends BiFunction, Boolean, RequestedAuthnContext> { } /** * When the generator is done building the {@code AuthnRequest}, but before it is signed, it will ask the * {@link AuthnRequestGeneratorContext#getAuthnRequestCustomizer()} method for the customizer that may operate and add * customizations to the request object. */ public interface AuthnRequestCustomizer extends Consumer { } /** * Enumeration that tells whether the Holder-of-key WebSSO profile is required, optional or not active. */ public enum HokRequirement { /** * The SP will always use HoK - A call to * {@link AuthnRequestGenerator#generateAuthnRequest(String, String, AuthnRequestGeneratorContext)} for an IdP that * does not support this profile will fail. */ REQUIRED, /** * The Holder-of-key profile will be used if the IdP supports it. */ IF_AVAILABLE, /** * The holder-of-key profile will never be used. */ DONT_USE }; }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy