Author: anil.saldhana(a)jboss.com
Date: 2012-01-31 17:13:31 -0500 (Tue, 31 Jan 2012)
New Revision: 1358
Added:
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/workflow/AbstractSAML2RedirectWithSignatureTestCase.java
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/workflow/SAML2LogoutSignatureTomcatWorkflowUnitTestCase.java
Modified:
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/web/
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/web/handlers/saml2/
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/web/handlers/saml2/SAML2AuthenticationHandler.java
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/web/util/
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/web/util/RedirectBindingSignatureUtil.java
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/mock/MockCatalinaContext.java
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/mock/MockCatalinaRequest.java
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/workflow/
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/workflow/SAML2RedirectSignatureTomcatWorkflowUnitTestCase.java
Log:
merge changes from -r1328 to 1337
Property changes on:
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/web
___________________________________________________________________
Added: svn:mergeinfo
+
/federation/trunk/picketlink-bindings/src/main/java/org/picketlink/identity/federation/web:1159-1173,1192-1228
/federation/trunk/picketlink-bindings-jboss/src/main/java/org/picketlink/identity/federation/web:1159-1173,1192-1228
/federation/trunk/picketlink-fed-api/src/main/java/org/picketlink/identity/federation/web:1152-1154,1159-1173,1192-1228
/federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/web:1152-1173,1192-1228
/federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/web:1152-1154,1159-1173
/federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web:1152-1173,1329-1337
Modified:
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java
===================================================================
---
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java 2012-01-31
22:12:56 UTC (rev 1357)
+++
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java 2012-01-31
22:13:31 UTC (rev 1358)
@@ -89,6 +89,10 @@
String SAML_REQUEST_KEY = "SAMLRequest";
String SAML_RESPONSE_KEY = "SAMLResponse";
+
+ String SAML_SIG_ALG_REQUEST_KEY = "SigAlg";
+
+ String SAML_SIGNATURE_REQUEST_KEY = "Signature";
String DECRYPTING_KEY = "DECRYPTING_KEY";
Property changes on:
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java
___________________________________________________________________
Modified: svn:mergeinfo
-
/federation/trunk/picketlink-bindings/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java:1159-1173,1192-1228
/federation/trunk/picketlink-bindings-jboss/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java:1159-1173,1192-1228
/federation/trunk/picketlink-fed-api/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java:1152-1154,1159-1173,1192-1228
/federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java:1152-1173,1192-1228
/federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java:1152-1154,1159-1173
/federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java:1138-1141,1152-1173
+
/federation/trunk/picketlink-bindings/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java:1159-1173,1192-1228
/federation/trunk/picketlink-bindings-jboss/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java:1159-1173,1192-1228
/federation/trunk/picketlink-fed-api/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java:1152-1154,1159-1173,1192-1228
/federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java:1152-1173,1192-1228
/federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java:1152-1154,1159-1173
/federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java:1138-1141,1152-1173,1329-1337
Property changes on:
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/web/handlers/saml2
___________________________________________________________________
Modified: svn:mergeinfo
-
/federation/trunk/picketlink-bindings/src/main/java/org/picketlink/identity/federation/web/handlers/saml2:1159-1173,1192-1228
/federation/trunk/picketlink-bindings-jboss/src/main/java/org/picketlink/identity/federation/web/handlers/saml2:1159-1173,1192-1228
/federation/trunk/picketlink-fed-api/src/main/java/org/picketlink/identity/federation/web/handlers/saml2:1152-1154,1159-1173,1192-1228
/federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/web/handlers/saml2:1152-1173,1192-1228
/federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/web/handlers/saml2:1152-1154,1159-1173
/federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/handlers/saml2:1144-1147,1152-1173
+
/federation/trunk/picketlink-bindings/src/main/java/org/picketlink/identity/federation/web/handlers/saml2:1159-1173,1192-1228
/federation/trunk/picketlink-bindings-jboss/src/main/java/org/picketlink/identity/federation/web/handlers/saml2:1159-1173,1192-1228
/federation/trunk/picketlink-fed-api/src/main/java/org/picketlink/identity/federation/web/handlers/saml2:1152-1154,1159-1173,1192-1228
/federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/web/handlers/saml2:1152-1173,1192-1228
/federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/web/handlers/saml2:1152-1154,1159-1173
/federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/handlers/saml2:1144-1147,1152-1173,1329-1337
Property changes on:
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/web/handlers/saml2/SAML2AuthenticationHandler.java
___________________________________________________________________
Modified: svn:mergeinfo
-
/federation/trunk/picketlink-bindings/src/main/java/org/picketlink/identity/federation/web/handlers/saml2/SAML2AuthenticationHandler.java:1159-1173,1192-1228
/federation/trunk/picketlink-bindings-jboss/src/main/java/org/picketlink/identity/federation/web/handlers/saml2/SAML2AuthenticationHandler.java:1159-1173,1192-1228
/federation/trunk/picketlink-fed-api/src/main/java/org/picketlink/identity/federation/web/handlers/saml2/SAML2AuthenticationHandler.java:1152-1154,1159-1173,1192-1228
/federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/web/handlers/saml2/SAML2AuthenticationHandler.java:1152-1173,1192-1228
/federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/web/handlers/saml2/SAML2AuthenticationHandler.java:1152-1154,1159-1173
/federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/handlers/saml2/SAML2AuthenticationHandler.java:1144-1147,1152-1173,1295-1298
+
/federation/trunk/picketlink-bindings/src/main/java/org/picketlink/identity/federation/web/handlers/saml2/SAML2AuthenticationHandler.java:1159-1173,1192-1228
/federation/trunk/picketlink-bindings-jboss/src/main/java/org/picketlink/identity/federation/web/handlers/saml2/SAML2AuthenticationHandler.java:1159-1173,1192-1228
/federation/trunk/picketlink-fed-api/src/main/java/org/picketlink/identity/federation/web/handlers/saml2/SAML2AuthenticationHandler.java:1152-1154,1159-1173,1192-1228
/federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/web/handlers/saml2/SAML2AuthenticationHandler.java:1152-1173,1192-1228
/federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/web/handlers/saml2/SAML2AuthenticationHandler.java:1152-1154,1159-1173
/federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/handlers/saml2/SAML2AuthenticationHandler.java:1144-1147,1152-1173,1295-1298,1329-1337
Property changes on:
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/web/util
___________________________________________________________________
Modified: svn:mergeinfo
-
/federation/trunk/picketlink-bindings/src/main/java/org/picketlink/identity/federation/web/util:1159-1173,1192-1228
/federation/trunk/picketlink-bindings-jboss/src/main/java/org/picketlink/identity/federation/web/util:1159-1173,1192-1228
/federation/trunk/picketlink-fed-api/src/main/java/org/picketlink/identity/federation/web/util:1152-1154,1159-1173,1192-1228
/federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/web/util:1152-1173,1192-1228
/federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/web/util:1152-1154,1159-1173
/federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/util:1152-1173,1302-1320
+
/federation/trunk/picketlink-bindings/src/main/java/org/picketlink/identity/federation/web/util:1159-1173,1192-1228
/federation/trunk/picketlink-bindings-jboss/src/main/java/org/picketlink/identity/federation/web/util:1159-1173,1192-1228
/federation/trunk/picketlink-fed-api/src/main/java/org/picketlink/identity/federation/web/util:1152-1154,1159-1173,1192-1228
/federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/web/util:1152-1173,1192-1228
/federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/web/util:1152-1154,1159-1173
/federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/util:1152-1173,1302-1320,1329-1337
Modified:
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/web/util/RedirectBindingSignatureUtil.java
===================================================================
---
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/web/util/RedirectBindingSignatureUtil.java 2012-01-31
22:12:56 UTC (rev 1357)
+++
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/web/util/RedirectBindingSignatureUtil.java 2012-01-31
22:13:31 UTC (rev 1358)
@@ -52,6 +52,7 @@
*/
public class RedirectBindingSignatureUtil
{
+
/**
* Get the URL for the SAML request that contains the signature and signature
algorithm
* @param authRequest
@@ -69,16 +70,19 @@
// Deal with the original request
StringWriter sw = new StringWriter();
+
saml2Request.marshall(authRequest, sw);
//URL Encode the Request
String urlEncodedRequest =
RedirectBindingUtil.deflateBase64URLEncode(sw.toString());
String urlEncodedRelayState = null;
+
if (isNotNull(relayState))
urlEncodedRelayState = URLEncoder.encode(relayState, "UTF-8");
- byte[] sigValue = computeSignature("SAMLRequest=" + urlEncodedRequest,
urlEncodedRelayState, signingKey);
+ byte[] sigValue = computeSignature(GeneralConstants.SAML_REQUEST_KEY,
urlEncodedRequest, urlEncodedRelayState,
+ signingKey);
//Now construct the URL
return getRequestRedirectURLWithSignature(urlEncodedRequest, urlEncodedRelayState,
sigValue,
@@ -110,7 +114,8 @@
if (isNotNull(relayState))
urlEncodedRelayState = URLEncoder.encode(relayState, "UTF-8");
- byte[] sigValue = computeSignature("SAMLResponse=" + urlEncodedResponse,
urlEncodedRelayState, signingKey);
+ byte[] sigValue = computeSignature(GeneralConstants.SAML_RESPONSE_KEY,
urlEncodedResponse, urlEncodedRelayState,
+ signingKey);
//Now construct the URL
return getResponseRedirectURLWithSignature(urlEncodedResponse,
urlEncodedRelayState, sigValue,
@@ -129,7 +134,8 @@
public static String getSAMLRequestURLWithSignature(String urlEncodedRequest, String
urlEncodedRelayState,
PrivateKey signingKey) throws IOException, GeneralSecurityException
{
- byte[] sigValue = computeSignature("SAMLRequest=" + urlEncodedRequest,
urlEncodedRelayState, signingKey);
+ byte[] sigValue = computeSignature(GeneralConstants.SAML_REQUEST_KEY,
urlEncodedRequest, urlEncodedRelayState,
+ signingKey);
return getRequestRedirectURLWithSignature(urlEncodedRequest, urlEncodedRelayState,
sigValue,
signingKey.getAlgorithm());
}
@@ -146,7 +152,8 @@
public static String getSAMLResponseURLWithSignature(String urlEncodedResponse, String
urlEncodedRelayState,
PrivateKey signingKey) throws IOException, GeneralSecurityException
{
- byte[] sigValue = computeSignature("SAMLResponse=" + urlEncodedResponse,
urlEncodedRelayState, signingKey);
+ byte[] sigValue = computeSignature(GeneralConstants.SAML_RESPONSE_KEY,
urlEncodedResponse, urlEncodedRelayState,
+ signingKey);
return getResponseRedirectURLWithSignature(urlEncodedResponse,
urlEncodedRelayState, sigValue,
signingKey.getAlgorithm());
}
@@ -163,7 +170,7 @@
public static AuthnRequestType getRequestFromSignedURL(String signedURL) throws
ConfigurationException,
ProcessingException, ParsingException, IOException
{
- String samlRequestTokenValue = getTokenValue(signedURL, "SAMLRequest");
+ String samlRequestTokenValue = getTokenValue(signedURL,
GeneralConstants.SAML_REQUEST_KEY);
SAML2Request saml2Request = new SAML2Request();
return
saml2Request.getAuthnRequestType(RedirectBindingUtil.urlBase64DeflateDecode(samlRequestTokenValue));
@@ -177,7 +184,7 @@
*/
public static byte[] getSignatureValueFromSignedURL(String signedURL) throws
IOException
{
- String sigValueTokenValue = getTokenValue(signedURL, "Signature");
+ String sigValueTokenValue = getTokenValue(signedURL,
GeneralConstants.SAML_SIGNATURE_REQUEST_KEY);
if (sigValueTokenValue == null)
throw new IllegalArgumentException(ErrorCodes.NULL_VALUE + "Signature Token
is not present");
return RedirectBindingUtil.urlBase64Decode(sigValueTokenValue);
@@ -199,40 +206,58 @@
throws UnsupportedEncodingException, GeneralSecurityException
{
//Construct the url again
- String reqFromURL = RedirectBindingSignatureUtil.getTokenValue(queryString,
"SAMLRequest");
+ StringBuilder sb = new StringBuilder();
+
+ if (isRequestQueryString(queryString))
+ {
+ addParameter(sb, GeneralConstants.SAML_REQUEST_KEY,
+ RedirectBindingSignatureUtil.getTokenValue(queryString,
GeneralConstants.SAML_REQUEST_KEY));
+ }
+ else
+ {
+ addParameter(sb, GeneralConstants.SAML_RESPONSE_KEY,
+ RedirectBindingSignatureUtil.getTokenValue(queryString,
GeneralConstants.SAML_RESPONSE_KEY));
+ }
+
String relayStateFromURL = RedirectBindingSignatureUtil.getTokenValue(queryString,
GeneralConstants.RELAY_STATE);
- String sigAlgFromURL = RedirectBindingSignatureUtil.getTokenValue(queryString,
"SigAlg");
- StringBuilder sb = new StringBuilder();
- sb.append("SAMLRequest=").append(reqFromURL);
-
if (isNotNull(relayStateFromURL))
{
- sb.append("&RelayState=").append(relayStateFromURL);
+ addParameter(sb, GeneralConstants.RELAY_STATE, relayStateFromURL);
}
- sb.append("&SigAlg=").append(sigAlgFromURL);
+ addParameter(sb, GeneralConstants.SAML_SIG_ALG_REQUEST_KEY,
+ RedirectBindingSignatureUtil.getTokenValue(queryString,
GeneralConstants.SAML_SIG_ALG_REQUEST_KEY));
+
return SignatureUtil.validate(sb.toString().getBytes("UTF-8"), sigValue,
validatingKey);
}
+ private static boolean isRequestQueryString(String queryString)
+ {
+ return RedirectBindingSignatureUtil.getTokenValue(queryString,
GeneralConstants.SAML_REQUEST_KEY) != null;
+ }
+
//***************** Private Methods **************
- private static byte[] computeSignature(String requestOrResponseKeyValuePair, String
urlEncodedRelayState,
+ private static byte[] computeSignature(String samlParameter, String urlEncoded, String
urlEncodedRelayState,
PrivateKey signingKey) throws IOException, GeneralSecurityException
{
StringBuilder sb = new StringBuilder();
- sb.append(requestOrResponseKeyValuePair);
+
+ addParameter(sb, samlParameter, urlEncoded);
+
if (isNotNull(urlEncodedRelayState))
{
- sb.append("&RelayState=").append(urlEncodedRelayState);
+ addParameter(sb, GeneralConstants.RELAY_STATE, urlEncodedRelayState);
}
+
//SigAlg
String algo = signingKey.getAlgorithm();
String sigAlg = SignatureUtil.getXMLSignatureAlgorithmURI(algo);
sigAlg = URLEncoder.encode(sigAlg, "UTF-8");
- sb.append("&SigAlg=").append(sigAlg);
+ addParameter(sb, GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, sigAlg);
byte[] sigValue = SignatureUtil.sign(sb.toString(), signingKey);
@@ -242,49 +267,54 @@
private static String getRequestRedirectURLWithSignature(String urlEncodedRequest,
String urlEncodedRelayState,
byte[] signature, String sigAlgo) throws IOException
{
+ return getRedirectURLWithSignature(GeneralConstants.SAML_REQUEST_KEY,
urlEncodedRequest, urlEncodedRelayState,
+ signature, sigAlgo);
+ }
+
+ private static String getResponseRedirectURLWithSignature(String urlEncodedResponse,
String urlEncodedRelayState,
+ byte[] signature, String sigAlgo) throws IOException
+ {
+ return getRedirectURLWithSignature(GeneralConstants.SAML_RESPONSE_KEY,
urlEncodedResponse, urlEncodedRelayState,
+ signature, sigAlgo);
+ }
+
+ private static String getRedirectURLWithSignature(String samlParameter, String
urlEncoded,
+ String urlEncodedRelayState, byte[] signature, String sigAlgo) throws
IOException
+ {
StringBuilder sb = new StringBuilder();
- sb.append("SAMLRequest=").append(urlEncodedRequest);
+
+ addParameter(sb, samlParameter, urlEncoded);
+
if (isNotNull(urlEncodedRelayState))
{
-
sb.append("&").append("RelayState=").append(urlEncodedRelayState);
+ addParameter(sb, GeneralConstants.RELAY_STATE, urlEncodedRelayState);
}
+
//SigAlg
String sigAlg = SignatureUtil.getXMLSignatureAlgorithmURI(sigAlgo);
sigAlg = URLEncoder.encode(sigAlg, "UTF-8");
- sb.append("&").append("SigAlg=").append(sigAlg);
+ addParameter(sb, GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, sigAlg);
//Encode the signature value
String encodedSig = RedirectBindingUtil.base64URLEncode(signature);
- sb.append("&").append("Signature=").append(encodedSig);
+ addParameter(sb, GeneralConstants.SAML_SIGNATURE_REQUEST_KEY, encodedSig);
return sb.toString();
}
- private static String getResponseRedirectURLWithSignature(String urlEncodedResponse,
String urlEncodedRelayState,
- byte[] signature, String sigAlgo) throws IOException
+ private static void addParameter(StringBuilder queryString, String paramName, String
paramValue)
{
- StringBuilder sb = new StringBuilder();
- sb.append("SAMLResponse=").append(urlEncodedResponse);
- if (isNotNull(urlEncodedRelayState))
+ String parameterSeparator = "&";
+
+ if (queryString.length() == 0)
{
-
sb.append("&").append("RelayState=").append(urlEncodedRelayState);
+ parameterSeparator = "";
}
- //SigAlg
- String sigAlg = SignatureUtil.getXMLSignatureAlgorithmURI(sigAlgo);
- sigAlg = URLEncoder.encode(sigAlg, "UTF-8");
-
- sb.append("&").append("SigAlg=").append(sigAlg);
-
- //Encode the signature value
- String encodedSig = RedirectBindingUtil.base64URLEncode(signature);
-
- sb.append("&").append("Signature=").append(encodedSig);
-
- return sb.toString();
+
queryString.append(parameterSeparator).append(paramName).append("=").append(paramValue);
}
private static String getToken(String queryString, String token)
Property changes on:
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings
___________________________________________________________________
Added: svn:mergeinfo
+
/federation/trunk/picketlink-bindings/src/test/java/org/picketlink/test/identity/federation/bindings:1140-1173,1329-1337
/federation/trunk/picketlink-fed-api/src/test/java/org/picketlink/test/identity/federation/bindings:1192-1228
/federation/trunk/picketlink-fed-core/src/test/java/org/picketlink/test/identity/federation/bindings:1152-1154,1159-1173,1192-1228
Modified:
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/mock/MockCatalinaContext.java
===================================================================
---
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/mock/MockCatalinaContext.java 2012-01-31
22:12:56 UTC (rev 1357)
+++
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/mock/MockCatalinaContext.java 2012-01-31
22:13:31 UTC (rev 1358)
@@ -879,7 +879,7 @@
return null;
}
- public RequestDispatcher getRequestDispatcher(String arg0)
+ public RequestDispatcher getRequestDispatcher(final String path)
{
return new RequestDispatcher()
{
@@ -890,6 +890,11 @@
public void forward(ServletRequest arg0, ServletResponse arg1) throws
ServletException, IOException
{
+ if (arg0 instanceof MockCatalinaRequest) {
+ MockCatalinaRequest mockRequest = (MockCatalinaRequest) arg0;
+
+ mockRequest.setForwardPath(path);
+ }
}
};
}
Modified:
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/mock/MockCatalinaRequest.java
===================================================================
---
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/mock/MockCatalinaRequest.java 2012-01-31
22:12:56 UTC (rev 1357)
+++
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/mock/MockCatalinaRequest.java 2012-01-31
22:13:31 UTC (rev 1358)
@@ -44,6 +44,7 @@
private String method;
private String remotee;
private String queryString;
+ private String forwardPath;
@Override
@@ -154,4 +155,14 @@
this.params.clear();
this.session = null;
}
+
+ public String getForwardPath()
+ {
+ return this.forwardPath;
+ }
+
+ public void setForwardPath(String path)
+ {
+ this.forwardPath = path;
+ }
}
\ No newline at end of file
Property changes on:
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/workflow
___________________________________________________________________
Modified: svn:mergeinfo
-
/federation/trunk/picketlink-bindings/src/test/java/org/picketlink/test/identity/federation/bindings/workflow:1140-1173,1307-1318,1321-1325
/federation/trunk/picketlink-fed-api/src/test/java/org/picketlink/test/identity/federation/bindings/workflow:1192-1228
/federation/trunk/picketlink-fed-core/src/test/java/org/picketlink/test/identity/federation/bindings/workflow:1152-1154,1159-1173,1192-1228
+
/federation/trunk/picketlink-bindings/src/test/java/org/picketlink/test/identity/federation/bindings/workflow:1140-1173,1307-1318,1321-1325,1329-1337
/federation/trunk/picketlink-fed-api/src/test/java/org/picketlink/test/identity/federation/bindings/workflow:1192-1228
/federation/trunk/picketlink-fed-core/src/test/java/org/picketlink/test/identity/federation/bindings/workflow:1152-1154,1159-1173,1192-1228
Copied:
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/workflow/AbstractSAML2RedirectWithSignatureTestCase.java
(from rev 1337,
federation/trunk/picketlink-bindings/src/test/java/org/picketlink/test/identity/federation/bindings/workflow/AbstractSAML2RedirectWithSignatureTestCase.java)
===================================================================
---
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/workflow/AbstractSAML2RedirectWithSignatureTestCase.java
(rev 0)
+++
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/workflow/AbstractSAML2RedirectWithSignatureTestCase.java 2012-01-31
22:13:31 UTC (rev 1358)
@@ -0,0 +1,288 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2011, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.picketlink.test.identity.federation.bindings.workflow;
+
+import java.io.IOException;
+import java.net.URL;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpSession;
+
+import junit.framework.Assert;
+
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.Session;
+import org.apache.catalina.realm.GenericPrincipal;
+import org.picketlink.identity.federation.bindings.tomcat.idp.IDPWebBrowserSSOValve;
+import
org.picketlink.identity.federation.bindings.tomcat.sp.SPRedirectSignatureFormAuthenticator;
+import org.picketlink.identity.federation.web.constants.GeneralConstants;
+import org.picketlink.identity.federation.web.core.IdentityServer;
+import org.picketlink.identity.federation.web.util.RedirectBindingUtil;
+import org.picketlink.test.identity.federation.bindings.mock.MockCatalinaContext;
+import
org.picketlink.test.identity.federation.bindings.mock.MockCatalinaContextClassLoader;
+import org.picketlink.test.identity.federation.bindings.mock.MockCatalinaRealm;
+import org.picketlink.test.identity.federation.bindings.mock.MockCatalinaRequest;
+import org.picketlink.test.identity.federation.bindings.mock.MockCatalinaResponse;
+import org.picketlink.test.identity.federation.bindings.mock.MockCatalinaSession;
+
+/**
+ * Abstract class to create SAML2 Redirect Binding testcases using signatures.
+ *
+ * @author Pedro Igor
+ * @since Dec 2, 2011
+ */
+public abstract class AbstractSAML2RedirectWithSignatureTestCase
+{
+ protected static final String BASE_PROFILE = "saml2/redirect";
+
+ private static final String IDP_PROFILE = BASE_PROFILE + "/idp-sig/";
+
+ private MockCatalinaSession idpHttpSession = new MockCatalinaSession();
+
+ protected IDPWebBrowserSSOValve createIdentityProvider()
+ {
+ Thread.currentThread().setContextClassLoader(setupTCL(IDP_PROFILE));
+
+ IDPWebBrowserSSOValve idpWebBrowserSSOValve = new IDPWebBrowserSSOValve();
+
+ MockCatalinaContext catalinaContext = new MockCatalinaContext();
+
+ idpWebBrowserSSOValve.setContainer(catalinaContext);
+
+ catalinaContext.setAttribute("IDENTITY_SERVER", new IdentityServer());
+
+ idpWebBrowserSSOValve.setSignOutgoingMessages(true);
+ idpWebBrowserSSOValve.setIgnoreIncomingSignatures(false);
+ idpWebBrowserSSOValve.setValidatingAliasToTokenIssuer(true);
+
+ try
+ {
+ idpWebBrowserSSOValve.start();
+ }
+ catch (LifecycleException e)
+ {
+ e.printStackTrace();
+ }
+
+ return idpWebBrowserSSOValve;
+ }
+
+ protected void addIdentityServerParticipants(IDPWebBrowserSSOValve idp, String url) {
+ IdentityServer identityServer = getIdentityServer(idp);
+
+ identityServer.stack().register(getIDPHttpSession().getId(), url, false);
+ }
+
+ protected MockCatalinaSession getIDPHttpSession()
+ {
+ return this.idpHttpSession;
+ }
+
+ protected IdentityServer getIdentityServer(IDPWebBrowserSSOValve idp)
+ {
+ return (IdentityServer) ((MockCatalinaContext)
idp.getContainer()).getAttribute("IDENTITY_SERVER");
+ }
+
+ protected SPRedirectSignatureFormAuthenticator createServiceProvider(String
spProfile)
+ {
+ Thread.currentThread().setContextClassLoader(setupTCL(spProfile));
+
+ SPRedirectSignatureFormAuthenticator sp = new
SPRedirectSignatureFormAuthenticator();
+
+ sp.setIdpAddress("192.168.1.1");
+
+ sp.setContainer(new MockCatalinaContext());
+
+ try
+ {
+ sp.testStart();
+ }
+ catch (LifecycleException e)
+ {
+ Assert.fail("Error while creating Employee SP.");
+ }
+
+ return sp;
+ }
+
+ protected void setQueryStringFromResponse(MockCatalinaResponse
idpLogoutEmployeeResponse,
+ MockCatalinaRequest idpLogoutResponseRequest) throws IOException
+ {
+ String samlParameter = null;
+ String samlParameterValue = null;
+
+ if
(idpLogoutEmployeeResponse.redirectString.contains(GeneralConstants.SAML_REQUEST_KEY +
"="))
+ {
+ samlParameter = GeneralConstants.SAML_REQUEST_KEY;
+ samlParameterValue = getSAMLRequest(idpLogoutEmployeeResponse);
+ }
+ else
+ {
+ samlParameter = GeneralConstants.SAML_RESPONSE_KEY;
+ samlParameterValue = getSAMLResponse(idpLogoutEmployeeResponse);
+ }
+
+ idpLogoutResponseRequest.setParameter(samlParameter,
RedirectBindingUtil.urlDecode(samlParameterValue));
+
+ boolean hasRelayState =
idpLogoutEmployeeResponse.redirectString.indexOf("&RelayState") != -1;
+
+ if (hasRelayState)
+ {
+ idpLogoutResponseRequest.setParameter(GeneralConstants.RELAY_STATE,
+
RedirectBindingUtil.urlDecode(getSAMLRelayState(idpLogoutEmployeeResponse)));
+ }
+
+ idpLogoutResponseRequest.setParameter(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY,
+ RedirectBindingUtil.urlDecode(getSAMLSigAlg(idpLogoutEmployeeResponse)));
+ idpLogoutResponseRequest.setParameter(GeneralConstants.SAML_SIGNATURE_REQUEST_KEY,
+ RedirectBindingUtil.urlDecode(getSAMLSignature(idpLogoutEmployeeResponse)));
+
+ StringBuffer queryString = new StringBuffer();
+
+ queryString.append(samlParameter + "=" + samlParameterValue);
+
+ if (hasRelayState)
+ {
+
queryString.append("&").append(GeneralConstants.RELAY_STATE).append("=")
+ .append(getSAMLRelayState(idpLogoutEmployeeResponse));
+ }
+
+
queryString.append("&").append(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY).append("=")
+ .append(getSAMLSigAlg(idpLogoutEmployeeResponse));
+
queryString.append("&").append(GeneralConstants.SAML_SIGNATURE_REQUEST_KEY).append("=")
+ .append(getSAMLSignature(idpLogoutEmployeeResponse));
+
+ idpLogoutResponseRequest.setQueryString(queryString.toString());
+ }
+
+ protected String getSAMLResponse(MockCatalinaResponse response)
+ {
+ int endIndex = response.redirectString.indexOf("&SigAlg=");
+
+ if (response.redirectString.contains("&RelayState="))
+ {
+ endIndex = response.redirectString.indexOf("&RelayState=");
+ }
+
+ return response.redirectString.substring(
+ response.redirectString.indexOf(GeneralConstants.SAML_RESPONSE_KEY +
"=")
+ + (GeneralConstants.SAML_RESPONSE_KEY + "=").length(),
endIndex);
+ }
+
+ protected String getSAMLSignature(MockCatalinaResponse response)
+ {
+ return
response.redirectString.substring(response.redirectString.indexOf("&Signature=")
+ "&Signature=".length());
+ }
+
+ protected String getSAMLRelayState(MockCatalinaResponse response)
+ {
+ return response.redirectString.substring(
+ response.redirectString.indexOf("&RelayState=") +
"&RelayState=".length(),
+ response.redirectString.lastIndexOf("&SigAlg="));
+ }
+
+ protected String getSAMLSigAlg(MockCatalinaResponse response)
+ {
+ return
response.redirectString.substring(response.redirectString.indexOf("&SigAlg=")
+ "&SigAlg=".length(),
+ response.redirectString.lastIndexOf("&Signature="));
+ }
+
+ protected String getSAMLRequest(MockCatalinaResponse response)
+ {
+ int endIndex = response.redirectString.indexOf("&SigAlg=");
+
+ if (response.redirectString.contains("&RelayState="))
+ {
+ endIndex = response.redirectString.indexOf("&RelayState=");
+ }
+
+ return
response.redirectString.substring(response.redirectString.indexOf(GeneralConstants.SAML_REQUEST_KEY
+ "=")
+ + (GeneralConstants.SAML_REQUEST_KEY + "=").length(), endIndex);
+ }
+
+ protected MockCatalinaRequest createRequest(HttpSession httpSession, boolean
withUserPrincipal)
+ {
+ MockCatalinaRequest request = createRequest("192.168.1.3",
withUserPrincipal);
+
+ request.setSession((Session) httpSession);
+
+ return request;
+ }
+
+ protected MockCatalinaRequest createRequest(String userAddress, boolean
withUserPrincipal)
+ {
+ MockCatalinaRequest request = new MockCatalinaRequest();
+
+ request = new MockCatalinaRequest();
+ request.setMethod("GET");
+ request.setRemoteAddr(userAddress);
+ request.setSession(new MockCatalinaSession());
+ request.setContext(new MockCatalinaContext());
+
+ if (withUserPrincipal) {
+ request.setUserPrincipal(createPrincipal());
+ }
+
+ return request;
+ }
+
+ protected MockCatalinaRequest createIDPRequest(boolean withUserPrincipal)
+ {
+ return createRequest(this.getIDPHttpSession(), withUserPrincipal);
+ }
+
+ protected GenericPrincipal createPrincipal()
+ {
+ MockCatalinaRealm realm = new MockCatalinaRealm("user", "user",
new Principal()
+ {
+ public String getName()
+ {
+ return "user";
+ }
+ });
+ List<String> roles = new ArrayList<String>();
+ roles.add("manager");
+ roles.add("employee");
+
+ List<String> rolesList = new ArrayList<String>();
+ rolesList.add("manager");
+
+ return new GenericPrincipal(realm, "user", "user", roles);
+ }
+
+ protected MockCatalinaContextClassLoader setupTCL(String resource)
+ {
+ URL[] urls = new URL[]
+
+ {Thread.currentThread().getContextClassLoader().getResource(resource)};
+
+ MockCatalinaContextClassLoader mcl = new MockCatalinaContextClassLoader(urls);
+
+ mcl.setDelegate(Thread.currentThread().getContextClassLoader());
+ mcl.setProfile(resource);
+
+ return mcl;
+ }
+
+}
Copied:
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/workflow/SAML2LogoutSignatureTomcatWorkflowUnitTestCase.java
(from rev 1337,
federation/trunk/picketlink-bindings/src/test/java/org/picketlink/test/identity/federation/bindings/workflow/SAML2LogoutSignatureTomcatWorkflowUnitTestCase.java)
===================================================================
---
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/workflow/SAML2LogoutSignatureTomcatWorkflowUnitTestCase.java
(rev 0)
+++
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/workflow/SAML2LogoutSignatureTomcatWorkflowUnitTestCase.java 2012-01-31
22:13:31 UTC (rev 1358)
@@ -0,0 +1,191 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.picketlink.test.identity.federation.bindings.workflow;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletException;
+
+import junit.framework.Assert;
+
+import org.apache.catalina.LifecycleException;
+import org.junit.Test;
+import org.picketlink.identity.federation.bindings.tomcat.idp.IDPWebBrowserSSOValve;
+import
org.picketlink.identity.federation.bindings.tomcat.sp.SPRedirectSignatureFormAuthenticator;
+import org.picketlink.identity.federation.web.constants.GeneralConstants;
+import org.picketlink.test.identity.federation.bindings.mock.MockCatalinaLoginConfig;
+import org.picketlink.test.identity.federation.bindings.mock.MockCatalinaRequest;
+import org.picketlink.test.identity.federation.bindings.mock.MockCatalinaResponse;
+import org.picketlink.test.identity.federation.bindings.mock.MockCatalinaSession;
+
+/**
+ * <p>Unit test the SAML2 Logout Mechanism for Tomcat bindings with token
signature.</>
+ * <p>This test uses a scenario where there are two SPs (Employee e Sales) pointing
to the same IDP. When the user sends a GLO logout request to the Employee SP
+ * Picketlink will start the logout process and invalidate the user in both
SPs.</p>
+ *
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ * @since Dec 1, 2011
+ */
+@SuppressWarnings("unused")
+public class SAML2LogoutSignatureTomcatWorkflowUnitTestCase extends
AbstractSAML2RedirectWithSignatureTestCase
+{
+ private static final String SP_SALES_URL =
"http://192.168.1.4:8080/sales/";
+
+ private static final String SP_SALES_PROFILE = BASE_PROFILE +
"/sp/sales-sig";
+
+ private static final String SP_EMPLOYEE_URL =
"http://192.168.1.2:8080/employee/";
+
+ private static final String SP_EMPLOYEE_PROFILE = BASE_PROFILE +
"/sp/employee-sig";
+
+ private IDPWebBrowserSSOValve idpWebBrowserSSOValve;
+
+ private MockCatalinaSession employeeHttpSession = new MockCatalinaSession();
+
+ private MockCatalinaSession salesHttpSession = new MockCatalinaSession();
+
+ private SPRedirectSignatureFormAuthenticator salesServiceProvider;
+
+ private SPRedirectSignatureFormAuthenticator employeeServiceProvider;
+
+ /**
+ * Tests the GLO logout mechanism.
+ *
+ * @throws LifecycleException
+ * @throws IOException
+ * @throws ServletException
+ */
+ @Test
+ public void testSAML2LogOutFromSP() throws LifecycleException, IOException,
ServletException
+ {
+
+ // requests a GLO logout to the Employee SP
+ MockCatalinaRequest originalEmployeeLogoutRequest =
createRequest(employeeHttpSession, true);
+
+ originalEmployeeLogoutRequest.setParameter(GeneralConstants.GLOBAL_LOGOUT,
"true");
+
+ MockCatalinaResponse originalEmployeeLogoutResponse =
sendSPRequest(originalEmployeeLogoutRequest,
+ getEmployeeServiceProvider());
+
+ // sends the LogoutRequest to the IDP
+ MockCatalinaRequest idpLogoutRequest = createIDPRequest(true);
+
+ setQueryStringFromResponse(originalEmployeeLogoutResponse, idpLogoutRequest);
+
+ MockCatalinaResponse idpLogoutResponse = sendIDPRequest(idpLogoutRequest);
+
+ // The IDP responds with a LogoutRequest. Send it to the Sales SP with the
RelayState pointing to the Employee SP
+ MockCatalinaRequest salesLogoutRequest = createRequest(salesHttpSession, true);
+
+ setQueryStringFromResponse(idpLogoutResponse, salesLogoutRequest);
+
+ MockCatalinaResponse salesLogoutResponse = sendSPRequest(salesLogoutRequest,
getSalesServiceProvider());
+
+ // At this moment the user is not logged in Sales SP anymore.
+ assertTrue(this.salesHttpSession.isInvalidated());
+
+ // sends the StatusResponse to the IDP to continue the logout process.
+ MockCatalinaRequest processSalesStatusResponse = createIDPRequest(true);
+
+ setQueryStringFromResponse(salesLogoutResponse, processSalesStatusResponse);
+
+ MockCatalinaResponse salesStatusResponse =
sendIDPRequest(processSalesStatusResponse);
+
+ // The IDP responds with a LogoutRequest. Send it to the Employee SP.
+ MockCatalinaRequest employeeLogoutRequest = createRequest(employeeHttpSession,
true);
+
+ setQueryStringFromResponse(salesStatusResponse, employeeLogoutRequest);
+
+ MockCatalinaResponse employeeLogoutResponse = sendSPRequest(employeeLogoutRequest,
getEmployeeServiceProvider());
+
+ // At this moment the user is not logged in Employee SP anymore.
+ assertTrue(this.employeeHttpSession.isInvalidated());
+
+ Assert.assertNotNull(employeeLogoutRequest.getForwardPath());
+ Assert.assertEquals(employeeLogoutRequest.getForwardPath(),
GeneralConstants.LOGOUT_PAGE_NAME);
+ assertEquals(0,
getIdentityServer(getIDPWebBrowserSSOValve()).stack().getParticipants(getIDPHttpSession().getId()));
+ assertEquals(0,
getIdentityServer(getIDPWebBrowserSSOValve()).stack().getNumOfParticipantsInTransit(getIDPHttpSession().getId()));
+
+ //Finally the session should be invalidated
+ assertTrue(getIDPHttpSession().isInvalidated());
+ }
+
+ private MockCatalinaResponse sendSPRequest(MockCatalinaRequest request,
SPRedirectSignatureFormAuthenticator sp) throws LifecycleException,
+ IOException, ServletException
+ {
+ MockCatalinaResponse response = new MockCatalinaResponse();
+
+ sp.authenticate(request, response, new MockCatalinaLoginConfig());
+
+ return response;
+ }
+
+ private MockCatalinaResponse sendIDPRequest(MockCatalinaRequest request) throws
LifecycleException, IOException,
+ ServletException
+ {
+ IDPWebBrowserSSOValve idp = getIDPWebBrowserSSOValve();
+
+ MockCatalinaResponse response = new MockCatalinaResponse();
+
+ response.setWriter(new PrintWriter(new ByteArrayOutputStream()));
+
+ idp.invoke(request, response);
+
+ ((MockCatalinaSession) request.getSession()).clear();
+
+ return response;
+ }
+
+ private IDPWebBrowserSSOValve getIDPWebBrowserSSOValve() throws LifecycleException
+ {
+ if (this.idpWebBrowserSSOValve == null)
+ {
+ this.idpWebBrowserSSOValve = createIdentityProvider();
+ addIdentityServerParticipants(this.idpWebBrowserSSOValve, SP_EMPLOYEE_URL);
+ addIdentityServerParticipants(this.idpWebBrowserSSOValve, SP_SALES_URL);
+ }
+
+ return this.idpWebBrowserSSOValve;
+ }
+
+ public SPRedirectSignatureFormAuthenticator getEmployeeServiceProvider() {
+ if (this.employeeServiceProvider == null)
+ {
+ this.employeeServiceProvider = createServiceProvider(SP_EMPLOYEE_PROFILE);
+ }
+
+ return this.employeeServiceProvider;
+ }
+
+ public SPRedirectSignatureFormAuthenticator getSalesServiceProvider() {
+ if (this.salesServiceProvider == null)
+ {
+ this.salesServiceProvider = createServiceProvider(SP_SALES_PROFILE);
+ }
+
+ return this.salesServiceProvider;
+ }
+}
\ No newline at end of file
Modified:
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/workflow/SAML2RedirectSignatureTomcatWorkflowUnitTestCase.java
===================================================================
---
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/workflow/SAML2RedirectSignatureTomcatWorkflowUnitTestCase.java 2012-01-31
22:12:56 UTC (rev 1357)
+++
product/trunk/picketlink-core/src/test/java/org/picketlink/test/identity/federation/bindings/workflow/SAML2RedirectSignatureTomcatWorkflowUnitTestCase.java 2012-01-31
22:13:31 UTC (rev 1358)
@@ -21,68 +21,55 @@
*/
package org.picketlink.test.identity.federation.bindings.workflow;
-
import static org.junit.Assert.assertNotNull;
import java.io.IOException;
-import java.net.URL;
-import java.security.Principal;
-import java.util.ArrayList;
-import java.util.List;
import javax.servlet.ServletException;
import junit.framework.Assert;
import org.apache.catalina.LifecycleException;
-import org.apache.catalina.realm.GenericPrincipal;
import org.junit.Test;
import org.picketlink.identity.federation.bindings.tomcat.idp.IDPWebBrowserSSOValve;
import
org.picketlink.identity.federation.bindings.tomcat.sp.SPRedirectSignatureFormAuthenticator;
-import org.picketlink.identity.federation.web.constants.GeneralConstants;
-import org.picketlink.identity.federation.web.util.RedirectBindingUtil;
-import org.picketlink.test.identity.federation.bindings.mock.MockCatalinaContext;
-import
org.picketlink.test.identity.federation.bindings.mock.MockCatalinaContextClassLoader;
import org.picketlink.test.identity.federation.bindings.mock.MockCatalinaLoginConfig;
-import org.picketlink.test.identity.federation.bindings.mock.MockCatalinaRealm;
import org.picketlink.test.identity.federation.bindings.mock.MockCatalinaRequest;
import org.picketlink.test.identity.federation.bindings.mock.MockCatalinaResponse;
-import org.picketlink.test.identity.federation.bindings.mock.MockCatalinaSession;
/**
* <p>
* This {@code TestCase} tests the interaction between the SP and the IDP in a scenario
where token signature is used.
* </p>
* <p>
- * This class also tests the use of the {@code
SPRedirectSignatureFormAuthenticator.idpAddress} and the {@code
IDPWebBrowserSSOValve.validatingAliasToTokenIssuer} properties.
- * <br/>
+ * This class also tests the use of the {@code
SPRedirectSignatureFormAuthenticator.idpAddress} and the {@code
IDPWebBrowserSSOValve.validatingAliasToTokenIssuer} properties
+ * during the token's signature validation process.
+ * </p>
+ * <p>
* The objective is test the following scenarios:
- * <br/><br/>
- * 1) User's machine is the same of the SP and the IDP.
(testSAML2RedirectWithSameConsumerAndProvider)
- * <br/>
- * 2) User's machine is different of the SP and the IDP.
(testSAML2RedirectWithSifferentConsumerAndProvider)
+ * <ul>
+ * <li>User's machine is the same of the SP and the IDP.
(testSAML2RedirectWithSameConsumerAndProvider)</li>
+ * <li> User's machine is different of the SP and the IDP.
(testSAML2RedirectWithSifferentConsumerAndProvider)
+ * <br/>
* 192.168.1.1 -> IDP Address (IDP_PROFILE/WEB-INF/picketlink-idfed.xml)
+ * <br/>
* 192.168.1.2 -> SP Address (SP_PROFILE/WEB-INF/picketlink-idfed.xml)
+ * <br/>
* 192.168.1.3 -> End User Address
+ * </li>
+ * <ul>
* </p>
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
* @since Nov 14, 2011
*/
-public class SAML2RedirectSignatureTomcatWorkflowUnitTestCase
+public class SAML2RedirectSignatureTomcatWorkflowUnitTestCase extends
AbstractSAML2RedirectWithSignatureTestCase
{
- private static final String profile = "saml2/redirect";
- private static final String IDP_PROFILE = profile + "/idp-sig/";
+ private static final String SP_EMPLOYEE_PROFILE = BASE_PROFILE +
"/sp/employee-sig";
- private static final String SP_PROFILE = profile + "/sp/employee-sig";
+ private SPRedirectSignatureFormAuthenticator employeeServiceProvider;
- private final ClassLoader tcl = Thread.currentThread().getContextClassLoader();
-
- private String SAML_REQUEST_KEY = "SAMLRequest=";
-
- private String SAML_RESPONSE_KEY = "SAMLResponse=";
-
/**
* Tests the token's signatures validations when the requester and the SP/IDP as
on the same host.
* The keyprovider is configured with the same ValidatingAlias for all of them.
@@ -92,168 +79,94 @@
@Test
public void testSAML2RedirectWithSameConsumerAndProvider() throws Exception
{
- testWorkflow("192.168.1.1", "192.168.1.1", false);
+ testWorkflow("192.168.1.1", "192.168.1.1");
}
-
+
/**
* Tests the token's signatures validations when the requester is in a differente
host than the SP and IDP.
- * The keyprovider is configured with a ValidatingAlias for specific for the SP
(192.168.1.2) that is different from the IDP (localhost) and the user (192.168.1.1).
+ * <br/>
+ * The keyprovider is configured with a ValidatingAlias for a specific SP
(192.168.1.2) that is different from the IDP (192.168.1.1) and the user (192.168.1.3).
+ * <br/>
+ * Test fails if:
+ * <ul>
+ * <li>If you change the IDP address the test will fail because the
SP's keystore and SPRedirectSignatureFormAuthenticator.idpAddress is configured to use
a validating alias with value 192.168.1.1.</li>
+ * <li>If you change the SP address
(SP_PROFILE/WEB-INF/picketlink-idfed.xml) the test will fail because the IDP's
keystore is only configured to use a validating alias with value 192.168.1.2.</li>
+ * <li>If you ommit the SPRedirectSignatureFormAuthenticator.idpAddress
because the user's address will be used to validate the token. His address is not in
the keystore.</li>
+ * <li>If you ommit the IDPWebBrowserSSOValve.validatingAliasToTokenIssuer
because the user's address will be used to validate the token. His address is not in
the keystore.</li>
+ * </ul>
*/
@Test
- public void testSAML2RedirectWithSifferentConsumerAndProvider() throws Exception
+ public void testSAML2RedirectWithDifferentConsumerAndProvider() throws Exception
{
- testWorkflow("192.168.1.3", "192.168.1.1", true);
+ testWorkflow("192.168.1.3", "192.168.1.1");
}
- private void testWorkflow(String userAddress, String idpAddress, boolean
validatingAliasToTokenIssuer) throws LifecycleException, IOException, ServletException
+ private void testWorkflow(String userAddress, String idpAddress)
+ throws LifecycleException, IOException, ServletException
{
- MockCatalinaRequest request = createRequest(userAddress);
-
+ MockCatalinaRequest request = createRequest(userAddress, false);
+
// Sends a initial request to the SP. Requesting a resource ...
MockCatalinaResponse idpAuthRequest = sendSPRequest(request, false, idpAddress);
-
+
assertNotNull("Redirect String can not be null.",
idpAuthRequest.redirectString);
-
+
// Sends a auth request to the IDP
- request = createRequest(userAddress);
-
- request.setParameter("SAMLRequest",
RedirectBindingUtil.urlDecode(getSAMLRequest(idpAuthRequest)));
- request.setParameter("SigAlg",
RedirectBindingUtil.urlDecode(getSAMLSigAlg(idpAuthRequest)));
- request.setParameter("Signature",
RedirectBindingUtil.urlDecode(getSAMLSignature(idpAuthRequest)));
- request.setQueryString(SAML_REQUEST_KEY + getSAMLRequest(idpAuthRequest) +
"&SigAlg=" + getSAMLSigAlg(idpAuthRequest) + "&Signature=" +
getSAMLSignature(idpAuthRequest));
-
- request.setUserPrincipal(new GenericPrincipal(createRealm(), "user",
"user", getRoles()) );
-
- MockCatalinaResponse idpAuthResponse = sendIDPRequest(request,
validatingAliasToTokenIssuer);
-
+ request = createRequest(userAddress, true);
+
+ setQueryStringFromResponse(idpAuthRequest, request);
+
+ MockCatalinaResponse idpAuthResponse = sendIDPRequest(request);
+
assertNotNull("Redirect String can not be null.",
idpAuthResponse.redirectString);
-
+
// Sends the IDP response to the SP. Now the user is succesfully authenticated and
access for the requested resource is granted...
- request = createRequest(userAddress);
- request.getContext().setRealm(createRealm());
-
- request.setParameter("SAMLResponse",
RedirectBindingUtil.urlDecode(getSAMLResponse(idpAuthResponse)));
- request.setParameter("SigAlg",
RedirectBindingUtil.urlDecode(getSAMLSigAlg(idpAuthResponse)));
- request.setParameter("Signature",
RedirectBindingUtil.urlDecode(getSAMLSignature(idpAuthResponse)));
- request.setQueryString(SAML_RESPONSE_KEY + getSAMLResponse(idpAuthResponse) +
"&SigAlg=" + getSAMLSigAlg(idpAuthResponse) + "&Signature=" +
getSAMLSignature(idpAuthResponse));
-
+ request = createRequest(userAddress, false);
+
+ setQueryStringFromResponse(idpAuthResponse, request);
+
sendSPRequest(request, true, idpAddress);
}
- private MockCatalinaResponse sendIDPRequest(MockCatalinaRequest request, boolean
validatingAliasToTokenIssuer)
+ private MockCatalinaResponse sendIDPRequest(MockCatalinaRequest request)
throws LifecycleException, IOException, ServletException
{
- MockCatalinaContextClassLoader mclIDP = setupTCL(IDP_PROFILE);
- Thread.currentThread().setContextClassLoader(mclIDP);
+ IDPWebBrowserSSOValve idp = createIdentityProvider();
- IDPWebBrowserSSOValve idp = new IDPWebBrowserSSOValve();
-
- idp.setSignOutgoingMessages(true);
- idp.setIgnoreIncomingSignatures(false);
- idp.setValidatingAliasToTokenIssuer(validatingAliasToTokenIssuer);
-
- idp.setContainer(request.getContext());
- idp.start();
-
MockCatalinaResponse response = new MockCatalinaResponse();
-
+
idp.invoke(request, response);
-
- return response;
- }
- private MockCatalinaResponse sendSPRequest(MockCatalinaRequest request, boolean
validateAuthentication, String idpAddress)
- throws LifecycleException, IOException
- {
- MockCatalinaContextClassLoader mclSPEmp = setupTCL(SP_PROFILE);
- Thread.currentThread().setContextClassLoader(mclSPEmp);
-
- SPRedirectSignatureFormAuthenticator sp = new
SPRedirectSignatureFormAuthenticator();
-
- sp.setIdpAddress(idpAddress);
-
- request.setParameter(GeneralConstants.RELAY_STATE, null);
-
- MockCatalinaLoginConfig loginConfig = new MockCatalinaLoginConfig();
-
- sp.setContainer(request.getContext());
- sp.testStart();
-
- MockCatalinaResponse response = new MockCatalinaResponse();
-
- if (validateAuthentication) {
- Assert.assertTrue("Employee app succesfully authenticated.",
sp.authenticate(request, response, loginConfig));
- } else {
- sp.authenticate(request, response, loginConfig);
- }
-
return response;
}
-
- private MockCatalinaRequest createRequest(String userAddress)
- {
- MockCatalinaRequest request = new MockCatalinaRequest();
-
- request = new MockCatalinaRequest();
- request.setMethod("GET");
- request.setRemoteAddr(userAddress);
- request.setSession(new MockCatalinaSession());
- request.setContext(new MockCatalinaContext());
-
- return request;
- }
- private String getSAMLResponse(MockCatalinaResponse response)
+ private MockCatalinaResponse sendSPRequest(MockCatalinaRequest request, boolean
validateAuthentication,
+ String idpAddress) throws LifecycleException, IOException
{
- return
response.redirectString.substring(response.redirectString.indexOf(SAML_RESPONSE_KEY) +
- SAML_RESPONSE_KEY.length(),
response.redirectString.indexOf("&SigAlg="));
- }
- private String getSAMLSignature(MockCatalinaResponse response)
- {
- return
response.redirectString.substring(response.redirectString.indexOf("&Signature=")
+
- "&Signature=".length());
- }
+ MockCatalinaResponse response = new MockCatalinaResponse();
- private String getSAMLSigAlg(MockCatalinaResponse response)
- {
- return
response.redirectString.substring(response.redirectString.indexOf("&SigAlg=")
+
- "&SigAlg=".length(),
response.redirectString.lastIndexOf("&Signature="));
- }
+ if (validateAuthentication)
+ {
+ Assert.assertTrue("Employee app succesfully authenticated.",
+ getEmployeeServiceProvider().authenticate(request, response, new
MockCatalinaLoginConfig()));
+ }
+ else
+ {
+ getEmployeeServiceProvider().authenticate(request, response, new
MockCatalinaLoginConfig());
+ }
- private String getSAMLRequest(MockCatalinaResponse response)
- {
- return
response.redirectString.substring(response.redirectString.indexOf(SAML_REQUEST_KEY) +
- SAML_REQUEST_KEY.length(),
response.redirectString.indexOf("&SigAlg="));
+ return response;
}
- private List<String> getRoles()
+ public SPRedirectSignatureFormAuthenticator getEmployeeServiceProvider()
{
- List<String> roles = new ArrayList<String>();
- roles.add("manager");
- roles.add("employee");
- return roles;
- }
+ if (this.employeeServiceProvider == null)
+ {
+ this.employeeServiceProvider = createServiceProvider(SP_EMPLOYEE_PROFILE);
+ }
- private MockCatalinaRealm createRealm()
- {
- return new MockCatalinaRealm("user", "user", new Principal()
- {
- public String getName()
- {
- return "user";
- }
- });
+ return this.employeeServiceProvider;
}
-
- private MockCatalinaContextClassLoader setupTCL(String resource)
- {
- URL[] urls = new URL[] {tcl.getResource(resource)};
-
- MockCatalinaContextClassLoader mcl = new MockCatalinaContextClassLoader(urls);
- mcl.setDelegate(tcl);
- mcl.setProfile(resource);
- return mcl;
- }
-
+
}