Search in sources :

Example 26 with RequestAbstractType

use of org.opensaml.saml.saml2.core.RequestAbstractType in project cas by apereo.

the class SamlObjectSignatureValidator method validateSignatureOnAuthenticationRequest.

private void validateSignatureOnAuthenticationRequest(final RequestAbstractType profileRequest, final HttpServletRequest request, final MessageContext context, final RoleDescriptorResolver roleDescriptorResolver) throws Exception {
    val peer = context.getSubcontext(SAMLPeerEntityContext.class, true);
    peer.setEntityId(SamlIdPUtils.getIssuerFromSamlObject(profileRequest));
    val peerEntityId = Objects.requireNonNull(peer.getEntityId());
    LOGGER.debug("Validating request signature for [{}]...", peerEntityId);
    val roleDescriptor = roleDescriptorResolver.resolveSingle(new CriteriaSet(new EntityIdCriterion(peerEntityId), new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME)));
    peer.setRole(roleDescriptor.getElementQName());
    val protocol = context.getSubcontext(SAMLProtocolContext.class, true);
    protocol.setProtocol(SAMLConstants.SAML20P_NS);
    LOGGER.debug("Building security parameters context for signature validation of [{}]", peerEntityId);
    val secCtx = context.getSubcontext(SecurityParametersContext.class, true);
    val validationParams = new SignatureValidationParameters();
    if (overrideBlockedSignatureAlgorithms != null && !overrideBlockedSignatureAlgorithms.isEmpty()) {
        validationParams.setExcludedAlgorithms(this.overrideBlockedSignatureAlgorithms);
        LOGGER.debug("Validation override blocked algorithms are [{}]", this.overrideAllowedAlgorithms);
    }
    if (overrideAllowedAlgorithms != null && !overrideAllowedAlgorithms.isEmpty()) {
        validationParams.setIncludedAlgorithms(this.overrideAllowedAlgorithms);
        LOGGER.debug("Validation override allowed algorithms are [{}]", this.overrideAllowedAlgorithms);
    }
    LOGGER.debug("Resolving signing credentials for [{}]", peerEntityId);
    val credentials = getSigningCredential(roleDescriptorResolver, profileRequest);
    if (credentials.isEmpty()) {
        throw new SamlException("Signing credentials for validation could not be resolved");
    }
    var foundValidCredential = false;
    val it = credentials.iterator();
    while (!foundValidCredential && it.hasNext()) {
        val handler = new SAML2HTTPRedirectDeflateSignatureSecurityHandler();
        try {
            val credential = it.next();
            val resolver = new StaticCredentialResolver(credential);
            val keyResolver = new StaticKeyInfoCredentialResolver(credential);
            val trustEngine = new ExplicitKeySignatureTrustEngine(resolver, keyResolver);
            validationParams.setSignatureTrustEngine(trustEngine);
            secCtx.setSignatureValidationParameters(validationParams);
            handler.setHttpServletRequest(request);
            LOGGER.debug("Initializing [{}] to execute signature validation for [{}]", handler.getClass().getSimpleName(), peerEntityId);
            handler.initialize();
            LOGGER.debug("Invoking [{}] to handle signature validation for [{}]", handler.getClass().getSimpleName(), peerEntityId);
            handler.invoke(context);
            LOGGER.debug("Successfully validated request signature for [{}].", profileRequest.getIssuer());
            foundValidCredential = true;
        } catch (final Exception e) {
            LOGGER.debug(e.getMessage(), e);
        } finally {
            handler.destroy();
        }
    }
    if (!foundValidCredential) {
        LOGGER.error("No valid credentials could be found to verify the signature for [{}]", profileRequest.getIssuer());
        throw new SamlException("No valid signing credentials for validation could not be resolved");
    }
}
Also used : lombok.val(lombok.val) SignatureValidationParameters(org.opensaml.xmlsec.SignatureValidationParameters) StaticKeyInfoCredentialResolver(org.opensaml.xmlsec.keyinfo.impl.StaticKeyInfoCredentialResolver) StaticCredentialResolver(org.opensaml.security.credential.impl.StaticCredentialResolver) ExplicitKeySignatureTrustEngine(org.opensaml.xmlsec.signature.support.impl.ExplicitKeySignatureTrustEngine) CriteriaSet(net.shibboleth.utilities.java.support.resolver.CriteriaSet) EntityIdCriterion(org.opensaml.core.criterion.EntityIdCriterion) EntityRoleCriterion(org.opensaml.saml.criterion.EntityRoleCriterion) SAML2HTTPRedirectDeflateSignatureSecurityHandler(org.opensaml.saml.saml2.binding.security.impl.SAML2HTTPRedirectDeflateSignatureSecurityHandler) SamlException(org.apereo.cas.support.saml.SamlException) SamlException(org.apereo.cas.support.saml.SamlException)

