net.unicon.cas.chalkwire.servlet.CasChalkWireHttpServlet.java Source code

Java tutorial

Introduction

Here is the source code for net.unicon.cas.chalkwire.servlet.CasChalkWireHttpServlet.java

Source

/**
Licensed to Jasig under one or more contributor license
agreements. See the NOTICE file distributed with this work
for additional information regarding copyright ownership.
Jasig licenses this file to you 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 net.unicon.cas.chalkwire.servlet;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Properties;
import java.util.UUID;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class CasChalkWireHttpServlet extends HttpServlet {

    private static final String ENCODING_TYPE = "UTF-8";
    private static final long serialVersionUID = -5315331084020083938L;
    private static final String CHALK_WIRE_PARAM_COURSE_ID = "course";
    private static final String CHALK_WIRE_PARAM_TOP_SECTION_ID = "0";

    private static final Log logger = LogFactory.getLog(CasChalkWireHttpServlet.class);

    private Properties properties;

    public CasChalkWireHttpServlet() throws IOException {
        InputStream stream = null;
        try {
            stream = getClass().getClassLoader().getResourceAsStream("chalkwire.properties");
            properties = new Properties();
            properties.load(stream);
        } finally {
            if (stream != null)
                stream.close();
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        throw new ServletException("POST is not supported by " + getClass().getName());
    }

    private String getChalkWireServerUrl() {
        return properties.getProperty("chalkwire.server.url");
    }

    private String getChalkWireCustomerId() {
        return properties.getProperty("chalkwire.customer.id");
    }

    private String getChalkWireCustomerDomain() {
        return properties.getProperty("chalkwire.customer.domain");
    }

    private String getChalkWireSharedSecretKey() {
        return properties.getProperty("chalkwire.shared.secret.key");
    }

    public static String generateMAC(final String sharedSecret, final String data) throws IOException {
        final Mac mac = setKey(sharedSecret);
        final byte[] signBytes = mac.doFinal(data.getBytes("UTF8"));
        final String signature = encodeBase64(signBytes);
        return signature;
    }

    private static String encodeBase64(final byte[] signBytes) {
        return Base64.encodeBase64URLSafeString(signBytes);
    }

    private static Mac setKey(final String sharedSecret) throws IOException {
        try {
            final Mac mac = Mac.getInstance("HmacSHA1");
            final byte[] keyBytes = sharedSecret.getBytes("UTF8");
            final SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA1");
            mac.init(signingKey);
            return mac;
        } catch (Exception e) {
            throw new IOException(e);
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        try {
            if (req.getRemoteUser() == null)
                throw new ServletException("User is not authenticated. Check the CAS client log files for details");

            String userId = req.getUserPrincipal().getName();

            if (logger.isDebugEnabled())
                logger.debug("Received login request from user " + userId);

            final String URL = buildSingleSignOnTokenRequestUrl(userId);

            if (logger.isDebugEnabled()) {
                logger.debug("Requesing security token from ePortfolio Connect Server");
                logger.debug("Requesting url:" + URL);
            }

            /*
             * Send the single sign-on request url to server and parse the response.
             */
            ChalkWireResponseParser parser = new ChalkWireResponseParser(URL);

            if (logger.isDebugEnabled())
                logger.debug("Response is success:" + parser.isSuccess());

            if (parser.isSuccess()) {

                if (logger.isDebugEnabled())
                    logger.debug("url: " + parser.getURL());

                if (logger.isDebugEnabled())
                    logger.debug("token: " + parser.getToken());

                String finalURL = buildFinalSingleSignOnUrl(userId, parser);

                if (logger.isDebugEnabled())
                    logger.debug("Single sign-on URL:" + finalURL);

                parser = new ChalkWireResponseParser(finalURL);

                if (!parser.isSuccess())
                    throw new ServletException(parser.getMessage());

                resp.sendRedirect(finalURL);

            } else
                throw new ServletException(parser.getMessage());

        } catch (ServletException e) {
            logger.error(e.getMessage(), e);

            String casServerLoginUrl = getServletContext().getInitParameter("casServerLoginUrl");

            String service = req.getRequestURL().toString();
            casServerLoginUrl += "login?renew=true&service=" + URLEncoder.encode(service, ENCODING_TYPE);

            RequestDispatcher dispatcher = getServletContext()
                    .getRequestDispatcher("/WEB-INF/view/jsp/chalkWireError.jsp");
            req.setAttribute("exception", e);

            if (logger.isDebugEnabled())
                logger.debug("Constructed CAS login url:" + casServerLoginUrl);

            req.setAttribute("loginUrl", casServerLoginUrl);
            dispatcher.forward(req, resp);

        }

    }

    private String buildFinalSingleSignOnUrl(String userId, final ChalkWireResponseParser parser)
            throws UnsupportedEncodingException {

        StringBuilder bldr = new StringBuilder(parser.getURL());

        bldr.append("?act=single_signon" + "&studentId=");
        bldr.append(URLEncoder.encode(userId, ENCODING_TYPE));
        bldr.append("&tocSecId=");
        bldr.append(URLEncoder.encode(CHALK_WIRE_PARAM_TOP_SECTION_ID, ENCODING_TYPE));
        bldr.append("&courseId=");
        bldr.append(URLEncoder.encode(CHALK_WIRE_PARAM_COURSE_ID, ENCODING_TYPE));
        bldr.append("&cus=");
        bldr.append(URLEncoder.encode(getChalkWireCustomerId(), ENCODING_TYPE));
        bldr.append("&token=");
        bldr.append(parser.getToken());

        return bldr.toString();
    }

    /** 
     * We need to get a security token from the CWConnect server. We'll make the request
     * in the form of: customerId/mac/guid/timestamp/studentId/firstname/lastname/email/courseId/tocSectionId
     */
    private String buildSingleSignOnTokenRequestUrl(String userId) throws IOException {

        final long time = System.currentTimeMillis();
        final String timestamp = String.valueOf(time);

        final String userGUID = UUID.randomUUID().toString();

        final String givenName = userId;
        final String familyName = userId;

        final String getEmailAddress = userId + "@" + getChalkWireCustomerDomain();

        final String s = timestamp + userGUID + getChalkWireSharedSecretKey();
        String mac = generateMAC(getChalkWireSharedSecretKey(), s);

        StringBuilder bldr = new StringBuilder(getChalkWireServerUrl());
        bldr.append("/epcs/sign-on/");
        bldr.append(URLEncoder.encode(getChalkWireCustomerId(), ENCODING_TYPE));
        bldr.append("/");
        bldr.append(URLEncoder.encode(mac, ENCODING_TYPE));
        bldr.append("/");
        bldr.append(URLEncoder.encode(userGUID, ENCODING_TYPE));
        bldr.append("/");
        bldr.append(URLEncoder.encode(timestamp, ENCODING_TYPE));
        bldr.append("/");
        bldr.append(URLEncoder.encode(userId, ENCODING_TYPE));
        bldr.append("/");
        bldr.append(URLEncoder.encode(givenName, ENCODING_TYPE));
        bldr.append("/");
        bldr.append(URLEncoder.encode(familyName, ENCODING_TYPE));
        bldr.append("/");
        bldr.append(URLEncoder.encode(getEmailAddress, ENCODING_TYPE));
        bldr.append("/");
        bldr.append(URLEncoder.encode(CHALK_WIRE_PARAM_COURSE_ID, ENCODING_TYPE));
        bldr.append("/");
        bldr.append(URLEncoder.encode(CHALK_WIRE_PARAM_TOP_SECTION_ID, ENCODING_TYPE));

        return bldr.toString();

    }
}