/* * JBoss, a division of Red Hat * Copyright 2012, Red Hat Middleware, LLC, and individual contributors as indicated * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. * */ package org.gatein.sso.agent.opensso; import org.gatein.common.logging.Logger; import org.gatein.common.logging.LoggerFactory; import org.gatein.common.util.Base64; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Parsing of SAML message received from OpenSSO CDCServlet * * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a> */ class CDMessageParser { private static final Logger log = LoggerFactory.getLogger(CDMessageParser.class); private static final Pattern SAML_SUCCESS_PATTERN = Pattern.compile("<samlp:StatusCode Value=(.*)>"); private static final Pattern SAML_DATE_CONDITIONS = Pattern.compile("<saml:Conditions NotBefore=\"(.*)\" NotOnOrAfter=\"(.*)\" >"); private static final Pattern IN_RESPONSE_TO_PATTERN = Pattern.compile("InResponseTo=\"([0-9]*)\""); private static final Pattern TOKEN_PATTERN = Pattern.compile("<saml:NameIdentifier .*>(.*)</saml:NameIdentifier>"); /** * * @param encodedInputMessage * @return decoded and parsed object with all important informations from SAML message */ public CDMessageContext parseMessage(String encodedInputMessage) { String decodedMessage = decodeMessage(encodedInputMessage); if (log.isTraceEnabled()) { log.trace("Decoded message from CDCServlet: "); log.trace(decodedMessage); } boolean success = false; Matcher m = SAML_SUCCESS_PATTERN.matcher(decodedMessage); if (m.find()) { String group = m.group(1); if (group.contains("samlp:Success")) { success = true; } } String beforeDate = null; String afterDate = null; m = SAML_DATE_CONDITIONS.matcher(decodedMessage); if (m.find()) { beforeDate = m.group(1); afterDate = m.group(2); } Integer inResponseTo = -1; m = IN_RESPONSE_TO_PATTERN.matcher(decodedMessage); if (m.find()) { inResponseTo = Integer.parseInt(m.group(1)); } String token = null; m = TOKEN_PATTERN.matcher(decodedMessage); if (m.find()) { token = m.group(1); } // Token is URL encoded in OpenSSO and we need to decode it (not encoded in OpenAM but we can decode in either case) try { token = URLDecoder.decode(token, "UTF-8"); } catch (UnsupportedEncodingException uee) { throw new RuntimeException(uee); } return new CDMessageContext(success, inResponseTo, beforeDate, afterDate, token); } /** * @param encodedInputMessage * @return decoded string, which represents SAML message received from CDCServlet */ String decodeMessage(String encodedInputMessage) { byte[] bytes = Base64.decode(encodedInputMessage); String decodedSamlMessage = new String(bytes); return decodedSamlMessage; } }