Example 27 with RequestAbstractType

use of org.opensaml.saml.saml2.core.RequestAbstractType in project cas by apereo.

the class SamlResponseArtifactEncoder method finalizeEncode.

@Override
protected void finalizeEncode(final RequestAbstractType authnRequest, final BaseSAML2MessageEncoder e, final Response samlResponse, final String relayState, final MessageContext messageContext) {
    val encoder = (HTTPArtifactEncoder) e;
    encoder.setArtifactMap(this.samlArtifactMap);
    val ctx = getEncoderMessageContext(authnRequest, samlResponse, relayState, messageContext);
    prepareArtifactContext(samlResponse, ctx);
    encoder.setMessageContext(ctx);
    super.finalizeEncode(authnRequest, encoder, samlResponse, relayState, messageContext);
}
Also used : lombok.val(lombok.val) HTTPArtifactEncoder(org.opensaml.saml.saml2.binding.encoding.impl.HTTPArtifactEncoder)

Example 28 with RequestAbstractType

use of org.opensaml.saml.saml2.core.RequestAbstractType in project cas by apereo.

the class SamlIdPInitiatedProfileHandlerController method handleIdPInitiatedSsoRequest.

/**
 * Handle idp initiated sso requests.
 * The URL of the response location at the SP (called the "Assertion Consumer Service")
 * but can be omitted in favor of the IdP picking the default endpoint location from metadata.
 *
 * @param response the response
 * @param request  the request
 * @return the model and view
 * @throws Exception the exception
 */
