OpenSAMLv3 HTTPPostEncoder sending OPTIONS request instead of POST

Mark Watson mjw4tson at gmail.com
Fri Mar 15 20:21:32 EDT 2019


Hi all,

I've just started migrating my older OpenSAMLv2 code to use the newer v3
library and I'm having some trouble getting the HTTPPostEncoder to work for
single logout.

I've built a LogoutRequest and wrapped it in a MessageContext, but when I
call the encode method the subsequent SAML request is sent using an OPTIONS
request. My understanding of OPTIONS is that it's used for CORS to
determine if the destination server will accept the subsequent requests,
but when I use a SAML trace tool my LogoutRequest is being sent in the
OPTIONS request body. Any idea where I could be going wrong? Here's my code:

public class IdentityProviderSingleLogoutRedirect {

    private void redirectUserForLogout(HttpServletResponse response, String
username, String sessionIndex) {

        LogoutRequestMessageContextGenerator generator = new
LogoutRequestMessageContextGenerator(IdentityProvider.get(),
ServiceProvider.get());

        MessageContext<SAMLObject> context = generator.generate(username,
sessionIndex);

        redirectUserWithRequest(response, context);

    }


    /**

     * Redirects client to Identity Provider with signed LogoutRequest

     * @param response

     * @param context

     */

    private void redirectUserWithRequest(HttpServletResponse response,
MessageContext<SAMLObject> context) {

        HTTPPostEncoder encoder = new HTTPPostEncoder();

        encoder.setMessageContext(context);

        encoder.setHttpServletResponse(response);

        encoder.setVelocityEngine(buildVelocityEngine());


        try {

            encoder.initialize();

        } catch (ComponentInitializationException e) {

            throw Error.HTTPPOSTENCODER_INITIALIZATION_ERROR.with(e);

        }


        try {

            logger.debug("Redirecting to Identity Provider");

            encoder.encode();

        } catch (MessageEncodingException e) {

            throw Error.IDENTITY_PROVIDER_REDIRECT_ERROR.with(e);

        }

    }


    private VelocityEngine buildVelocityEngine() {

        VelocityEngine velocityEngine = new VelocityEngine();

        velocityEngine.setProperty(RuntimeConstants.ENCODING_DEFAULT,
"UTF-8");

        velocityEngine.setProperty(RuntimeConstants.OUTPUT_ENCODING,
"UTF-8");

        velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER,
"classpath");

        velocityEngine.setProperty("classpath.resource.loader.class",
"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");

        velocityEngine.init();


        return velocityEngine;

    }

}



public class LogoutRequestMessageContextGenerator {


    private IdentityProvider identityProvider;


    private ServiceProvider  serviceProvider;


    public LogoutRequestMessageContextGenerator(IdentityProvider
identityProvider, ServiceProvider serviceProvider) {

        if (identityProvider == null) {

            throw
Error.LOGOUT_REQUEST_GENERATOR_CANT_BE_INITIALIZED_IDP.with();

        }


        if (serviceProvider == null) {

            throw
Error.LOGOUT_REQUEST_GENERATOR_CANT_BE_INITIALIZED_SP.with();

        }


        this.identityProvider = identityProvider;

        this.serviceProvider = serviceProvider;

    }


    public MessageContext<SAMLObject> generate(String username, String
sessionIndex) {

        MessageContext<SAMLObject> context = new MessageContext<>();

        SAMLEndpointContext endpointContext =
context.getSubcontext(SAMLPeerEntityContext.class, true)

                        .getSubcontext(SAMLEndpointContext.class, true);


        endpointContext.setEndpoint(buildIdPSingleLogoutService());

        LogoutRequest logoutRequest = buildLogoutRequest(username,
sessionIndex);

        context.setMessage(logoutRequest);


        SignatureSigningParameters signatureSigningParameters = new
SignatureSigningParameters();


signatureSigningParameters.setSigningCredential(serviceProvider.getSigningCredential());


signatureSigningParameters.setSignatureAlgorithm(serviceProvider.getSignatureAlgorithm());


        SecurityParametersContext securityParameterContext =
context.getSubcontext(SecurityParametersContext.class, true);


securityParameterContext.setSignatureSigningParameters(signatureSigningParameters);


        return context;

    }


    /**

     * Builds an OpenSAML SingleSignOnService object

     * @return

     */

    private Endpoint buildIdPSingleLogoutService() {

        SingleLogoutService endpoint =
OpenSAMLUtils.buildSAMLObject(SingleLogoutService.DEFAULT_ELEMENT_NAME);

        endpoint.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);

        endpoint.setLocation(identityProvider.getLogoutUrl());


        return endpoint;

    }


    /**

     * Builds an OpenSAML LogoutRequest object

     * @return

     */

    private LogoutRequest buildLogoutRequest(String username, String
sessionIndex) {

        LogoutRequest logoutRequest =
OpenSAMLUtils.buildSAMLObject(LogoutRequest.DEFAULT_ELEMENT_NAME);

        logoutRequest.setID(OpenSAMLUtils.generateSecureRandomId());

        logoutRequest.setIssueInstant(new DateTime());

        logoutRequest.setDestination(identityProvider.getLogoutUrl());

        logoutRequest.setIssuer(serviceProvider.buildIssuer());

        logoutRequest.setNameID(buildNameID(username));


logoutRequest.getSessionIndexes().add(buildSessionIndex(sessionIndex));

        logoutRequest.setReason(LogoutRequest.USER_REASON);


        Signature signature = serviceProvider.buildSignature();


        if (signature != null) {

            logoutRequest.setSignature(signature);

        }


        try {


XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(logoutRequest).marshall(logoutRequest);

        } catch (MarshallingException e) {

            throw
Error.LOGOUT_REQUEST_GENERATOR_CANT_MARSHALL_REQUEST.with();

        }


        if (signature != null) {

            try {

                Signer.signObject(signature);

            } catch (SignatureException e) {

                Error.LOGOUT_REQUEST_GENERATOR_SIGNING_ERROR.with();

            }

        }


        return logoutRequest;

    }


    private NameID buildNameID(String username) {

        NameID nameId =
OpenSAMLUtils.buildSAMLObject(NameID.DEFAULT_ELEMENT_NAME);

        nameId.setValue(username);

        nameId.setFormat(identityProvider.getNameIDFormat());


        return nameId;

    }


    private SessionIndex buildSessionIndex(String sessionId) {

        SessionIndex sessionIndex =
OpenSAMLUtils.buildSAMLObject(SessionIndex.DEFAULT_ELEMENT_NAME);

        sessionIndex.setSessionIndex(sessionId);


        return sessionIndex;

    }

}


Thanks in advance for the help!


-Mark
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://shibboleth.net/pipermail/dev/attachments/20190315/1a5f4789/attachment-0001.html>


More information about the dev mailing list