Author: anil.saldhana(a)jboss.com
Date: 2009-01-14 20:15:09 -0500 (Wed, 14 Jan 2009)
New Revision: 217
Added:
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/tomcat/sp/SPRedirectSignatureFormAuthenticator.java
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/util/cert/KeyStoreUtil.java
identity-federation/trunk/identity-bindings/src/test/java/org/jboss/test/identity/federation/bindings/util/
identity-federation/trunk/identity-bindings/src/test/java/org/jboss/test/identity/federation/bindings/util/RedirectBindingSignatureUtilTestCase.java
Modified:
identity-federation/trunk/identity-bindings/.classpath
identity-federation/trunk/identity-bindings/pom.xml
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/tomcat/idp/IDPRedirectValve.java
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/tomcat/sp/SPRedirectFormAuthenticator.java
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/tomcat/sp/SPRedirectValve.java
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/util/HTTPRedirectUtil.java
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/util/RedirectBindingSignatureUtil.java
Log:
some signature support
Modified: identity-federation/trunk/identity-bindings/.classpath
===================================================================
--- identity-federation/trunk/identity-bindings/.classpath 2009-01-14 13:12:43 UTC (rev
216)
+++ identity-federation/trunk/identity-bindings/.classpath 2009-01-15 01:15:09 UTC (rev
217)
@@ -17,5 +17,7 @@
<classpathentry kind="var"
path="M2_REPO/apache-log4j/log4j/1.2.14/log4j-1.2.14.jar"/>
<classpathentry combineaccessrules="false" kind="src"
path="/identity-fed-core"/>
<classpathentry combineaccessrules="false" kind="src"
path="/identity-fed-model"/>
+ <classpathentry kind="var"
path="M2_REPO/org/apache/xmlsec/1.4.1/xmlsec-1.4.1.jar"/>
+ <classpathentry kind="var"
path="M2_REPO/org/jboss/identity/jboss-identity-xmlsec-model/1.0.0-SNAPSHOT/jboss-identity-xmlsec-model-1.0.0-SNAPSHOT.jar"/>
<classpathentry kind="output" path="target-eclipse/"/>
</classpath>
Modified: identity-federation/trunk/identity-bindings/pom.xml
===================================================================
--- identity-federation/trunk/identity-bindings/pom.xml 2009-01-14 13:12:43 UTC (rev 216)
+++ identity-federation/trunk/identity-bindings/pom.xml 2009-01-15 01:15:09 UTC (rev 217)
@@ -100,6 +100,12 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>sun-jaf</groupId>
+ <artifactId>activation</artifactId>
+ <version>1.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
Modified:
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/tomcat/idp/IDPRedirectValve.java
===================================================================
---
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/tomcat/idp/IDPRedirectValve.java 2009-01-14
13:12:43 UTC (rev 216)
+++
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/tomcat/idp/IDPRedirectValve.java 2009-01-15
01:15:09 UTC (rev 217)
@@ -128,7 +128,7 @@
log.trace("IDP:Destination=" + destination);
base64Response = URLEncoder.encode(base64Response,
"UTF-8");
- HTTPRedirectUtil.sendRedirect(destination +
"?SAMLResponse=" + base64Response,response);
+ HTTPRedirectUtil.sendRedirectForRequestor(destination +
"?SAMLResponse=" + base64Response,response);
}
catch (Exception e)
{
Modified:
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/tomcat/sp/SPRedirectFormAuthenticator.java
===================================================================
---
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/tomcat/sp/SPRedirectFormAuthenticator.java 2009-01-14
13:12:43 UTC (rev 216)
+++
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/tomcat/sp/SPRedirectFormAuthenticator.java 2009-01-15
01:15:09 UTC (rev 217)
@@ -24,7 +24,6 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.net.URLEncoder;
import java.security.Principal;
import javax.servlet.ServletException;
@@ -41,6 +40,7 @@
import org.jboss.identity.federation.api.util.Base64;
import org.jboss.identity.federation.api.util.DeflateUtil;
import org.jboss.identity.federation.bindings.util.HTTPRedirectUtil;
+import org.jboss.identity.federation.bindings.util.RedirectBindingSignatureUtil;
import org.jboss.identity.federation.core.saml.v2.exceptions.AssertionExpiredException;
import org.jboss.identity.federation.saml.v2.protocol.AuthnRequestType;
import org.jboss.identity.federation.saml.v2.protocol.ResponseType;
@@ -81,6 +81,7 @@
}
Session session = request.getSessionInternal(true);
+ String relayState = request.getParameter("RelayState");
//Try to get the username
try
@@ -88,7 +89,9 @@
Principal p = process(request,response);
if(p == null)
{
- createSAMLRequestMessage("someuser", response);
+ String destination = createSAMLRequestMessage("someuser",
relayState, response);
+ HTTPRedirectUtil.sendRedirectForResponder(destination, response);
+
return false;
}
String username = p.getName();
@@ -104,10 +107,12 @@
log.debug("Assertion has expired. Issuing a new saml2 request to the
IDP");
try
{
- createSAMLRequestMessage("someuser", response);
+ String destination = createSAMLRequestMessage("someuser",
relayState, response);
+ HTTPRedirectUtil.sendRedirectForResponder(destination, response);
}
catch (Exception e)
{
+ //TODO: send a saml response message
log.trace("Exception:",e);
e.printStackTrace();
}
@@ -115,6 +120,7 @@
}
catch(Exception e)
{
+ //TODO: send a saml response message
log.debug("Exception :",e);
e.printStackTrace();
}
@@ -123,7 +129,7 @@
return super.authenticate(request, response, loginConfig);
}
- private void createSAMLRequestMessage(String username, Response response)
+ protected String createSAMLRequestMessage(String username, String relayState, Response
response)
throws Exception
{
//create a saml request
@@ -134,22 +140,25 @@
SPUtil spUtil = new SPUtil();
AuthnRequestType authnRequest = spUtil.createSAMLRequest(serviceURL, identityURL);
-
+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
saml2Request.marshall(authnRequest, baos);
-
- //Deflate encoding
- byte[] deflatedMsg = DeflateUtil.encode(baos.toByteArray());
-
- String base64Request = Base64.encodeBytes(deflatedMsg, Base64.DONT_BREAK_LINES);
-
- base64Request = URLEncoder.encode(base64Request, "UTF-8");
- String destination = authnRequest.getDestination() + "?SAMLRequest=" +
base64Request;
+
+ String base64Request =
RedirectBindingSignatureUtil.deflateBase64URLEncode(baos.toByteArray());
+ String destination = authnRequest.getDestination() + getDestination(base64Request,
relayState);
log.debug("Sending to destination="+destination);
-
- HTTPRedirectUtil.sendRedirect(destination, response);
- return;
+
+ return destination;
}
+
+ protected String getDestination(String urlEncodedRequest, String
urlEncodedRelayState)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("?SAMLRequest=").append(urlEncodedRequest);
+ if(urlEncodedRelayState != null && urlEncodedRelayState.length() > 0)
+ sb.append("&RelayState=").append(urlEncodedRelayState);
+ return sb.toString();
+ }
private Principal process(Request request, Response response) throws Exception
{
Added:
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/tomcat/sp/SPRedirectSignatureFormAuthenticator.java
===================================================================
---
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/tomcat/sp/SPRedirectSignatureFormAuthenticator.java
(rev 0)
+++
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/tomcat/sp/SPRedirectSignatureFormAuthenticator.java 2009-01-15
01:15:09 UTC (rev 217)
@@ -0,0 +1,72 @@
+/*
+ * 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.jboss.identity.federation.bindings.tomcat.sp;
+
+import java.security.KeyStore;
+import java.security.PrivateKey;
+
+import org.jboss.identity.federation.bindings.util.RedirectBindingSignatureUtil;
+import org.jboss.identity.federation.bindings.util.cert.KeyStoreUtil;
+
+/**
+ * Tomcat Authenticator for the HTTP/Redirect
+ * binding with Signature support
+ * @author Anil.Saldhana(a)redhat.com
+ * @since Jan 12, 2009
+ */
+public class SPRedirectSignatureFormAuthenticator extends SPRedirectFormAuthenticator
+{
+ private String keyStore;
+ private char[] keypass;
+ private String alias;
+
+ public void setKeyStore(String keyStore)
+ {
+ this.keyStore = keyStore;
+ }
+
+ public void setKeyStorePassword(String keypass)
+ {
+ this.keypass = keypass.toCharArray();
+ }
+
+ public void setAlias(String alias)
+ {
+ this.alias = alias;
+ }
+
+ @Override
+ protected String getDestination(String urlEncodedRequest, String
urlEncodedRelayState)
+ {
+ try
+ {
+ //Get the signing key
+ KeyStore ks = KeyStoreUtil.getKeyStore(keyStore, keypass);
+ PrivateKey signingKey = (PrivateKey) ks.getKey(alias, keypass);
+ return
RedirectBindingSignatureUtil.getSAMLRequestURLWithSignature(urlEncodedRequest,
urlEncodedRelayState, signingKey);
+ }
+ catch(Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+}
\ No newline at end of file
Modified:
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/tomcat/sp/SPRedirectValve.java
===================================================================
---
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/tomcat/sp/SPRedirectValve.java 2009-01-14
13:12:43 UTC (rev 216)
+++
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/tomcat/sp/SPRedirectValve.java 2009-01-15
01:15:09 UTC (rev 217)
@@ -24,7 +24,6 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.net.URLEncoder;
import java.security.Principal;
import javax.servlet.ServletException;
@@ -38,9 +37,8 @@
import org.jboss.identity.federation.api.saml.v2.common.IDGenerator;
import org.jboss.identity.federation.api.saml.v2.request.SAML2Request;
import org.jboss.identity.federation.api.saml.v2.response.SAML2Response;
-import org.jboss.identity.federation.api.util.Base64;
-import org.jboss.identity.federation.api.util.DeflateUtil;
import org.jboss.identity.federation.bindings.util.HTTPRedirectUtil;
+import org.jboss.identity.federation.bindings.util.RedirectBindingSignatureUtil;
import org.jboss.identity.federation.saml.v2.protocol.AuthnRequestType;
import org.jboss.identity.federation.saml.v2.protocol.ResponseType;
@@ -78,9 +76,8 @@
String samlResponse = request.getParameter("SAMLResponse");
if(samlResponse != null && samlResponse.length() > 0 )
{
- //deal with saml response from IDP
- byte[] base64DecodedResponse = Base64.decode(samlResponse);
- InputStream is = DeflateUtil.decode(base64DecodedResponse);
+ //deal with saml response from IDP
+ InputStream is =
RedirectBindingSignatureUtil.urlBase64DeflateDecode(samlResponse);
SAML2Response saml2Response = new SAML2Response();
@@ -108,18 +105,13 @@
ByteArrayOutputStream baos = new ByteArrayOutputStream();
saml2Request.marshall(authnRequest, baos);
-
- //Deflate encoding
- byte[] deflatedMsg = DeflateUtil.encode(baos.toByteArray());
-
- String base64Request = Base64.encodeBytes(deflatedMsg,
Base64.DONT_BREAK_LINES);
-
- base64Request = URLEncoder.encode(base64Request, "UTF-8");
+
+ String base64Request =
RedirectBindingSignatureUtil.deflateBase64URLEncode(baos.toByteArray());
String destination = authnRequest.getDestination() +
"?SAMLRequest=" + base64Request;
log.trace("Sending to destination="+destination);
log.trace("
");
- HTTPRedirectUtil.sendRedirect(destination, response);
+ HTTPRedirectUtil.sendRedirectForRequestor(destination, response);
return;
}
}
@@ -131,6 +123,7 @@
}
catch(Exception e)
{
+ //TODO: send error via saml response status
log.error("Exception:",e);
response.sendError(Response.SC_INTERNAL_SERVER_ERROR, "Server
Error");
}
Modified:
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/util/HTTPRedirectUtil.java
===================================================================
---
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/util/HTTPRedirectUtil.java 2009-01-14
13:12:43 UTC (rev 216)
+++
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/util/HTTPRedirectUtil.java 2009-01-15
01:15:09 UTC (rev 217)
@@ -41,15 +41,36 @@
* @param response HttpServletResponse
* @throws IOException
*/
- public static void sendRedirect(String destination, HttpServletResponse response)
+ public static void sendRedirectForRequestor(String destination, HttpServletResponse
response)
throws IOException
{
response.setCharacterEncoding("UTF-8");
response.setHeader("Location", destination);
+
response.setHeader("Cache-Control", "no-cache, no-store");
- response.setHeader("Pragma", "no-cache");
+ response.setHeader("Pragma", "no-cache");
+ sendRedirect(response,destination);
+ }
+
+ /**
+ * @see #sendRedirectForRequestor(String, HttpServletResponse)
+ */
+ public static void sendRedirectForResponder(String destination, HttpServletResponse
response)
+ throws IOException
+ {
+ response.setCharacterEncoding("UTF-8");
+ response.setHeader("Location", destination);
+ //Add couple of headers for responders to get away from caching with http proxies
+ response.setHeader("Cache-Control", "no-cache, no-store,
must-revalidate,private");
+ response.setHeader("Pragma", "no-cache");
+
+ sendRedirect(response,destination);
+ }
+
+ private static void sendRedirect(HttpServletResponse response, String destination)
throws IOException
+ {
response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
- response.sendRedirect(destination);
- }
+ response.sendRedirect(destination);
+ }
}
\ No newline at end of file
Modified:
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/util/RedirectBindingSignatureUtil.java
===================================================================
---
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/util/RedirectBindingSignatureUtil.java 2009-01-14
13:12:43 UTC (rev 216)
+++
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/util/RedirectBindingSignatureUtil.java 2009-01-15
01:15:09 UTC (rev 217)
@@ -21,12 +21,17 @@
*/
package org.jboss.identity.federation.bindings.util;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.PrivateKey;
-import javax.servlet.http.HttpServletRequest;
-
+import org.jboss.identity.federation.api.saml.v2.request.SAML2Request;
+import org.jboss.identity.federation.api.util.Base64;
+import org.jboss.identity.federation.api.util.DeflateUtil;
import org.jboss.identity.federation.core.saml.v2.util.SignatureUtil;
+import org.jboss.identity.federation.saml.v2.protocol.AuthnRequestType;
/**
@@ -35,8 +40,153 @@
* @since Dec 16, 2008
*/
public class RedirectBindingSignatureUtil
-{
- public static String getRequestRedirectURLWithSignature(
+{
+ /**
+ * Get the URL for the SAML request that contains the signature and signature
algorithm
+ * @param authRequest
+ * @param relayState
+ * @param signingKey
+ * @return
+ * @throws Exception
+ */
+ public static String getSAMLRequestURLWithSignature(AuthnRequestType authRequest,
String relayState,
+ PrivateKey signingKey) throws Exception
+ {
+ SAML2Request saml2Request = new SAML2Request();
+
+ // Deal with the original request
+ StringWriter sw = new StringWriter();
+ saml2Request.marshall(authRequest, sw);
+
+ //URL Encode the Request
+ String urlEncodedRequest = deflateBase64URLEncode(sw.toString());
+
+ String urlEncodedRelayState = null;
+ if(relayState != null && relayState.length() > 0 )
+ urlEncodedRelayState = URLEncoder.encode(relayState, "UTF-8");
+
+ byte[] sigValue = computeSignature(urlEncodedRequest, urlEncodedRelayState,
signingKey);
+
+ //Now construct the URL
+ return getRequestRedirectURLWithSignature(urlEncodedRequest, urlEncodedRelayState,
sigValue, signingKey.getAlgorithm());
+ }
+
+ /**
+ * Given an url-encoded saml request and relay state and a private key, compute the
url
+ * @param urlEncodedRequest
+ * @param urlEncodedRelayState
+ * @param signingKey
+ * @return
+ * @throws Exception
+ */
+ public static String getSAMLRequestURLWithSignature(String urlEncodedRequest, String
urlEncodedRelayState,
+ PrivateKey signingKey) throws Exception
+ {
+ byte[] sigValue = computeSignature(urlEncodedRequest, urlEncodedRelayState,
signingKey);
+ return getRequestRedirectURLWithSignature(urlEncodedRequest, urlEncodedRelayState,
sigValue, signingKey.getAlgorithm());
+ }
+
+ /**
+ * From the SAML Request URL, get the Request object
+ * @param signedURL
+ * @return
+ * @throws Exception
+ */
+ public static AuthnRequestType getRequestFromSignedURL(String signedURL) throws
Exception
+ {
+ String samlRequestTokenValue = getTokenValue(signedURL, "SAMLRequest");
+
+ SAML2Request saml2Request = new SAML2Request();
+ return
saml2Request.getAuthnRequestType(urlBase64DeflateDecode(samlRequestTokenValue));
+ }
+
+ /**
+ * Get the signature value from the url
+ * @param signedURL
+ * @return
+ * @throws Exception
+ */
+ public static byte[] getSignatureValueFromSignedURL(String signedURL) throws
Exception
+ {
+ String sigValueTokenValue = getTokenValue(signedURL,"Signature");
+
+ return urlBase64Decode(sigValueTokenValue);
+ }
+
+ /**
+ * On the byte array, apply base64 encoding following by URL encoding
+ * @param stringToEncode
+ * @return
+ * @throws Exception
+ */
+ public static String base64URLEncode(byte[] stringToEncode) throws Exception
+ {
+ String base64Request = Base64.encodeBytes(stringToEncode, Base64.DONT_BREAK_LINES);
+ return URLEncoder.encode(base64Request, "UTF-8");
+ }
+
+ /**
+ * On the byte array, apply URL decoding followed by base64 decoding
+ * @param encodedString
+ * @return
+ * @throws Exception
+ */
+ public static byte[] urlBase64Decode(String encodedString) throws Exception
+ {
+ String decodedString = URLDecoder.decode(encodedString, "UTF-8");
+ return Base64.decode(decodedString);
+ }
+
+ /**
+ * Apply deflate compression followed by base64 encoding and URL encoding
+ * @param stringToEncode
+ * @return
+ * @throws Exception
+ */
+ public static String deflateBase64URLEncode(String stringToEncode) throws Exception
+ {
+ return deflateBase64URLEncode(stringToEncode.getBytes("UTF-8"));
+ }
+
+ /**
+ * Apply deflate compression followed by base64 encoding and URL encoding
+ * @param stringToEncode
+ * @return
+ * @throws Exception
+ */
+ public static String deflateBase64URLEncode(byte[] stringToEncode) throws Exception
+ {
+ byte[] deflatedMsg = DeflateUtil.encode(stringToEncode);
+ return base64URLEncode(deflatedMsg);
+ }
+
+ /**
+ * Apply URL decoding, followed by base64 decoding followed by deflate decompression
+ * @param encodedString
+ * @return
+ * @throws Exception
+ */
+ public static InputStream urlBase64DeflateDecode(String encodedString) throws
Exception
+ {
+ byte[] deflatedString = urlBase64Decode(encodedString);
+ return DeflateUtil.decode(deflatedString);
+ }
+
+ /**
+ * From the query string that contains key/value pairs, get the value of a key
+ * <b>Note:</b> if the token is null, a null value is returned
+ * @param queryString
+ * @param token
+ * @return
+ */
+ public static String getTokenValue(String queryString, String token)
+ {
+ return getTokenValue(getToken(queryString, token));
+ }
+
+ //***************** Private Methods **************
+
+ private static byte[] computeSignature(
String urlEncodedRequest, String urlEncodedRelayState,
PrivateKey signingKey) throws Exception
{
@@ -44,7 +194,7 @@
sb.append("SAMLRequest=").append(urlEncodedRequest);
if(urlEncodedRelayState != null && urlEncodedRelayState.length() > 0)
{
-
sb.append("&").append("RelayState=").append(urlEncodedRelayState);
+ sb.append("&RelayState=").append(urlEncodedRelayState);
}
//SigAlg
String algo = signingKey.getAlgorithm();
@@ -52,49 +202,35 @@
sigAlg = URLEncoder.encode(sigAlg, "UTF-8");
- sb.append("&").append("SigAlg=").append(sigAlg);
+ sb.append("&SigAlg=").append(sigAlg);
byte[] sigValue = SignatureUtil.sign(sb.toString(), signingKey);
- sb.append("&").append("Signature=").append(sigValue);
-
- return sb.toString();
+ return sigValue;
}
-
- public static String getSignedURL(HttpServletRequest request,
- PrivateKey signingKey)
+
+ private static String getRequestRedirectURLWithSignature(
+ String urlEncodedRequest, String urlEncodedRelayState, byte[] signature, String
sigAlgo) throws Exception
{
- //Build the query string
- String queryString = request.getQueryString();
StringBuilder sb = new StringBuilder();
-
- String req = getToken(queryString, "SAMLRequest");
- if(req != null)
- sb.append("SAMLRequest=").append(req);
- else
+ sb.append("SAMLRequest=").append(urlEncodedRequest);
+ if(urlEncodedRelayState != null && urlEncodedRelayState.length() > 0)
{
- String res = getToken(queryString, "SAMLResponse");
- if(res == null)
- throw new IllegalStateException("Either SAMLRequest or SAMLResponse
needed");
-
- sb.append("SAMLResponse=").append(res);
+
sb.append("&").append("RelayState=").append(urlEncodedRelayState);
}
+ //SigAlg
+ String sigAlg = SignatureUtil.getXMLSignatureAlgorithmURI(sigAlgo);
- sb.append("&");
+ sigAlg = URLEncoder.encode(sigAlg, "UTF-8");
+
+ sb.append("&").append("SigAlg=").append(sigAlg);
- //Relay State
- String relayState = getToken(queryString,"RelayState");
- if(relayState != null)
- {
- sb.append("RelayState=").append(relayState);
- }
+ //Encode the signature value
+ String encodedSig = base64URLEncode(signature);
- //SigAlg
- String algo = signingKey.getAlgorithm();
- String sigVal = SignatureUtil.getXMLSignatureAlgorithmURI(algo);
+ sb.append("&").append("Signature=").append(encodedSig);
- sb.append("SigVal=").append(sigVal);
- return null;
+ return sb.toString();
}
private static String getToken(String queryString, String token)
@@ -115,4 +251,16 @@
return queryString.substring(start,end);
}
+
+ private static String getTokenValue(String token)
+ {
+ if(token == null)
+ return token;
+
+ int eq = token.indexOf('=');
+ if(eq == -1)
+ return token;
+ else
+ return token.substring(eq + 1);
+ }
}
\ No newline at end of file
Added:
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/util/cert/KeyStoreUtil.java
===================================================================
---
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/util/cert/KeyStoreUtil.java
(rev 0)
+++
identity-federation/trunk/identity-bindings/src/main/java/org/jboss/identity/federation/bindings/util/cert/KeyStoreUtil.java 2009-01-15
01:15:09 UTC (rev 217)
@@ -0,0 +1,55 @@
+/*
+ * 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.jboss.identity.federation.bindings.util.cert;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+
+/**
+ * Utility to handle Java Keystore
+ * @author Anil.Saldhana(a)redhat.com
+ * @since Jan 12, 2009
+ */
+public class KeyStoreUtil
+{
+ public static KeyStore getKeyStore(String url, char[] password) throws
GeneralSecurityException, IOException
+ {
+ File file = new File(url);
+ FileInputStream fis = new FileInputStream(file);
+
+ KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
+ ks.load(fis, password);
+ return ks;
+ }
+
+ public static KeyPair generateKeyPair(String algo) throws Exception
+ {
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance(algo);
+ return kpg.genKeyPair();
+ }
+
+}
\ No newline at end of file
Added:
identity-federation/trunk/identity-bindings/src/test/java/org/jboss/test/identity/federation/bindings/util/RedirectBindingSignatureUtilTestCase.java
===================================================================
---
identity-federation/trunk/identity-bindings/src/test/java/org/jboss/test/identity/federation/bindings/util/RedirectBindingSignatureUtilTestCase.java
(rev 0)
+++
identity-federation/trunk/identity-bindings/src/test/java/org/jboss/test/identity/federation/bindings/util/RedirectBindingSignatureUtilTestCase.java 2009-01-15
01:15:09 UTC (rev 217)
@@ -0,0 +1,80 @@
+/*
+ * 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.jboss.test.identity.federation.bindings.util;
+
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+import junit.framework.TestCase;
+
+import org.jboss.identity.federation.api.saml.v2.common.IDGenerator;
+import org.jboss.identity.federation.bindings.util.RedirectBindingSignatureUtil;
+import org.jboss.identity.federation.bindings.util.cert.KeyStoreUtil;
+import
org.jboss.identity.federation.core.saml.v2.factories.JBossSAMLAuthnRequestFactory;
+import org.jboss.identity.federation.core.saml.v2.util.SignatureUtil;
+import org.jboss.identity.federation.saml.v2.protocol.AuthnRequestType;
+
+/**
+ * Unit Test the redirect binding sig util
+ * @author Anil.Saldhana(a)redhat.com
+ * @since Jan 13, 2009
+ */
+public class RedirectBindingSignatureUtilTestCase extends TestCase
+{
+ public void testUseCase() throws Exception
+ {
+ AuthnRequestType authnRequest =
JBossSAMLAuthnRequestFactory.createAuthnRequestType(
+ IDGenerator.create("ID_"), "http://sp",
"http://idp", "http://sp");
+
+ KeyPair kp = KeyStoreUtil.generateKeyPair("RSA");
+
+ PrivateKey signingKey = kp.getPrivate();
+
+ String sigURL =
RedirectBindingSignatureUtil.getSAMLRequestURLWithSignature(authnRequest, null,
signingKey);
+
+ //At this time, the sigURL contains the signed request and the signature
+
+ //Let us do the processing at the receiving end
+ byte[] sigValue =
RedirectBindingSignatureUtil.getSignatureValueFromSignedURL(sigURL);
+
+ //Construct the url again
+ String reqFromURL = RedirectBindingSignatureUtil.getTokenValue(sigURL,
"SAMLRequest");
+ String relayStateFromURL = RedirectBindingSignatureUtil.getTokenValue(sigURL,
"RelayState");
+ String sigAlgFromURL = RedirectBindingSignatureUtil.getTokenValue(sigURL,
"SigAlg");
+
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("SAMLRequest=").append(reqFromURL);
+
+ if(relayStateFromURL != null && relayStateFromURL.length() > 0)
+ {
+ sb.append("&RelayState=").append(relayStateFromURL);
+ }
+ sb.append("&SigAlg=").append(sigAlgFromURL);
+
+ PublicKey validatingKey = kp.getPublic();
+ boolean isValid = SignatureUtil.validate(sb.toString().getBytes("UTF-8"),
sigValue, validatingKey);
+
+ assertTrue(isValid);
+ }
+}
\ No newline at end of file