@GetMapping(path = SamlIdPConstants.ENDPOINT_SAML2_IDP_INIT_PROFILE_SSO)
protected ModelAndView handleIdPInitiatedSsoRequest(final HttpServletResponse response, final HttpServletRequest request) throws Exception {
    val providerId = request.getParameter(SamlIdPConstants.PROVIDER_ID);
    if (StringUtils.isBlank(providerId)) {
        LOGGER.warn("No providerId parameter given in unsolicited SSO authentication request.");
        throw new MessageDecodingException("Missing providerId");
    }
    val registeredService = verifySamlRegisteredService(providerId);
    val adaptor = getSamlMetadataFacadeFor(registeredService, providerId);
    if (adaptor.isEmpty()) {
        throw new UnauthorizedServiceException(UnauthorizedServiceException.CODE_UNAUTHZ_SERVICE, "Cannot find metadata linked to " + providerId);
    }
    var shire = request.getParameter(SamlIdPConstants.SHIRE);
    val facade = adaptor.get();
    if (StringUtils.isBlank(shire)) {
        LOGGER.info("Resolving service provider assertion consumer service URL for [{}] and binding [{}]", providerId, SAMLConstants.SAML2_POST_BINDING_URI);
        val acs = facade.getAssertionConsumerService(SAMLConstants.SAML2_POST_BINDING_URI);
        shire = acs != null ? StringUtils.isBlank(acs.getResponseLocation()) ? acs.getLocation() : acs.getResponseLocation() : null;
    }
    if (StringUtils.isBlank(shire)) {
        LOGGER.warn("Unable to resolve service provider assertion consumer service URL for AuthnRequest construction for entityID: [{}]", providerId);
        throw new MessageDecodingException("Unable to resolve SP ACS URL for AuthnRequest construction");
    }
    val target = request.getParameter(SamlIdPConstants.TARGET);
    val time = request.getParameter(SamlIdPConstants.TIME);
    val builder = (SAMLObjectBuilder) getConfigurationContext().getOpenSamlConfigBean().getBuilderFactory().getBuilder(AuthnRequest.DEFAULT_ELEMENT_NAME);
    val authnRequest = (AuthnRequest) builder.buildObject();
    authnRequest.setAssertionConsumerServiceURL(shire);
    val isBuilder = (SAMLObjectBuilder) getConfigurationContext().getOpenSamlConfigBean().getBuilderFactory().getBuilder(Issuer.DEFAULT_ELEMENT_NAME);
    val issuer = (Issuer) isBuilder.buildObject();
    issuer.setValue(providerId);
    authnRequest.setIssuer(issuer);
    authnRequest.setProtocolBinding(SAMLConstants.SAML2_POST_BINDING_URI);
    val pBuilder = (SAMLObjectBuilder) getConfigurationContext().getOpenSamlConfigBean().getBuilderFactory().getBuilder(NameIDPolicy.DEFAULT_ELEMENT_NAME);
    val nameIDPolicy = (NameIDPolicy) pBuilder.buildObject();
    nameIDPolicy.setAllowCreate(Boolean.TRUE);
    authnRequest.setNameIDPolicy(nameIDPolicy);
    if (NumberUtils.isCreatable(time)) {
        authnRequest.setIssueInstant(Instant.ofEpochMilli(Long.parseLong(time)));
    } else {
        authnRequest.setIssueInstant(ZonedDateTime.now(ZoneOffset.UTC).toInstant());
    }
    authnRequest.setForceAuthn(Boolean.FALSE);
    if (StringUtils.isNotBlank(target)) {
        request.setAttribute(SamlProtocolConstants.PARAMETER_SAML_RELAY_STATE, target);
    }
    val ctx = new MessageContext();
    if (facade.isAuthnRequestsSigned() || registeredService.isSignUnsolicitedAuthnRequest()) {
        getConfigurationContext().getSamlObjectSigner().encode(authnRequest, registeredService, facade, response, request, SAMLConstants.SAML2_POST_BINDING_URI, authnRequest, ctx);
    }
    ctx.setMessage(authnRequest);
    val bindingContext = ctx.getSubcontext(SAMLBindingContext.class, true);
    Objects.requireNonNull(bindingContext).setHasBindingSignature(false);
    SAMLBindingSupport.setRelayState(ctx, target);
    val pair = Pair.<RequestAbstractType, MessageContext>of(authnRequest, ctx);
    val modelAndView = initiateAuthenticationRequest(pair, response, request);
    if (modelAndView != null) {
        val view = (RedirectView) modelAndView.getView();
        val urlBuilder = new URIBuilder(Objects.requireNonNull(view).getUrl());
        val paramNames = request.getParameterNames();
        while (paramNames.hasMoreElements()) {
            val parameterName = paramNames.nextElement();
            if (!parameterName.equalsIgnoreCase(SamlIdPConstants.TARGET) && !parameterName.equalsIgnoreCase(SamlIdPConstants.TIME) && !parameterName.equalsIgnoreCase(SamlIdPConstants.SHIRE) && !parameterName.equalsIgnoreCase(SamlIdPConstants.PROVIDER_ID)) {
                urlBuilder.addParameter(parameterName, request.getParameter(parameterName));
            }
        }
        view.setUrl(urlBuilder.build().toString());
    }
    return modelAndView;
}
Also used : lombok.val(lombok.val) MessageDecodingException(org.opensaml.messaging.decoder.MessageDecodingException) AuthnRequest(org.opensaml.saml.saml2.core.AuthnRequest) SAMLObjectBuilder(org.opensaml.saml.common.SAMLObjectBuilder) Issuer(org.opensaml.saml.saml2.core.Issuer) NameIDPolicy(org.opensaml.saml.saml2.core.NameIDPolicy) RequestAbstractType(org.opensaml.saml.saml2.core.RequestAbstractType) RedirectView(org.springframework.web.servlet.view.RedirectView) UnauthorizedServiceException(org.apereo.cas.services.UnauthorizedServiceException) MessageContext(org.opensaml.messaging.context.MessageContext) URIBuilder(org.apache.http.client.utils.URIBuilder) GetMapping(org.springframework.web.bind.annotation.GetMapping)

