com.vmware.demo.HomeController.java Source code

Java tutorial

Introduction

Here is the source code for com.vmware.demo.HomeController.java

Source

/*****************************************************************
 * 
 * SAMLServiceProvider 1.0 Beta
 * 
 * Copyright (c) 2013 VMware, Inc. All Rights Reserved. 
 * 
 * This product is licensed to you under the Apache License, Version 2.0 (the "License").  
 * You may not use this product except in compliance with the License.  
 * 
 * This product may include a number of subcomponents with separate copyright notices 
 * and license terms. Your use of these subcomponents is subject to the terms and 
 * conditions of the subcomponent's license, as noted in the LICENSE file. 
 */
package com.vmware.demo;

import java.util.List;
import java.util.Locale;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.vmware.demo.db.dao.OrganizationHandler;
import com.vmware.demo.db.entity.IdentityProvider;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {

    @Autowired
    private OrganizationHandler organizationHandler;

    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
    private static final String COOKIE_NAME = "DemoServiceProvider";
    private static final String ATTRIBUTE_IDP_URI = "idpUri";
    private static final String ATTRIBUTE_SAML_CERT = "samlCert";
    private static final String ATTRIBUTE_ERROR_MSG = "errmsg";
    private static final String ATTRIBUTE_SUCCESS_MSG = "successmsg";
    private static final String ATTRIBUTE_SAML_CERTIFICATE = "SAMLCertificate";

    private static final String DEFAULT_SAML_CONSUMER = "https://horizon.mollocal.trcint.com";
    private static final String CONSUME_REQUEST = "/SAAS/API/1.0/POST/sso";
    private static final String METADATA_REQUEST = "/SAAS/API/1.0/GET/metadata/idp.xml";
    private static final String DEFAULT_NAMEID_FORMAT = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress";
    // "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified";
    // "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
    private static final String identityProviderId = "0";
    private static final String CONSUMER_URI = "http://serviceprovider.cloudfoundry.com/";
    private static final Object RELAY_STATE = "http://serviceprovider.cloudfoundry.com/";
    private static final String ATTRIBUTE_AUTHN_REQUEST = "authnRequest";
    private static final String ATTRIBUTE_RELAY_STATE = "RelayState";
    private static final String ATTRIBUTE_TARGET = "TARGET";
    private static final String ATTRIBUTE_META_DATA = "metaData";
    private static final String ATTRIBUTE_ACTION = "action";
    private static final String ATTRIBUTE_IDP_ID = "i";
    private static final String ATTRIBUTE_SP_ID = "s";

    @RequestMapping(value = "/sso", method = RequestMethod.GET)
    public String createForm(HttpServletRequest request, Locale locale, Model model) {
        if (null != request.getSession().getAttribute(ATTRIBUTE_SAML_CERTIFICATE)) {
            model.addAttribute(ATTRIBUTE_SAML_CERTIFICATE,
                    request.getSession().getAttribute(ATTRIBUTE_SAML_CERTIFICATE));
        }
        if (null != request.getSession().getAttribute(ATTRIBUTE_IDP_URI)) {
            model.addAttribute(ATTRIBUTE_IDP_URI, request.getSession().getAttribute(ATTRIBUTE_IDP_URI));
        } else {
            String cookieValue = null;
            Cookie[] cookies = request.getCookies();
            if (null != cookies) {
                for (Cookie cookie : cookies) {
                    if (COOKIE_NAME.equals(cookie.getName())) {
                        cookieValue = cookie.getValue();
                    }
                }
            }
            if (null != cookieValue) {
            } else {
                model.addAttribute(ATTRIBUTE_IDP_URI, DEFAULT_SAML_CONSUMER);
            }
        }
        model.addAttribute(ATTRIBUTE_META_DATA, generateMetaData(request));
        model.addAttribute(ATTRIBUTE_RELAY_STATE, getURLWithContextPath(request));
        model.addAttribute("action", "setup");
        return "home";
    }

    private String generateMetaData(HttpServletRequest request) {
        String url = getURLWithContextPath(request);
        String metaData = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
                + "<md:EntityDescriptor xmlns:md=\"urn:oasis:names:tc:SAML:2.0:metadata\" entityID=\"" + url
                + "\" validUntil=\"2022-05-09T20:03:15.334Z\">\n"
                + "   <md:SPSSODescriptor AuthnRequestsSigned=\"true\" WantAssertionsSigned=\"true\" protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\">\n"
                + "      <md:KeyDescriptor use=\"signing\">\n"
                + "         <ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">\n"
                + "            <ds:X509Data>\n"
                + "               <ds:X509Certificate>MIIFBzCCA++gAwIBAgIQDJ4ihF+4VYzLxb+qASp7IzANBgkqhkiG9w0BAQUFADCBvDELMAk\n"
                + "GA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbi\n"
                + "BUcnVzdCBOZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2UgYXQgaHR0cHM6Ly93d3cud\n"
                + "mVyaXNpZ24uY29tL3JwYSAoYykxMDE2MDQGA1UEAxMtVmVyaVNpZ24gQ2xhc3MgMyBJbnRl\n"
                + "cm5hdGlvbmFsIFNlcnZlciBDQSAtIEczMB4XDTExMTIwNzAwMDAwMFoXDTEzMTIwNzIzNTk\n"
                + "1OVowgY4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHFA1TYW\n"
                + "4gRnJhbmNpc2NvMR0wGwYDVQQKFBRTYWxlc2ZvcmNlLmNvbSwgSW5jLjEUMBIGA1UECxQLQ\n"
                + "XBwbGljYXRpb24xHTAbBgNVBAMUFHByb3h5LnNhbGVzZm9yY2UuY29tMIGfMA0GCSqGSIb3\n"
                + "DQEBAQUAA4GNADCBiQKBgQDMoSWW4dBiVScWbXno3C6n2+qR/0O+eE4lzT0Y1go53Pk+Skn\n"
                + "9sUu43Z+uZ8lOXDqmLiScTaB43ePbqIAUYimqCR9aYCLmSeNwhs68dsxcyDVqm5XIr2OZsr\n"
                + "LikhNkKPno+0fuoyOWbA35kRxBFXL66tEYlF8ETIT6G3kqt7CGVwIDAQABo4IBszCCAa8wC\n"
                + "QYDVR0TBAIwADALBgNVHQ8EBAMCBaAwQQYDVR0fBDowODA2oDSgMoYwaHR0cDovL1NWUklu\n"
                + "dGwtRzMtY3JsLnZlcmlzaWduLmNvbS9TVlJJbnRsRzMuY3JsMEQGA1UdIAQ9MDswOQYLYIZ\n"
                + "IAYb4RQEHFwMwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYT\n"
                + "AoBgNVHSUEITAfBglghkgBhvhCBAEGCCsGAQUFBwMBBggrBgEFBQcDAjByBggrBgEFBQcBA\n"
                + "QRmMGQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLnZlcmlzaWduLmNvbTA8BggrBgEFBQcw\n"
                + "AoYwaHR0cDovL1NWUkludGwtRzMtYWlhLnZlcmlzaWduLmNvbS9TVlJJbnRsRzMuY2VyMG4\n"
                + "GCCsGAQUFBwEMBGIwYKFeoFwwWjBYMFYWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFEtruS\n"
                + "iWBgy70FI4mymsSweLIQUYMCYWJGh0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28xL\n"
                + "mdpZjANBgkqhkiG9w0BAQUFAAOCAQEAVq0AapffwqicpyAu41f5pWDn7FPjgIt6lirqwo7t\n"
                + "LRMpxFuYKIMg+wvioJQ8DJ8mNyw+JnZDPxdVjDSkE2Lb+5Z5P9vKbD833jqKP5vniMMvHRf\n"
                + "tlkCqP/AI/9z6jomgQtfm3WbI7elTFJvDwA+/VdxgU86mKRpalMWDB545GxVFiO6AZ/8dvA\n"
                + "poHVHTQBfrckk9JCrH++Wq3EmErKcxzsY8LItC8qCl5HtgJy160fII0ZdF8hV5vKlrHQpo9\n"
                + "1L0c1pn+z5RB+kt8GIreME2rU3WEmtZglBKrlw3ik0sXL2CO/GCAzbh7YWkEfXtE3GcGh7N\n"
                + "xcHB+08lZiJzKwN/yg==</ds:X509Certificate>\n" + "            </ds:X509Data>\n"
                + "         </ds:KeyInfo>\n" + "      </md:KeyDescriptor>\n"
                + "      <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>\n"
                + "      <md:AttributeConsumingService isDefault=\"true\" index=\"1\"><md:ServiceName xml:lang=\"en\">Service Provider</md:ServiceName>\n"
                + "      <md:RequestedAttribute NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\" Name=\"firstName\" FriendlyName=\"firstName\"></md:RequestedAttribute>\n"
                + "      <md:RequestedAttribute NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\" Name=\"lastName\" FriendlyName=\"lastName\"></md:RequestedAttribute>\n"
                + "      </md:AttributeConsumingService>\n"
                + "      <md:AssertionConsumerService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\" Location=\""
                + url + "\" index=\"0\" isDefault=\"true\"/>\n" + "   </md:SPSSODescriptor>\n"
                + "</md:EntityDescriptor>";

        return metaData;
    }

    @RequestMapping(value = "/sso", method = RequestMethod.POST)
    public String generateRequest(HttpServletRequest request, HttpServletResponse response, Locale locale,
            Model model, String action, String SAMLResponse, String SAMLCertificate, String idpUri, String samlCert,
            String s, String i, String nameIdFormat, String consumeUrl) {
        String serviceProviderId = (String) request.getSession().getAttribute(ATTRIBUTE_SP_ID);

        // SETUP TEST
        if ("setup".equals(action)) {
            logger.info("Setup test");

            // Pass along the standard set
            model.addAttribute(ATTRIBUTE_IDP_ID, identityProviderId);
            model.addAttribute(ATTRIBUTE_SP_ID, serviceProviderId);
            model.addAttribute(ATTRIBUTE_IDP_URI, idpUri);
            model.addAttribute("nameIdFormat", DEFAULT_NAMEID_FORMAT);
            model.addAttribute("consumeUrl", idpUri + CONSUME_REQUEST);

            // Set in a cookie for next time you come back
            Cookie cookie = new Cookie(COOKIE_NAME, idpUri);
            response.addCookie(cookie);

            if (null != samlCert) {
                logger.info("Setup test using uploaded certificate.");
                try {
                    if (StringUtils.isNotEmpty(samlCert)) {
                        samlCert = SamlUtils.convertToPemFormat(SamlUtils.parsePemCertificate(samlCert));
                    } else {
                        model.addAttribute(ATTRIBUTE_ERROR_MSG,
                                "Saml certificate not provided, no validation will be done.");
                    }
                } catch (SamlException e) {
                    model.addAttribute(ATTRIBUTE_ERROR_MSG,
                            "Failed to parse certificate. " + e.getLocalizedMessage());
                    model.addAttribute(ATTRIBUTE_ACTION, "setupcert");
                    return "home";
                }
            } else {
                logger.info("Setup test using meta data url.");
                samlCert = SamlService.getInstance().loadSigningKeyFromMetaData(idpUri + METADATA_REQUEST);
                if (null == samlCert) {
                    model.addAttribute(ATTRIBUTE_ERROR_MSG, "Failed to contact service at " + idpUri
                            + ", please fetch and upload certificate manually.");
                    model.addAttribute(ATTRIBUTE_ACTION, "setupcert");
                    return "home";
                }
            }

            // Save to session
            if (!StringUtils.isEmpty(idpUri)) {
                request.getSession().setAttribute(ATTRIBUTE_IDP_URI, idpUri);
            }
            if (!StringUtils.isEmpty(samlCert)) {
                request.getSession().setAttribute(ATTRIBUTE_SAML_CERT, samlCert);
            }
            if (!StringUtils.isEmpty(s)) {
                request.getSession().setAttribute(ATTRIBUTE_SP_ID, s);
            }

            model.addAttribute(ATTRIBUTE_ACTION, "generaterequest");
        }

        // GENERATE SAML REQUEST
        if ("generaterequest".equals(action)) {
            logger.info("Generating authnRequest");

            String authnRequest = SamlService.getInstance().generateSAMLRequest(CONSUMER_URI, nameIdFormat);

            model.addAttribute("consumeUrl", consumeUrl);
            model.addAttribute(ATTRIBUTE_IDP_URI, idpUri);
            model.addAttribute(ATTRIBUTE_AUTHN_REQUEST, authnRequest);
            model.addAttribute(ATTRIBUTE_RELAY_STATE, RELAY_STATE);
            model.addAttribute(ATTRIBUTE_IDP_ID, null != i ? i : identityProviderId);
            model.addAttribute(ATTRIBUTE_SP_ID, null != s ? s : serviceProviderId);
            model.addAttribute(ATTRIBUTE_SAML_CERTIFICATE, SAMLCertificate);
            model.addAttribute(ATTRIBUTE_ACTION, "sendrequest");
        }

        // VALIDATE SAML RESPONSE
        if (null != SAMLResponse) {

            logger.info(SAMLResponse);
            String decodedResponse;
            String relayState;
            String target;
            try {
                samlCert = (String) request.getSession().getAttribute(ATTRIBUTE_SAML_CERT);
                relayState = (String) request.getParameter(ATTRIBUTE_RELAY_STATE);
                target = (String) request.getParameter(ATTRIBUTE_TARGET);
                model.addAttribute(ATTRIBUTE_RELAY_STATE, relayState);
                model.addAttribute(ATTRIBUTE_TARGET, target);

                List<IdentityProvider> identityProviders = organizationHandler.getAllIdentityProviders();
                if (null == samlCert) {
                    decodedResponse = SamlService.getInstance().validateSAMLResponse(SAMLResponse,
                            identityProviders);
                } else {
                    decodedResponse = SamlService.getInstance().validateSAMLResponse(SAMLResponse, samlCert);
                }

                if (StringUtils.isBlank(decodedResponse)) {
                    model.addAttribute(ATTRIBUTE_ERROR_MSG, "Failed to validate SAML Response");
                    model.addAttribute("SAMLResponse", decodedResponse);
                } else {
                    model.addAttribute(ATTRIBUTE_SUCCESS_MSG, "SAML Response validated.");
                    model.addAttribute("SAMLResponse", decodedResponse);
                }
            } catch (Exception e) {
                model.addAttribute("SAMLResponse", SAMLResponse);
                model.addAttribute(ATTRIBUTE_ERROR_MSG, e.getLocalizedMessage());
            }
        }

        return "home";
    }

    public static String getURLWithContextPath(HttpServletRequest request) {
        return request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
                + request.getContextPath() + "/";
    }

}