Skip to content
This repository has been archived by the owner on Oct 5, 2021. It is now read-only.

Commit

Permalink
Merge pull request #265 from supunmalinga/sso-valve
Browse files Browse the repository at this point in the history
fixes for WSAS-1936, WSAS-1937, WSAS-1945
  • Loading branch information
johannnallathamby committed May 24, 2015
2 parents f433e36 + 91777b6 commit 792a171
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,16 @@
import org.openid4java.discovery.DiscoveryInformation;
import org.opensaml.saml2.core.Assertion;
import org.opensaml.saml2.core.Response;
import org.wso2.carbon.identity.sso.agent.SSOAgentException;
import org.wso2.carbon.identity.sso.agent.util.SSOAgentUtils;

import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class LoggedInSessionBean {
public class LoggedInSessionBean implements Serializable{

private OpenID openId;

Expand All @@ -48,7 +53,7 @@ public void setOpenId(OpenID openId) {
this.openId = openId;
}

public static class AccessTokenResponseBean {
public static class AccessTokenResponseBean implements Serializable{

private String accessToken;

Expand Down Expand Up @@ -94,6 +99,11 @@ public String toString() {
Gson gson = new Gson();
return gson.toJson(this);
}

public AccessTokenResponseBean deSerialize(String accessTokenResponseBeanString) {
Gson gson = new Gson();
return gson.fromJson(accessTokenResponseBeanString, AccessTokenResponseBean.class);
}
}

public class OpenID {
Expand Down Expand Up @@ -129,7 +139,7 @@ public void setSubjectAttributes(Map<String, List<String>> subjectAttributes) {
}
}

public class SAML2SSO {
public class SAML2SSO implements Serializable{

private String subjectId;

Expand All @@ -147,6 +157,49 @@ public class SAML2SSO {

private Map<String, String> subjectAttributes;

private void writeObject(java.io.ObjectOutputStream stream)
throws IOException {

stream.writeObject(subjectId);

stream.writeObject(responseString);

stream.writeObject(assertionString);

stream.writeObject(sessionIndex);
if (accessTokenResponseBean != null) {
stream.writeObject(accessTokenResponseBean.toString());
} else {
stream.writeObject("");
}
stream.writeObject(subjectAttributes);
}

private void readObject(java.io.ObjectInputStream stream)
throws IOException, ClassNotFoundException, SSOAgentException {

subjectId = (String) stream.readObject();

responseString = (String) stream.readObject();
if (responseString != null && !"".equals(responseString)) {
response = (Response) SSOAgentUtils.unmarshall(responseString);
}

assertionString = (String) stream.readObject();
if (responseString != null && !"".equals(assertionString)) {
assertion = (Assertion) SSOAgentUtils.unmarshall(assertionString);
}

sessionIndex = (String) stream.readObject();
String accessTokenResponseBeanString = (String) stream.readObject();
if (!"".equals(accessTokenResponseBeanString)) {
accessTokenResponseBean = accessTokenResponseBean.deSerialize(accessTokenResponseBeanString);
} else {
accessTokenResponseBean = null;
}
subjectAttributes = (Map) stream.readObject();
}

public String getSubjectId() {
return subjectId;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,21 @@
package org.wso2.carbon.identity.sso.agent.saml;

import org.apache.xerces.impl.Constants;
import org.apache.xerces.util.SecurityManager;
import org.apache.xml.security.signature.XMLSignature;
import org.joda.time.DateTime;
import org.opensaml.Configuration;
import org.opensaml.DefaultBootstrap;
import org.opensaml.common.SAMLVersion;
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.common.Extensions;
import org.opensaml.saml2.core.*;
import org.opensaml.saml2.core.impl.*;
import org.opensaml.saml2.ecp.RelayState;
import org.opensaml.saml2.encryption.Decrypter;
import org.opensaml.xml.ConfigurationException;
import org.opensaml.xml.XMLObject;
import org.opensaml.xml.encryption.EncryptedKey;
import org.opensaml.xml.io.*;
import org.opensaml.xml.io.Marshaller;
import org.opensaml.xml.io.MarshallerFactory;
import org.opensaml.xml.io.MarshallingException;
import org.opensaml.xml.security.SecurityHelper;
import org.opensaml.xml.security.credential.Credential;
import org.opensaml.xml.security.keyinfo.KeyInfoCredentialResolver;
Expand All @@ -43,7 +42,6 @@
import org.opensaml.xml.util.Base64;
import org.opensaml.xml.util.XMLHelper;
import org.opensaml.xml.validation.ValidationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
Expand All @@ -53,20 +51,17 @@
import org.wso2.carbon.identity.sso.agent.SSOAgentException;
import org.wso2.carbon.identity.sso.agent.bean.LoggedInSessionBean;
import org.wso2.carbon.identity.sso.agent.bean.SSOAgentConfig;
import org.wso2.carbon.identity.sso.agent.util.CarbonEntityResolver;
import org.wso2.carbon.identity.sso.agent.util.SAMLSignatureValidator;
import org.wso2.carbon.identity.sso.agent.util.SSOAgentUtils;
import org.xml.sax.SAXException;

import javax.crypto.SecretKey;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -108,18 +103,7 @@ public SAML2SSOManager(SSOAgentConfig ssoAgentConfig) throws SSOAgentException {
} catch (InstantiationException e) {
throw new SSOAgentException("Error loading custom signature validator class", e);
}
try {
if (!bootStrapped) {
synchronized (this) {
if (!bootStrapped) {
DefaultBootstrap.bootstrap();
bootStrapped = true;
}
}
}
} catch (ConfigurationException e) {
throw new SSOAgentException("Error while bootstrapping OpenSAML library", e);
}
SSOAgentUtils.doBootstrap();
}

/**
Expand Down Expand Up @@ -280,7 +264,7 @@ public void processResponse(HttpServletRequest request, HttpServletResponse resp

if (saml2SSOResponse != null) {
String decodedResponse = new String(Base64.decode(saml2SSOResponse));
XMLObject samlObject = unmarshall(decodedResponse);
XMLObject samlObject = SSOAgentUtils.unmarshall(decodedResponse);
if (samlObject instanceof LogoutResponse) {
//This is a SAML response for a single logout request from the SP
doSLO(request);
Expand Down Expand Up @@ -310,11 +294,11 @@ public void doSLO(HttpServletRequest request) throws SSOAgentException {

XMLObject saml2Object = null;
if (request.getParameter(SSOAgentConstants.SAML2SSO.HTTP_POST_PARAM_SAML2_AUTH_REQ) != null) {
saml2Object = unmarshall(new String(Base64.decode(request.getParameter(
saml2Object = SSOAgentUtils.unmarshall(new String(Base64.decode(request.getParameter(
SSOAgentConstants.SAML2SSO.HTTP_POST_PARAM_SAML2_AUTH_REQ))));
}
if (saml2Object == null) {
saml2Object = unmarshall(new String(Base64.decode(request.getParameter(
saml2Object = SSOAgentUtils.unmarshall(new String(Base64.decode(request.getParameter(
SSOAgentConstants.SAML2SSO.HTTP_POST_PARAM_SAML2_RESP))));
}
if (saml2Object instanceof LogoutRequest) {
Expand All @@ -334,7 +318,12 @@ public void doSLO(HttpServletRequest request) throws SSOAgentException {
Set<HttpSession> sessions =
SSOAgentSessionManager.invalidateAllSessions(request.getSession(false));
for (HttpSession session : sessions) {
session.invalidate();
try {
session.invalidate();
} catch (IllegalStateException ignore) {
//ignore
//session is already invalidated
}
}
}
} else {
Expand All @@ -350,7 +339,7 @@ protected void processSSOResponse(HttpServletRequest request) throws SSOAgentExc
String saml2ResponseString =
new String(Base64.decode(request.getParameter(
SSOAgentConstants.SAML2SSO.HTTP_POST_PARAM_SAML2_RESP)));
Response saml2Response = (Response) unmarshall(saml2ResponseString);
Response saml2Response = (Response) SSOAgentUtils.unmarshall(saml2ResponseString);
sessionBean.getSAML2SSO().setResponseString(saml2ResponseString);
sessionBean.getSAML2SSO().setSAMLResponse(saml2Response);

Expand Down Expand Up @@ -562,39 +551,6 @@ protected String encodeRequestMessage(RequestAbstractType requestMessage, String
}
}

protected XMLObject unmarshall(String saml2SSOString) throws SSOAgentException {

try {
String decodedString = decodeHTMLCharacters(saml2SSOString);
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);

documentBuilderFactory.setExpandEntityReferences(false);
documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
SecurityManager securityManager = new SecurityManager();
securityManager.setEntityExpansionLimit(ENTITY_EXPANSION_LIMIT);
documentBuilderFactory.setAttribute(SECURITY_MANAGER_PROPERTY, securityManager);

DocumentBuilder docBuilder = documentBuilderFactory.newDocumentBuilder();
docBuilder.setEntityResolver(new CarbonEntityResolver());
ByteArrayInputStream is = new ByteArrayInputStream(decodedString.getBytes());
Document document = docBuilder.parse(is);
Element element = document.getDocumentElement();
UnmarshallerFactory unmarshallerFactory = Configuration.getUnmarshallerFactory();
Unmarshaller unmarshaller = unmarshallerFactory.getUnmarshaller(element);
return unmarshaller.unmarshall(element);
} catch (ParserConfigurationException e) {
throw new SSOAgentException("Error in unmarshalling SAML2SSO Request from the encoded String", e);
} catch (UnmarshallingException e) {
throw new SSOAgentException("Error in unmarshalling SAML2SSO Request from the encoded String", e);
} catch (SAXException e) {
throw new SSOAgentException("Error in unmarshalling SAML2SSO Request from the encoded String", e);
} catch (IOException e) {
throw new SSOAgentException("Error in unmarshalling SAML2SSO Request from the encoded String", e);
}

}

private String decodeHTMLCharacters(String encodedStr) {

return encodedStr.replaceAll("&amp;", "&").replaceAll("&lt;", "<").replaceAll("&gt;", ">")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,33 @@

import org.apache.xml.security.c14n.Canonicalizer;
import org.apache.xml.security.signature.XMLSignature;
import org.opensaml.Configuration;
import org.opensaml.DefaultBootstrap;
import org.opensaml.saml2.core.AuthnRequest;
import org.opensaml.saml2.core.LogoutRequest;
import org.opensaml.xml.ConfigurationException;
import org.opensaml.xml.XMLObject;
import org.opensaml.xml.XMLObjectBuilder;
import org.opensaml.xml.io.Marshaller;
import org.opensaml.xml.io.MarshallerFactory;
import org.opensaml.xml.io.*;
import org.opensaml.xml.security.x509.X509Credential;
import org.opensaml.xml.signature.KeyInfo;
import org.opensaml.xml.signature.Signature;
import org.opensaml.xml.signature.Signer;
import org.opensaml.xml.signature.X509Data;
import org.opensaml.xml.util.Base64;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.wso2.carbon.identity.sso.agent.SSOAgentConstants;
import org.wso2.carbon.identity.sso.agent.SSOAgentException;
import org.xml.sax.SAXException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.Writer;
import java.net.URLEncoder;
Expand All @@ -51,6 +60,7 @@
public class SSOAgentUtils {

private static Logger LOGGER = Logger.getLogger(SSOAgentConstants.LOGGER_NAME);
private static boolean isBootStrapped = false;

/**
* Generates a unique Id for Authentication Requests
Expand Down Expand Up @@ -78,6 +88,17 @@ public static String createID() {
return String.valueOf(chars);
}

public static void doBootstrap() throws SSOAgentException {
if (!isBootStrapped) {
try {
DefaultBootstrap.bootstrap();
isBootStrapped = true;
} catch (ConfigurationException e) {
throw new SSOAgentException("Error in bootstrapping the OpenSAML2 library", e);
}
}
}

/**
* Sign the SAML AuthnRequest message
*
Expand All @@ -88,7 +109,8 @@ public static String createID() {
* @throws org.wso2.carbon.identity.sso.agent.SSOAgentException
*/
public static AuthnRequest setSignature(AuthnRequest authnRequest, String signatureAlgorithm,
X509Credential cred) throws SSOAgentException {
X509Credential cred) throws SSOAgentException {
doBootstrap();
try {
Signature signature = (Signature) buildXMLObject(Signature.DEFAULT_ELEMENT_NAME);
signature.setSigningCredential(cred);
Expand Down Expand Up @@ -186,6 +208,7 @@ public static LogoutRequest setSignature(LogoutRequest logoutRequest, String sig

public static void addDeflateSignatureToHTTPQueryString(StringBuilder httpQueryString,
X509Credential cred) throws SSOAgentException {
doBootstrap();
try {
httpQueryString.append("&SigAlg="
+ URLEncoder.encode(XMLSignature.ALGO_ID_SIGNATURE_RSA, "UTF-8").trim());
Expand All @@ -212,6 +235,7 @@ public static void addDeflateSignatureToHTTPQueryString(StringBuilder httpQueryS
* @throws SSOAgentException
*/
private static XMLObject buildXMLObject(QName objectQName) throws SSOAgentException {
doBootstrap();
XMLObjectBuilder builder =
org.opensaml.xml.Configuration.getBuilderFactory()
.getBuilder(objectQName);
Expand Down Expand Up @@ -244,4 +268,31 @@ public static void sendPostResponse(HttpServletRequest request, HttpServletRespo
}
}
}

public static XMLObject unmarshall(String saml2SSOString) throws SSOAgentException {

doBootstrap();
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setExpandEntityReferences(false);
documentBuilderFactory.setNamespaceAware(true);
try {
DocumentBuilder docBuilder = documentBuilderFactory.newDocumentBuilder();
docBuilder.setEntityResolver(new CarbonEntityResolver());
ByteArrayInputStream is = new ByteArrayInputStream(saml2SSOString.getBytes());
Document document = docBuilder.parse(is);
Element element = document.getDocumentElement();
UnmarshallerFactory unmarshallerFactory = Configuration.getUnmarshallerFactory();
Unmarshaller unmarshaller = unmarshallerFactory.getUnmarshaller(element);
return unmarshaller.unmarshall(element);
} catch (ParserConfigurationException e) {
throw new SSOAgentException("Error in unmarshalling SAML2SSO Request from the encoded String", e);
} catch (UnmarshallingException e) {
throw new SSOAgentException("Error in unmarshalling SAML2SSO Request from the encoded String", e);
} catch (SAXException e) {
throw new SSOAgentException("Error in unmarshalling SAML2SSO Request from the encoded String", e);
} catch (IOException e) {
throw new SSOAgentException("Error in unmarshalling SAML2SSO Request from the encoded String", e);
}

}
}

0 comments on commit 792a171

Please sign in to comment.