Example 29 with RequestAbstractType

use of org.opensaml.saml.saml2.core.RequestAbstractType in project cas by apereo.

the class SamlIdPUtils method determineEndpointForRequest.

private static AssertionConsumerService determineEndpointForRequest(final RequestAbstractType authnRequest, final SamlRegisteredServiceServiceProviderMetadataFacade adaptor, final String binding, final AssertionConsumerService acsFromRequest, final AssertionConsumerService acsFromMetadata, final MessageContext authenticationContext) {
    LOGGER.trace("ACS from authentication request is [{}], ACS from metadata is [{}] with binding [{}]", acsFromRequest, acsFromMetadata, binding);
    if (acsFromRequest != null) {
        if (!authnRequest.isSigned() && !SAMLBindingSupport.isMessageSigned(authenticationContext)) {
            val locations = StringUtils.isNotBlank(binding) ? adaptor.getAssertionConsumerServiceLocations(binding) : adaptor.getAssertionConsumerServiceLocations();
            val acsUrl = StringUtils.defaultIfBlank(acsFromRequest.getResponseLocation(), acsFromRequest.getLocation());
            val acsIndex = authnRequest instanceof AuthnRequest ? AuthnRequest.class.cast(authnRequest).getAssertionConsumerServiceIndex() : null;
            if (StringUtils.isNotBlank(acsUrl) && locations.contains(acsUrl)) {
                return buildAssertionConsumerService(binding, acsUrl, acsIndex);
            }
            if (acsIndex != null) {
                val result = adaptor.getAssertionConsumerServiceFor(binding, acsIndex);
                if (result.isPresent()) {
                    return buildAssertionConsumerService(binding, result.get(), acsIndex);
                }
            }
            val message = String.format("Assertion consumer service [%s] cannot be located in metadata [%s]", acsUrl, locations);
            throw new SamlException(message);
        }
        return acsFromRequest;
    }
    return acsFromMetadata;
}
Also used : lombok.val(lombok.val) AuthnRequest(org.opensaml.saml.saml2.core.AuthnRequest)

Aggregations

lombok.val (lombok.val)11 AuthnRequest (org.opensaml.saml.saml2.core.AuthnRequest)8 SAMLObject (org.opensaml.saml.common.SAMLObject)5 RequestAbstractType (org.opensaml.saml.saml2.core.RequestAbstractType)5 MessageContext (org.opensaml.messaging.context.MessageContext)4 Assertion (org.opensaml.saml.saml2.core.Assertion)4 NameID (org.opensaml.saml.saml2.core.NameID)4 ZonedDateTime (java.time.ZonedDateTime)3 HttpServletResponse (javax.servlet.http.HttpServletResponse)3 SneakyThrows (lombok.SneakyThrows)3 CriteriaSet (net.shibboleth.utilities.java.support.resolver.CriteriaSet)3 SamlException (org.apereo.cas.support.saml.SamlException)3 LogoutRequest (org.opensaml.saml.saml2.core.LogoutRequest)3 AssertionConsumerService (org.opensaml.saml.saml2.metadata.AssertionConsumerService)3 Body (org.opensaml.soap.soap11.Body)3 Envelope (org.opensaml.soap.soap11.Envelope)3 Header (org.opensaml.soap.soap11.Header)3 ArrayList (java.util.ArrayList)2 Objects (java.util.Objects)2 Optional (java.util.Optional)2