Search in sources :

Example 56 with Request

use of org.opensaml.saml.saml2.ecp.Request in project ddf by codice.

the class LogoutRequestServiceTest method testGetLogoutRequestResponseInvalidSignature.

@Test
public void testGetLogoutRequestResponseInvalidSignature() throws Exception {
    String signature = "signature";
    String signatureAlgorithm = "sha1";
    String relayState = UUID.randomUUID().toString();
    String deflatedSamlResponse = RestSecurity.deflateAndBase64Encode("deflatedSamlResponse");
    LogoutResponse logoutResponse = mock(LogoutResponse.class);
    when(logoutMessage.extractSamlLogoutResponse(eq("deflatedSamlResponse"))).thenReturn(logoutResponse);
    LogoutRequestService lrs = new LogoutRequestService(simpleSign, idpMetadata, relayStates);
    lrs.setEncryptionService(encryptionService);
    lrs.setLogOutPageTimeOut(LOGOUT_PAGE_TIMEOUT);
    lrs.setLogoutMessage(logoutMessage);
    lrs.setRequest(request);
    lrs.setSessionFactory(sessionFactory);
    lrs.init();
    Response response = lrs.getLogoutRequest(null, deflatedSamlResponse, relayState, signatureAlgorithm, signature);
    assertEquals(Response.Status.SEE_OTHER.getStatusCode(), response.getStatus());
    String msg = "Unable to validate".replaceAll(" ", "+");
    assertTrue("Expected message containing " + msg, response.getLocation().getQuery().contains(msg));
}
Also used : LogoutResponse(org.opensaml.saml.saml2.core.LogoutResponse) Response(javax.ws.rs.core.Response) LogoutResponse(org.opensaml.saml.saml2.core.LogoutResponse) Matchers.anyString(org.mockito.Matchers.anyString) Test(org.junit.Test)

Example 57 with Request

use of org.opensaml.saml.saml2.ecp.Request in project ddf by codice.

the class IdpEndpoint method processLogin.

@GET
@Path("/login/sso")
public Response processLogin(@QueryParam(SAML_REQ) String samlRequest, @QueryParam(RELAY_STATE) String relayState, @QueryParam(AUTH_METHOD) String authMethod, @QueryParam(SSOConstants.SIG_ALG) String signatureAlgorithm, @QueryParam(SSOConstants.SIGNATURE) String signature, @QueryParam(ORIGINAL_BINDING) String originalBinding, @Context HttpServletRequest request) {
    LOGGER.debug("Processing login request: [ authMethod {} ], [ sigAlg {} ], [ relayState {} ]", authMethod, signatureAlgorithm, relayState);
    try {
        Binding binding;
        String template;
        if (!request.isSecure()) {
            throw new IllegalArgumentException("Authn Request must use TLS.");
        }
        //the authn request is always encoded as if it came in via redirect when coming from the web app
        Binding redirectBinding = new RedirectBinding(systemCrypto, serviceProviders);
        AuthnRequest authnRequest = redirectBinding.decoder().decodeRequest(samlRequest);
        String assertionConsumerServiceBinding = ResponseCreator.getAssertionConsumerServiceBinding(authnRequest, serviceProviders);
        if (HTTP_POST_BINDING.equals(originalBinding)) {
            binding = new PostBinding(systemCrypto, serviceProviders);
            template = submitForm;
        } else if (HTTP_REDIRECT_BINDING.equals(originalBinding)) {
            binding = redirectBinding;
            template = redirectPage;
        } else {
            throw new IdpException(new UnsupportedOperationException("Must use HTTP POST or Redirect bindings."));
        }
        binding.validator().validateAuthnRequest(authnRequest, samlRequest, relayState, signatureAlgorithm, signature, strictSignature);
        if (HTTP_POST_BINDING.equals(assertionConsumerServiceBinding)) {
            if (!(binding instanceof PostBinding)) {
                binding = new PostBinding(systemCrypto, serviceProviders);
            }
        } else if (HTTP_REDIRECT_BINDING.equals(assertionConsumerServiceBinding)) {
            if (!(binding instanceof RedirectBinding)) {
                binding = new RedirectBinding(systemCrypto, serviceProviders);
            }
        }
        org.opensaml.saml.saml2.core.Response encodedSaml = handleLogin(authnRequest, authMethod, request, null, false, false);
        LOGGER.debug("Returning SAML Response for relayState: {}" + relayState);
        NewCookie newCookie = createCookie(request, encodedSaml);
        Response response = binding.creator().getSamlpResponse(relayState, authnRequest, encodedSaml, newCookie, template);
        if (newCookie != null) {
            cookieCache.addActiveSp(newCookie.getValue(), authnRequest.getIssuer().getValue());
            logAddedSp(authnRequest);
        }
        return response;
    } catch (SecurityServiceException e) {
        LOGGER.info("Unable to retrieve subject for user.", e);
        return Response.status(Response.Status.UNAUTHORIZED).build();
    } catch (WSSecurityException e) {
        LOGGER.info("Unable to encode SAMLP response.", e);
    } catch (SimpleSign.SignatureException e) {
        LOGGER.info("Unable to sign SAML response.", e);
    } catch (IllegalArgumentException e) {
        LOGGER.info(e.getMessage(), e);
        return Response.status(Response.Status.BAD_REQUEST).build();
    } catch (ValidationException e) {
        LOGGER.info("AuthnRequest schema validation failed.", e);
        return Response.status(Response.Status.BAD_REQUEST).build();
    } catch (IOException e) {
        LOGGER.info("Unable to create SAML Response.", e);
    } catch (IdpException e) {
        LOGGER.info(e.getMessage(), e);
        return Response.status(Response.Status.BAD_REQUEST).build();
    }
    return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
Also used : RedirectBinding(org.codice.ddf.security.idp.binding.redirect.RedirectBinding) SoapBinding(org.codice.ddf.security.idp.binding.soap.SoapBinding) Binding(org.codice.ddf.security.idp.binding.api.Binding) PostBinding(org.codice.ddf.security.idp.binding.post.PostBinding) RedirectBinding(org.codice.ddf.security.idp.binding.redirect.RedirectBinding) SecurityServiceException(ddf.security.service.SecurityServiceException) ValidationException(ddf.security.samlp.ValidationException) WSSecurityException(org.apache.wss4j.common.ext.WSSecurityException) IOException(java.io.IOException) LogoutResponse(org.opensaml.saml.saml2.core.LogoutResponse) Response(javax.ws.rs.core.Response) SimpleSign(ddf.security.samlp.SimpleSign) AuthnRequest(org.opensaml.saml.saml2.core.AuthnRequest) PostBinding(org.codice.ddf.security.idp.binding.post.PostBinding) NewCookie(javax.ws.rs.core.NewCookie) Path(javax.ws.rs.Path) GET(javax.ws.rs.GET)

Example 58 with Request

use of org.opensaml.saml.saml2.ecp.Request in project ddf by codice.

the class IdpEndpoint method processRedirectLogout.

/**
     * aka HTTP-Redirect
     *
     * @param samlRequest        the base64 encoded saml request
     * @param samlResponse       the base64 encoded saml response
     * @param relayState         the UUID that references the logout state
     * @param signatureAlgorithm this signing algorithm
     * @param signature          the signature of the url
     * @param request            the http servlet request
     * @return Response redirecting to an service provider
     * @throws WSSecurityException
     * @throws IdpException
     */
@Override
@GET
@Path("/logout")
public Response processRedirectLogout(@QueryParam(SAML_REQ) final String samlRequest, @QueryParam(SAML_RESPONSE) final String samlResponse, @QueryParam(RELAY_STATE) final String relayState, @QueryParam(SSOConstants.SIG_ALG) final String signatureAlgorithm, @QueryParam(SSOConstants.SIGNATURE) final String signature, @Context final HttpServletRequest request) throws WSSecurityException, IdpException {
    LogoutState logoutState = getLogoutState(request);
    Cookie cookie = getCookie(request);
    try {
        if (samlRequest != null) {
            LogoutRequest logoutRequest = logoutMessage.extractSamlLogoutRequest(RestSecurity.inflateBase64(samlRequest));
            validateRedirect(relayState, signatureAlgorithm, signature, request, samlRequest, logoutRequest, logoutRequest.getIssuer().getValue());
            return handleLogoutRequest(cookie, logoutState, logoutRequest, SamlProtocol.Binding.HTTP_REDIRECT, relayState);
        } else if (samlResponse != null) {
            LogoutResponse logoutResponse = logoutMessage.extractSamlLogoutResponse(RestSecurity.inflateBase64(samlResponse));
            String requestId = logoutState != null ? logoutState.getCurrentRequestId() : null;
            validateRedirect(relayState, signatureAlgorithm, signature, request, samlResponse, logoutResponse, logoutResponse.getIssuer().getValue(), requestId);
            return handleLogoutResponse(cookie, logoutState, logoutResponse, SamlProtocol.Binding.HTTP_REDIRECT);
        }
    } catch (XMLStreamException e) {
        throw new IdpException("Unable to parse Saml Object.", e);
    } catch (ValidationException e) {
        throw new IdpException("Unable to validate Saml Object", e);
    } catch (IOException e) {
        throw new IdpException("Unable to deflate Saml Object", e);
    }
    throw new IdpException("Could not process logout");
}
Also used : NewCookie(javax.ws.rs.core.NewCookie) Cookie(javax.servlet.http.Cookie) ValidationException(ddf.security.samlp.ValidationException) LogoutResponse(org.opensaml.saml.saml2.core.LogoutResponse) XMLStreamException(javax.xml.stream.XMLStreamException) LogoutRequest(org.opensaml.saml.saml2.core.LogoutRequest) IOException(java.io.IOException) Path(javax.ws.rs.Path) GET(javax.ws.rs.GET)

Example 59 with Request

use of org.opensaml.saml.saml2.ecp.Request in project ddf by codice.

the class IdpEndpoint method showLoginPage.

private Response showLoginPage(String samlRequest, String relayState, String signatureAlgorithm, String signature, HttpServletRequest request, Binding binding, String template, String originalBinding) throws WSSecurityException {
    String responseStr;
    AuthnRequest authnRequest = null;
    try {
        Map<String, Object> responseMap = new HashMap<>();
        binding.validator().validateRelayState(relayState);
        authnRequest = binding.decoder().decodeRequest(samlRequest);
        authnRequest.getIssueInstant();
        binding.validator().validateAuthnRequest(authnRequest, samlRequest, relayState, signatureAlgorithm, signature, strictSignature);
        if (!request.isSecure()) {
            throw new IllegalArgumentException("Authn Request must use TLS.");
        }
        X509Certificate[] certs = (X509Certificate[]) request.getAttribute(CERTIFICATES_ATTR);
        boolean hasCerts = (certs != null && certs.length > 0);
        boolean hasCookie = hasValidCookie(request, authnRequest.isForceAuthn());
        if ((authnRequest.isPassive() && hasCerts) || hasCookie) {
            LOGGER.debug("Received Passive & PKI AuthnRequest.");
            org.opensaml.saml.saml2.core.Response samlpResponse;
            try {
                samlpResponse = handleLogin(authnRequest, PKI, request, null, authnRequest.isPassive(), hasCookie);
                LOGGER.debug("Passive & PKI AuthnRequest logged in successfully.");
            } catch (SecurityServiceException e) {
                LOGGER.debug(e.getMessage(), e);
                return getErrorResponse(relayState, authnRequest, StatusCode.AUTHN_FAILED, binding);
            } catch (WSSecurityException e) {
                LOGGER.debug(e.getMessage(), e);
                return getErrorResponse(relayState, authnRequest, StatusCode.REQUEST_DENIED, binding);
            } catch (SimpleSign.SignatureException | ConstraintViolationException e) {
                LOGGER.debug(e.getMessage(), e);
                return getErrorResponse(relayState, authnRequest, StatusCode.REQUEST_UNSUPPORTED, binding);
            }
            LOGGER.debug("Returning Passive & PKI SAML Response.");
            NewCookie cookie = null;
            if (hasCookie) {
                cookieCache.addActiveSp(getCookie(request).getValue(), authnRequest.getIssuer().getValue());
            } else {
                cookie = createCookie(request, samlpResponse);
                if (cookie != null) {
                    cookieCache.addActiveSp(cookie.getValue(), authnRequest.getIssuer().getValue());
                }
            }
            logAddedSp(authnRequest);
            return binding.creator().getSamlpResponse(relayState, authnRequest, samlpResponse, cookie, template);
        } else {
            LOGGER.debug("Building the JSON map to embed in the index.html page for login.");
            Document doc = DOMUtils.createDocument();
            doc.appendChild(doc.createElement("root"));
            String authn = DOM2Writer.nodeToString(OpenSAMLUtil.toDom(authnRequest, doc, false));
            String encodedAuthn = RestSecurity.deflateAndBase64Encode(authn);
            responseMap.put(PKI, hasCerts);
            responseMap.put(GUEST, guestAccess);
            responseMap.put(SAML_REQ, encodedAuthn);
            responseMap.put(RELAY_STATE, relayState);
            String assertionConsumerServiceURL = ((ResponseCreatorImpl) binding.creator()).getAssertionConsumerServiceURL(authnRequest);
            responseMap.put(ACS_URL, assertionConsumerServiceURL);
            responseMap.put(SSOConstants.SIG_ALG, signatureAlgorithm);
            responseMap.put(SSOConstants.SIGNATURE, signature);
            responseMap.put(ORIGINAL_BINDING, originalBinding);
        }
        String json = Boon.toJson(responseMap);
        LOGGER.debug("Returning index.html page.");
        responseStr = indexHtml.replace(IDP_STATE_OBJ, json);
        return Response.ok(responseStr).build();
    } catch (IllegalArgumentException e) {
        LOGGER.debug(e.getMessage(), e);
        if (authnRequest != null) {
            try {
                return getErrorResponse(relayState, authnRequest, StatusCode.REQUEST_UNSUPPORTED, binding);
            } catch (IOException | SimpleSign.SignatureException e1) {
                LOGGER.debug(e1.getMessage(), e1);
            }
        }
    } catch (UnsupportedOperationException e) {
        LOGGER.debug(e.getMessage(), e);
        if (authnRequest != null) {
            try {
                return getErrorResponse(relayState, authnRequest, StatusCode.UNSUPPORTED_BINDING, binding);
            } catch (IOException | SimpleSign.SignatureException e1) {
                LOGGER.debug(e1.getMessage(), e1);
            }
        }
    } catch (SimpleSign.SignatureException e) {
        LOGGER.debug("Unable to validate AuthRequest Signature", e);
    } catch (IOException e) {
        LOGGER.debug("Unable to decode AuthRequest", e);
    } catch (ValidationException e) {
        LOGGER.debug("AuthnRequest schema validation failed.", e);
    }
    return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
Also used : SecurityServiceException(ddf.security.service.SecurityServiceException) ValidationException(ddf.security.samlp.ValidationException) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) Document(org.w3c.dom.Document) SimpleSign(ddf.security.samlp.SimpleSign) ConstraintViolationException(net.shibboleth.utilities.java.support.logic.ConstraintViolationException) NewCookie(javax.ws.rs.core.NewCookie) ResponseCreatorImpl(org.codice.ddf.security.idp.binding.api.impl.ResponseCreatorImpl) WSSecurityException(org.apache.wss4j.common.ext.WSSecurityException) IOException(java.io.IOException) X509Certificate(java.security.cert.X509Certificate) AuthnRequest(org.opensaml.saml.saml2.core.AuthnRequest) SignableSAMLObject(org.opensaml.saml.common.SignableSAMLObject) SignableXMLObject(org.opensaml.xmlsec.signature.SignableXMLObject) XMLObject(org.opensaml.core.xml.XMLObject)

Example 60 with Request

use of org.opensaml.saml.saml2.ecp.Request in project ddf by codice.

the class IdpHandler method doPaosRequest.

private HandlerResult doPaosRequest(ServletRequest request, ServletResponse response) {
    HttpServletResponse httpServletResponse = (HttpServletResponse) response;
    HandlerResult handlerResult = new HandlerResult(HandlerResult.Status.REDIRECTED, null);
    handlerResult.setSource("idp-" + SOURCE);
    String paosHeader = ((HttpServletRequest) request).getHeader(PAOS);
    //some of these options aren't currently used, leaving these here as a marker for what
    //isn't implemented
    boolean wantChannelBind = paosHeader.contains("urn:oasis:names:tc:SAML:protocol:ext:channel-binding");
    boolean wantHok = paosHeader.contains("urn:oasis:names:tc:SAML:2.0:cm:holder-of-key");
    boolean wantSigned = paosHeader.contains("urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp:2.0:WantAuthnRequestsSigned");
    boolean wantDelegation = paosHeader.contains("urn:oasis:names:tc:SAML:2.0:conditions:delegation");
    LOGGER.trace("ECP Client requested: channel bind {}, holder of key {}, signatures {}, delegation {}", wantChannelBind, wantHok, wantSigned, wantDelegation);
    LOGGER.trace("Configuring SAML Response for POST.");
    Document doc = DOMUtils.createDocument();
    doc.appendChild(doc.createElement("root"));
    LOGGER.trace("Signing SAML POST Response.");
    String authnRequest;
    String paosRequest;
    String ecpRequest;
    String ecpRelayState;
    try {
        IDPSSODescriptor idpssoDescriptor = idpMetadata.getDescriptor();
        if (idpssoDescriptor == null) {
            throw new ServletException("IdP metadata is missing. No IDPSSODescriptor present.");
        }
        authnRequest = createAndSignAuthnRequest(true, wantSigned && idpssoDescriptor.getWantAuthnRequestsSigned());
        paosRequest = createPaosRequest((HttpServletRequest) request);
        ecpRequest = createEcpRequest();
        ecpRelayState = createEcpRelayState((HttpServletRequest) request);
    } catch (ServletException | WSSecurityException e) {
        LOGGER.debug("Unable to create and sign AuthnRequest.", e);
        httpServletResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        try {
            httpServletResponse.flushBuffer();
        } catch (IOException e1) {
            LOGGER.debug("Failed to send error response: {}", e1);
        }
        return handlerResult;
    }
    LOGGER.trace("Converting SAML Response to DOM");
    String soapMessage = soapMessageTemplate.replace("{{" + PAOS_REQUEST + "}}", paosRequest);
    soapMessage = soapMessage.replace("{{" + ECP_REQUEST + "}}", ecpRequest);
    soapMessage = soapMessage.replace("{{" + SAML_REQUEST + "}}", authnRequest);
    soapMessage = soapMessage.replace("{{" + ECP_RELAY_STATE + "}}", ecpRelayState);
    soapMessage = soapMessage.replace("{{" + PAOS_RESPONSE + "}}", "");
    try {
        httpServletResponse.setStatus(HttpServletResponse.SC_OK);
        httpServletResponse.setContentType("application/vnd.paos+xml");
        httpServletResponse.getOutputStream().print(soapMessage);
        httpServletResponse.flushBuffer();
    } catch (IOException ioe) {
        LOGGER.debug("Failed to send auth response: {}", ioe);
    }
    return handlerResult;
}
Also used : HttpServletRequest(javax.servlet.http.HttpServletRequest) ServletException(javax.servlet.ServletException) IDPSSODescriptor(org.opensaml.saml.saml2.metadata.IDPSSODescriptor) HttpServletResponse(javax.servlet.http.HttpServletResponse) HandlerResult(org.codice.ddf.security.handler.api.HandlerResult) WSSecurityException(org.apache.wss4j.common.ext.WSSecurityException) IOException(java.io.IOException) Document(org.w3c.dom.Document)

Aggregations

AuthnRequest (org.opensaml.saml.saml2.core.AuthnRequest)24 IOException (java.io.IOException)13 LogoutResponse (org.opensaml.saml.saml2.core.LogoutResponse)13 WSSecurityException (org.apache.wss4j.common.ext.WSSecurityException)12 SamlRegisteredServiceServiceProviderMetadataFacade (org.apereo.cas.support.saml.services.idp.metadata.SamlRegisteredServiceServiceProviderMetadataFacade)11 Test (org.junit.Test)10 ValidationException (ddf.security.samlp.ValidationException)9 Response (javax.ws.rs.core.Response)9 SamlRegisteredService (org.apereo.cas.support.saml.services.SamlRegisteredService)9 Assertion (org.jasig.cas.client.validation.Assertion)9 MessageContext (org.opensaml.messaging.context.MessageContext)9 Assertion (org.opensaml.saml.saml2.core.Assertion)9 Document (org.w3c.dom.Document)9 XMLStreamException (javax.xml.stream.XMLStreamException)8 LogoutRequest (org.opensaml.saml.saml2.core.LogoutRequest)8 NameID (org.opensaml.saml.saml2.core.NameID)7 ByteArrayInputStream (java.io.ByteArrayInputStream)6 SimpleSign (ddf.security.samlp.SimpleSign)5 ZonedDateTime (java.time.ZonedDateTime)5 Path (javax.ws.rs.Path)5