You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2016/12/21 15:06:56 UTC
[1/2] cxf-fediz git commit: Refactored Jetty plugins
Repository: cxf-fediz
Updated Branches:
refs/heads/master 25dcd2754 -> e8889b438
Refactored Jetty plugins
Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/db80f269
Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/db80f269
Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/db80f269
Branch: refs/heads/master
Commit: db80f26987cace847305f31203237a6b7c4fbfe9
Parents: 25dcd27
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Wed Dec 21 11:27:13 2016 +0000
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Wed Dec 21 11:27:13 2016 +0000
----------------------------------------------------------------------
.../fediz/jetty8/FederationAuthenticator.java | 367 ++++++++++---------
.../fediz/jetty9/FederationAuthenticator.java | 367 ++++++++++---------
2 files changed, 386 insertions(+), 348 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/db80f269/plugins/jetty8/src/main/java/org/apache/cxf/fediz/jetty8/FederationAuthenticator.java
----------------------------------------------------------------------
diff --git a/plugins/jetty8/src/main/java/org/apache/cxf/fediz/jetty8/FederationAuthenticator.java b/plugins/jetty8/src/main/java/org/apache/cxf/fediz/jetty8/FederationAuthenticator.java
index 56656a0..803c26a 100644
--- a/plugins/jetty8/src/main/java/org/apache/cxf/fediz/jetty8/FederationAuthenticator.java
+++ b/plugins/jetty8/src/main/java/org/apache/cxf/fediz/jetty8/FederationAuthenticator.java
@@ -79,7 +79,6 @@ import org.eclipse.jetty.util.log.Logger;
* associated with the session.
* </p>
*/
-// CHECKSTYLE:OFF
public class FederationAuthenticator extends LoginAuthenticator {
public static final String J_URI = "org.eclipse.jetty.security.form_URI";
@@ -166,10 +165,11 @@ public class FederationAuthenticator extends LoginAuthenticator {
// Check to see if it is a metadata request
MetadataDocumentHandler mdHandler = new MetadataDocumentHandler(fedConfig);
if (mdHandler.canHandleRequest(request)) {
+ Authentication authentication = Authentication.SEND_FAILURE;
if (mdHandler.handleRequest(request, response)) {
- return Authentication.SEND_CONTINUE;
+ authentication = Authentication.SEND_CONTINUE;
}
- return Authentication.SEND_FAILURE;
+ return authentication;
}
if (!mandatory) {
@@ -182,199 +182,54 @@ public class FederationAuthenticator extends LoginAuthenticator {
LOG.warn("Unsupported encoding '" + this.encoding + "'", ex);
}
- String uri = request.getRequestURI();
- if (uri == null) {
- uri = URIUtil.SLASH;
- }
-
try {
String action = request.getParameter(FederationConstants.PARAM_ACTION);
- String responseToken = getResponseToken(request, fedConfig);
+ Authentication authentication = null;
// Handle a request for authentication.
if (isSignInRequest(request, fedConfig)) {
-
- FedizResponse wfRes = null;
- if (LOG.isDebugEnabled()) {
- LOG.debug("SignIn request found");
- }
-
- if (responseToken == null) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("SignIn request must contain a response token from the IdP");
- }
- response.sendError(HttpServletResponse.SC_BAD_REQUEST);
- return Authentication.SEND_FAILURE;
- } else {
-
- FedizRequest wfReq = new FedizRequest();
- wfReq.setAction(action);
- wfReq.setResponseToken(responseToken);
- wfReq.setState(request.getParameter("RelayState"));
- wfReq.setRequest(request);
-
- X509Certificate certs[] =
- (X509Certificate[])request.getAttribute("javax.servlet.request.X509Certificate");
- wfReq.setCerts(certs);
-
- FederationLoginService fedLoginService = (FederationLoginService)this._loginService;
- UserIdentity user = fedLoginService.login(null, wfReq, fedConfig);
- if (user != null)
- {
- session=renewSession(request,response);
-
- // Redirect to original request
- String nuri;
- synchronized(session)
- {
- // Check the context
- String savedContext = (String) session.getAttribute(J_CONTEXT);
- String receivedContext = request.getParameter(FederationConstants.PARAM_CONTEXT);
- if (savedContext == null || !savedContext.equals(receivedContext)) {
- LOG.warn("The received wctx parameter does not match the saved value");
- response.sendError(HttpServletResponse.SC_FORBIDDEN);
- return Authentication.UNAUTHENTICATED;
- }
-
- nuri = (String) session.getAttribute(J_URI);
-
- if (nuri == null || nuri.length() == 0)
- {
- nuri = request.getContextPath();
- if (nuri.length() == 0) {
- nuri = URIUtil.SLASH;
- }
- }
- Authentication cached=new SessionAuthentication(getAuthMethod(), user, wfRes);
- session.setAttribute(SessionAuthentication.__J_AUTHENTICATED, cached);
- }
-
- FederationUserIdentity fui = (FederationUserIdentity)user;
- session.setAttribute(SECURITY_TOKEN_ATTR, fui.getToken());
-
- response.setContentLength(0);
- response.sendRedirect(response.encodeRedirectURL(nuri));
-
- return new FederationAuthentication(getAuthMethod(), user);
- }
-
- // not authenticated
- if (LOG.isDebugEnabled()) {
- LOG.debug("WSFED authentication FAILED");
- }
- if (response != null) {
- response.sendError(HttpServletResponse.SC_FORBIDDEN);
- return Authentication.UNAUTHENTICATED;
- }
-
- }
+ authentication = handleSignInRequest(request, response, session, fedConfig);
} else if (FederationConstants.ACTION_SIGNOUT_CLEANUP.equals(action)) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("SignOutCleanup request found");
- LOG.debug("SignOutCleanup action...");
- }
- session.invalidate();
-
- final ServletOutputStream responseOutputStream = response.getOutputStream();
- InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("logout.jpg");
- if (inputStream == null) {
- LOG.warn("Could not write logout.jpg");
- return Authentication.SEND_FAILURE;
- }
- int read = 0;
- byte[] buf = new byte[1024];
- while ((read = inputStream.read(buf)) != -1) {
- responseOutputStream.write(buf, 0, read);
- }
- inputStream.close();
- responseOutputStream.flush();
- return Authentication.SEND_SUCCESS;
+ authentication = handleSignOutCleanup(response, session);
} else if (!FederationConstants.ACTION_SIGNOUT.equals(action) && action != null) {
LOG.warn("Not supported action found in parameter wa: " + action);
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
- return Authentication.UNAUTHENTICATED;
+ authentication = Authentication.UNAUTHENTICATED;
+ }
+
+ if (authentication != null) {
+ return authentication;
}
// Look for cached authentication
- Authentication authentication = (Authentication) session.getAttribute(SessionAuthentication.__J_AUTHENTICATED);
- if (authentication != null)
- {
- // Has authentication been revoked?
- if (authentication instanceof Authentication.User
- && isTokenExpired(fedConfig, ((Authentication.User)authentication).getUserIdentity())) {
- session.removeAttribute(SessionAuthentication.__J_AUTHENTICATED);
- }
- else
- {
- //logout
- boolean logout = FederationConstants.ACTION_SIGNOUT.equals(action);
- String logoutUrl = fedConfig.getLogoutURL();
- if (logout || logoutUrl != null && !logoutUrl.isEmpty() && uri.equals(contextName + logoutUrl)) {
- session.invalidate();
-
- FedizProcessor wfProc =
- FedizProcessorFactory.newFedizProcessor(fedConfig.getProtocol());
- signOutRedirectToIssuer(request, response, wfProc);
-
- return Authentication.SEND_CONTINUE;
- }
-
- String j_uri = (String)session.getAttribute(J_URI);
- if (j_uri != null)
- {
- @SuppressWarnings("unchecked")
- MultiMap<String> j_post = (MultiMap<String>)session.getAttribute(J_POST);
- if (j_post != null)
- {
- StringBuffer buf = request.getRequestURL();
- if (request.getQueryString() != null) {
- buf.append("?").append(request.getQueryString());
- }
-
- if (j_uri.equals(buf.toString()))
- {
- // This is a retry of an original POST request
- // so restore method and parameters
-
- session.removeAttribute(J_POST);
- Request base_request = (req instanceof Request)?(Request)req:AbstractHttpConnection.getCurrentConnection().getRequest();
- base_request.setMethod(HttpMethods.POST);
- base_request.setParameters(j_post);
- }
- }
- else
- session.removeAttribute(J_URI);
-
- }
- return authentication;
- }
- }
+ authentication = handleCachedAuthentication(request, response, session, fedConfig);
+ if (authentication != null) {
+ return authentication;
+ }
// if we can't send challenge
- if (DeferredAuthentication.isDeferred(response))
- {
- LOG.debug("auth deferred {}",session.getId());
+ if (DeferredAuthentication.isDeferred(response)) {
+ LOG.debug("auth deferred {}", session.getId());
return Authentication.UNAUTHENTICATED;
}
// remember the current URI
- synchronized (session)
- {
+ synchronized (session) {
// But only if it is not set already, or we save every uri that leads to a login form redirect
- if (session.getAttribute(J_URI)==null) // || alwaysSaveUri)
- {
+ if (session.getAttribute(J_URI) == null) { // || alwaysSaveUri)
StringBuffer buf = request.getRequestURL();
if (request.getQueryString() != null) {
buf.append("?").append(request.getQueryString());
}
session.setAttribute(J_URI, buf.toString());
- if (MimeTypes.FORM_ENCODED.equalsIgnoreCase(req.getContentType()) && HttpMethods.POST.equals(request.getMethod()))
- {
- Request base_request = (req instanceof Request)?(Request)req:AbstractHttpConnection.getCurrentConnection().getRequest();
- base_request.extractParameters();
- session.setAttribute(J_POST, new MultiMap<String>(base_request.getParameters()));
+ if (MimeTypes.FORM_ENCODED.equalsIgnoreCase(req.getContentType())
+ && HttpMethods.POST.equals(request.getMethod())) {
+ Request baseRequest = (req instanceof Request) ? (Request)req
+ : AbstractHttpConnection.getCurrentConnection().getRequest();
+ baseRequest.extractParameters();
+ session.setAttribute(J_POST, new MultiMap<String>(baseRequest.getParameters()));
}
}
}
@@ -393,6 +248,170 @@ public class FederationAuthenticator extends LoginAuthenticator {
*/
}
+ private Authentication handleSignInRequest(HttpServletRequest request, HttpServletResponse response,
+ HttpSession session, FedizContext fedConfig) throws IOException {
+ FedizResponse wfRes = null;
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("SignIn request found");
+ }
+
+ String action = request.getParameter(FederationConstants.PARAM_ACTION);
+ String responseToken = getResponseToken(request, fedConfig);
+ if (responseToken == null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("SignIn request must contain a response token from the IdP");
+ }
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return Authentication.SEND_FAILURE;
+ } else {
+
+ FedizRequest wfReq = new FedizRequest();
+ wfReq.setAction(action);
+ wfReq.setResponseToken(responseToken);
+ wfReq.setState(request.getParameter("RelayState"));
+ wfReq.setRequest(request);
+
+ X509Certificate[] certs =
+ (X509Certificate[])request.getAttribute("javax.servlet.request.X509Certificate");
+ wfReq.setCerts(certs);
+
+ FederationLoginService fedLoginService = (FederationLoginService)this._loginService;
+ UserIdentity user = fedLoginService.login(null, wfReq, fedConfig);
+ if (user != null) {
+ session = renewSession(request, response);
+
+ // Redirect to original request
+ String nuri;
+ synchronized (session) {
+ // Check the context
+ String savedContext = (String) session.getAttribute(J_CONTEXT);
+ String receivedContext = request.getParameter(FederationConstants.PARAM_CONTEXT);
+ if (savedContext == null || !savedContext.equals(receivedContext)) {
+ LOG.warn("The received wctx parameter does not match the saved value");
+ response.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return Authentication.UNAUTHENTICATED;
+ }
+
+ nuri = (String) session.getAttribute(J_URI);
+
+ if (nuri == null || nuri.length() == 0) {
+ nuri = request.getContextPath();
+ if (nuri.length() == 0) {
+ nuri = URIUtil.SLASH;
+ }
+ }
+ Authentication cached = new SessionAuthentication(getAuthMethod(), user, wfRes);
+ session.setAttribute(SessionAuthentication.__J_AUTHENTICATED, cached);
+ }
+
+ FederationUserIdentity fui = (FederationUserIdentity)user;
+ session.setAttribute(SECURITY_TOKEN_ATTR, fui.getToken());
+
+ response.setContentLength(0);
+ response.sendRedirect(response.encodeRedirectURL(nuri));
+
+ return new FederationAuthentication(getAuthMethod(), user);
+ }
+
+ // not authenticated
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("WSFED authentication FAILED");
+ }
+ if (response != null) {
+ response.sendError(HttpServletResponse.SC_FORBIDDEN);
+ }
+ return Authentication.UNAUTHENTICATED;
+ }
+ }
+
+ private Authentication handleSignOutCleanup(HttpServletResponse response, HttpSession session) throws IOException {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("SignOutCleanup request found");
+ LOG.debug("SignOutCleanup action...");
+ }
+ session.invalidate();
+
+ final ServletOutputStream responseOutputStream = response.getOutputStream();
+ InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("logout.jpg");
+ if (inputStream == null) {
+ LOG.warn("Could not write logout.jpg");
+ return Authentication.SEND_FAILURE;
+ }
+ int read = 0;
+ byte[] buf = new byte[1024];
+ while ((read = inputStream.read(buf)) != -1) {
+ responseOutputStream.write(buf, 0, read);
+ }
+ inputStream.close();
+ responseOutputStream.flush();
+ return Authentication.SEND_SUCCESS;
+ }
+
+ private Authentication handleCachedAuthentication(HttpServletRequest request, HttpServletResponse response,
+ HttpSession session, FedizContext fedConfig) throws IOException {
+ Authentication authentication =
+ (Authentication) session.getAttribute(SessionAuthentication.__J_AUTHENTICATED);
+ if (authentication != null) {
+ // Has authentication been revoked?
+ if (authentication instanceof Authentication.User
+ && isTokenExpired(fedConfig, ((Authentication.User)authentication).getUserIdentity())) {
+ session.removeAttribute(SessionAuthentication.__J_AUTHENTICATED);
+ } else {
+ //logout
+ String action = request.getParameter(FederationConstants.PARAM_ACTION);
+ boolean logout = FederationConstants.ACTION_SIGNOUT.equals(action);
+ String logoutUrl = fedConfig.getLogoutURL();
+
+ String uri = request.getRequestURI();
+ if (uri == null) {
+ uri = URIUtil.SLASH;
+ }
+
+ String contextName = request.getSession().getServletContext().getContextPath();
+ if (contextName == null || contextName.isEmpty()) {
+ contextName = "/";
+ }
+
+ if (logout || logoutUrl != null && !logoutUrl.isEmpty() && uri.equals(contextName + logoutUrl)) {
+ session.invalidate();
+
+ FedizProcessor wfProc =
+ FedizProcessorFactory.newFedizProcessor(fedConfig.getProtocol());
+ signOutRedirectToIssuer(request, response, wfProc);
+
+ return Authentication.SEND_CONTINUE;
+ }
+
+ String jUri = (String)session.getAttribute(J_URI);
+ @SuppressWarnings("unchecked")
+ MultiMap<String> jPost = (MultiMap<String>)session.getAttribute(J_POST);
+ if (jUri != null && jPost != null) {
+ StringBuffer buf = request.getRequestURL();
+ if (request.getQueryString() != null) {
+ buf.append("?").append(request.getQueryString());
+ }
+
+ if (jUri.equals(buf.toString())) {
+ // This is a retry of an original POST request
+ // so restore method and parameters
+
+ session.removeAttribute(J_POST);
+ Request baseRequest = (Request)request;
+ // (req instanceof Request)?(Request)
+ // req:HttpConnection.getCurrentConnection().getRequest();
+ baseRequest.setMethod(HttpMethods.POST);
+ baseRequest.setParameters(jPost);
+ }
+ } else if (jUri != null) {
+ session.removeAttribute(J_URI);
+ }
+
+ return authentication;
+ }
+ }
+ return null;
+ }
+
private boolean isTokenExpired(FedizContext fedConfig, UserIdentity userIdentity) {
if (fedConfig.isDetectExpiredTokens()) {
try {
@@ -463,7 +482,8 @@ public class FederationAuthenticator extends LoginAuthenticator {
* {@link HttpServletResponse#sendError(int, String)} throws an
* {@link IOException}
*/
- protected void signInRedirectToIssuer(HttpServletRequest request, HttpServletResponse response, FedizProcessor processor, HttpSession session)
+ protected void signInRedirectToIssuer(HttpServletRequest request, HttpServletResponse response,
+ FedizProcessor processor, HttpSession session)
throws IOException {
//Not supported in jetty 7.6
@@ -484,7 +504,7 @@ public class FederationAuthenticator extends LoginAuthenticator {
}
}
- synchronized(session) {
+ synchronized (session) {
session.setAttribute(J_CONTEXT, redirectionResponse.getRequestState().getState());
}
@@ -502,7 +522,8 @@ public class FederationAuthenticator extends LoginAuthenticator {
}
- protected void signOutRedirectToIssuer(HttpServletRequest request, HttpServletResponse response, FedizProcessor processor)
+ protected void signOutRedirectToIssuer(HttpServletRequest request, HttpServletResponse response,
+ FedizProcessor processor)
throws IOException {
//Not supported in jetty 7.6
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/db80f269/plugins/jetty9/src/main/java/org/apache/cxf/fediz/jetty9/FederationAuthenticator.java
----------------------------------------------------------------------
diff --git a/plugins/jetty9/src/main/java/org/apache/cxf/fediz/jetty9/FederationAuthenticator.java b/plugins/jetty9/src/main/java/org/apache/cxf/fediz/jetty9/FederationAuthenticator.java
index e845b08..d5ce68c 100644
--- a/plugins/jetty9/src/main/java/org/apache/cxf/fediz/jetty9/FederationAuthenticator.java
+++ b/plugins/jetty9/src/main/java/org/apache/cxf/fediz/jetty9/FederationAuthenticator.java
@@ -78,7 +78,6 @@ import org.eclipse.jetty.util.log.Logger;
* associated with the session.
* </p>
*/
-// CHECKSTYLE:OFF
public class FederationAuthenticator extends LoginAuthenticator {
public static final String J_URI = "org.eclipse.jetty.security.form_URI";
@@ -165,10 +164,11 @@ public class FederationAuthenticator extends LoginAuthenticator {
// Check to see if it is a metadata request
MetadataDocumentHandler mdHandler = new MetadataDocumentHandler(fedConfig);
if (mdHandler.canHandleRequest(request)) {
+ Authentication authentication = Authentication.SEND_FAILURE;
if (mdHandler.handleRequest(request, response)) {
- return Authentication.SEND_CONTINUE;
+ authentication = Authentication.SEND_CONTINUE;
}
- return Authentication.SEND_FAILURE;
+ return authentication;
}
if (!mandatory) {
@@ -181,189 +181,41 @@ public class FederationAuthenticator extends LoginAuthenticator {
LOG.warn("Unsupported encoding '" + this.encoding + "'", ex);
}
- String uri = request.getRequestURI();
- if (uri == null) {
- uri = URIUtil.SLASH;
- }
-
try {
String action = request.getParameter(FederationConstants.PARAM_ACTION);
- String responseToken = getResponseToken(request, fedConfig);
+ Authentication authentication = null;
// Handle a request for authentication.
if (isSignInRequest(request, fedConfig)) {
-
- FedizResponse wfRes = null;
- if (LOG.isDebugEnabled()) {
- LOG.debug("SignIn request found");
- }
-
- if (responseToken == null) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("SignIn request must contain a response token from the IdP");
- }
- response.sendError(HttpServletResponse.SC_BAD_REQUEST);
- return Authentication.SEND_FAILURE;
- } else {
-
- FedizRequest wfReq = new FedizRequest();
- wfReq.setAction(action);
- wfReq.setResponseToken(responseToken);
- wfReq.setState(request.getParameter("RelayState"));
- wfReq.setRequest(request);
-
- X509Certificate certs[] =
- (X509Certificate[])request.getAttribute("javax.servlet.request.X509Certificate");
- wfReq.setCerts(certs);
-
- FederationLoginService fedLoginService = (FederationLoginService)this._loginService;
- UserIdentity user = fedLoginService.login(null, wfReq, fedConfig);
- if (user != null)
- {
- session=renewSession(request,response);
-
- // Redirect to original request
- String nuri;
- synchronized(session)
- {
- // Check the context
- String savedContext = (String) session.getAttribute(J_CONTEXT);
- String receivedContext = request.getParameter(FederationConstants.PARAM_CONTEXT);
- if (savedContext == null || !savedContext.equals(receivedContext)) {
- LOG.warn("The received wctx parameter does not match the saved value");
- response.sendError(HttpServletResponse.SC_FORBIDDEN);
- return Authentication.UNAUTHENTICATED;
- }
-
- nuri = (String) session.getAttribute(J_URI);
-
- if (nuri == null || nuri.length() == 0)
- {
- nuri = request.getContextPath();
- if (nuri.length() == 0) {
- nuri = URIUtil.SLASH;
- }
- }
- Authentication cached=new SessionAuthentication(getAuthMethod(), user, wfRes);
- session.setAttribute(SessionAuthentication.__J_AUTHENTICATED, cached);
- }
-
- FederationUserIdentity fui = (FederationUserIdentity)user;
- session.setAttribute(SECURITY_TOKEN_ATTR, fui.getToken());
-
- response.setContentLength(0);
- response.sendRedirect(response.encodeRedirectURL(nuri));
-
- return new FederationAuthentication(getAuthMethod(), user);
- }
-
- // not authenticated
- if (LOG.isDebugEnabled()) {
- LOG.debug("WSFED authentication FAILED");
- }
- if (response != null) {
- response.sendError(HttpServletResponse.SC_FORBIDDEN);
- return Authentication.UNAUTHENTICATED;
- }
-
- }
+ authentication = handleSignInRequest(request, response, session, fedConfig);
} else if (FederationConstants.ACTION_SIGNOUT_CLEANUP.equals(action)) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("SignOutCleanup request found");
- LOG.debug("SignOutCleanup action...");
- }
- session.invalidate();
-
- final ServletOutputStream responseOutputStream = response.getOutputStream();
- InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("logout.jpg");
- if (inputStream == null) {
- LOG.warn("Could not write logout.jpg");
- return Authentication.SEND_FAILURE;
- }
- int read = 0;
- byte[] buf = new byte[1024];
- while ((read = inputStream.read(buf)) != -1) {
- responseOutputStream.write(buf, 0, read);
- }
- inputStream.close();
- responseOutputStream.flush();
- return Authentication.SEND_SUCCESS;
+ authentication = handleSignOutCleanup(response, session);
} else if (!FederationConstants.ACTION_SIGNOUT.equals(action) && action != null) {
LOG.warn("Not supported action found in parameter wa: " + action);
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
- return Authentication.UNAUTHENTICATED;
+ authentication = Authentication.UNAUTHENTICATED;
+ }
+
+ if (authentication != null) {
+ return authentication;
}
// Look for cached authentication
- Authentication authentication = (Authentication) session.getAttribute(SessionAuthentication.__J_AUTHENTICATED);
- if (authentication != null)
- {
- // Has authentication been revoked?
- if (authentication instanceof Authentication.User
- && isTokenExpired(fedConfig, ((Authentication.User)authentication).getUserIdentity())) {
- session.removeAttribute(SessionAuthentication.__J_AUTHENTICATED);
- }
- else
- {
- //logout
- boolean logout = FederationConstants.ACTION_SIGNOUT.equals(action);
- String logoutUrl = fedConfig.getLogoutURL();
- if (logout || logoutUrl != null && !logoutUrl.isEmpty() && uri.equals(contextName + logoutUrl)) {
- session.invalidate();
-
- FedizProcessor wfProc =
- FedizProcessorFactory.newFedizProcessor(fedConfig.getProtocol());
- signOutRedirectToIssuer(request, response, wfProc);
-
- return Authentication.SEND_CONTINUE;
- }
-
- String j_uri = (String)session.getAttribute(J_URI);
- if (j_uri != null)
- {
- @SuppressWarnings("unchecked")
- MultiMap<String> j_post = (MultiMap<String>)session.getAttribute(J_POST);
- if (j_post != null)
- {
- StringBuffer buf = request.getRequestURL();
- if (request.getQueryString() != null) {
- buf.append("?").append(request.getQueryString());
- }
-
- if (j_uri.equals(buf.toString()))
- {
- // This is a retry of an original POST request
- // so restore method and parameters
-
- session.removeAttribute(J_POST);
- Request base_request = (Request)req;
- // (req instanceof Request)?(Request)req:HttpConnection.getCurrentConnection().getRequest();
- base_request.setMethod(HttpMethod.POST.asString());
- base_request.setQueryParameters(j_post);
- }
- }
- else
- session.removeAttribute(J_URI);
-
- }
- return authentication;
- }
- }
-
+ authentication = handleCachedAuthentication(request, response, session, fedConfig);
+ if (authentication != null) {
+ return authentication;
+ }
// if we can't send challenge
- if (DeferredAuthentication.isDeferred(response))
- {
- LOG.debug("auth deferred {}",session.getId());
+ if (DeferredAuthentication.isDeferred(response)) {
+ LOG.debug("auth deferred {}", session.getId());
return Authentication.UNAUTHENTICATED;
}
// remember the current URI
- synchronized (session)
- {
+ synchronized (session) {
// But only if it is not set already, or we save every uri that leads to a login form redirect
- if (session.getAttribute(J_URI)==null) // || alwaysSaveUri)
- {
+ if (session.getAttribute(J_URI) == null) { // || alwaysSaveUri)
StringBuffer buf = request.getRequestURL();
if (request.getQueryString() != null) {
buf.append("?").append(request.getQueryString());
@@ -371,12 +223,11 @@ public class FederationAuthenticator extends LoginAuthenticator {
session.setAttribute(J_URI, buf.toString());
if (MimeTypes.Type.FORM_ENCODED.asString().equals(req.getContentType())
- && HttpMethod.POST.asString().equals(request.getMethod()))
- {
- Request base_request = (Request)req;
+ && HttpMethod.POST.asString().equals(request.getMethod())) {
+ Request baseRequest = (Request)req;
//(req instanceof Request)?(Request)req:HttpConnection.getCurrentConnection().getRequest();
- base_request.extractParameters();
- session.setAttribute(J_POST, new MultiMap<String>(base_request.getQueryParameters()));
+ baseRequest.extractParameters();
+ session.setAttribute(J_POST, new MultiMap<String>(baseRequest.getQueryParameters()));
}
}
}
@@ -395,6 +246,170 @@ public class FederationAuthenticator extends LoginAuthenticator {
*/
}
+ private Authentication handleSignInRequest(HttpServletRequest request, HttpServletResponse response,
+ HttpSession session, FedizContext fedConfig) throws IOException {
+ FedizResponse wfRes = null;
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("SignIn request found");
+ }
+
+ String action = request.getParameter(FederationConstants.PARAM_ACTION);
+ String responseToken = getResponseToken(request, fedConfig);
+ if (responseToken == null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("SignIn request must contain a response token from the IdP");
+ }
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return Authentication.SEND_FAILURE;
+ } else {
+
+ FedizRequest wfReq = new FedizRequest();
+ wfReq.setAction(action);
+ wfReq.setResponseToken(responseToken);
+ wfReq.setState(request.getParameter("RelayState"));
+ wfReq.setRequest(request);
+
+ X509Certificate[] certs =
+ (X509Certificate[])request.getAttribute("javax.servlet.request.X509Certificate");
+ wfReq.setCerts(certs);
+
+ FederationLoginService fedLoginService = (FederationLoginService)this._loginService;
+ UserIdentity user = fedLoginService.login(null, wfReq, fedConfig);
+ if (user != null) {
+ session = renewSession(request, response);
+
+ // Redirect to original request
+ String nuri;
+ synchronized (session) {
+ // Check the context
+ String savedContext = (String) session.getAttribute(J_CONTEXT);
+ String receivedContext = request.getParameter(FederationConstants.PARAM_CONTEXT);
+ if (savedContext == null || !savedContext.equals(receivedContext)) {
+ LOG.warn("The received wctx parameter does not match the saved value");
+ response.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return Authentication.UNAUTHENTICATED;
+ }
+
+ nuri = (String) session.getAttribute(J_URI);
+
+ if (nuri == null || nuri.length() == 0) {
+ nuri = request.getContextPath();
+ if (nuri.length() == 0) {
+ nuri = URIUtil.SLASH;
+ }
+ }
+ Authentication cached = new SessionAuthentication(getAuthMethod(), user, wfRes);
+ session.setAttribute(SessionAuthentication.__J_AUTHENTICATED, cached);
+ }
+
+ FederationUserIdentity fui = (FederationUserIdentity)user;
+ session.setAttribute(SECURITY_TOKEN_ATTR, fui.getToken());
+
+ response.setContentLength(0);
+ response.sendRedirect(response.encodeRedirectURL(nuri));
+
+ return new FederationAuthentication(getAuthMethod(), user);
+ }
+
+ // not authenticated
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("WSFED authentication FAILED");
+ }
+ if (response != null) {
+ response.sendError(HttpServletResponse.SC_FORBIDDEN);
+ }
+ return Authentication.UNAUTHENTICATED;
+ }
+ }
+
+ private Authentication handleSignOutCleanup(HttpServletResponse response, HttpSession session) throws IOException {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("SignOutCleanup request found");
+ LOG.debug("SignOutCleanup action...");
+ }
+ session.invalidate();
+
+ final ServletOutputStream responseOutputStream = response.getOutputStream();
+ InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("logout.jpg");
+ if (inputStream == null) {
+ LOG.warn("Could not write logout.jpg");
+ return Authentication.SEND_FAILURE;
+ }
+ int read = 0;
+ byte[] buf = new byte[1024];
+ while ((read = inputStream.read(buf)) != -1) {
+ responseOutputStream.write(buf, 0, read);
+ }
+ inputStream.close();
+ responseOutputStream.flush();
+ return Authentication.SEND_SUCCESS;
+ }
+
+ private Authentication handleCachedAuthentication(HttpServletRequest request, HttpServletResponse response,
+ HttpSession session, FedizContext fedConfig) throws IOException {
+ Authentication authentication =
+ (Authentication) session.getAttribute(SessionAuthentication.__J_AUTHENTICATED);
+ if (authentication != null) {
+ // Has authentication been revoked?
+ if (authentication instanceof Authentication.User
+ && isTokenExpired(fedConfig, ((Authentication.User)authentication).getUserIdentity())) {
+ session.removeAttribute(SessionAuthentication.__J_AUTHENTICATED);
+ } else {
+ //logout
+ String action = request.getParameter(FederationConstants.PARAM_ACTION);
+ boolean logout = FederationConstants.ACTION_SIGNOUT.equals(action);
+ String logoutUrl = fedConfig.getLogoutURL();
+
+ String uri = request.getRequestURI();
+ if (uri == null) {
+ uri = URIUtil.SLASH;
+ }
+
+ String contextName = request.getSession().getServletContext().getContextPath();
+ if (contextName == null || contextName.isEmpty()) {
+ contextName = "/";
+ }
+
+ if (logout || logoutUrl != null && !logoutUrl.isEmpty() && uri.equals(contextName + logoutUrl)) {
+ session.invalidate();
+
+ FedizProcessor wfProc =
+ FedizProcessorFactory.newFedizProcessor(fedConfig.getProtocol());
+ signOutRedirectToIssuer(request, response, wfProc);
+
+ return Authentication.SEND_CONTINUE;
+ }
+
+ String jUri = (String)session.getAttribute(J_URI);
+ @SuppressWarnings("unchecked")
+ MultiMap<String> jPost = (MultiMap<String>)session.getAttribute(J_POST);
+ if (jUri != null && jPost != null) {
+ StringBuffer buf = request.getRequestURL();
+ if (request.getQueryString() != null) {
+ buf.append("?").append(request.getQueryString());
+ }
+
+ if (jUri.equals(buf.toString())) {
+ // This is a retry of an original POST request
+ // so restore method and parameters
+
+ session.removeAttribute(J_POST);
+ Request baseRequest = (Request)request;
+ // (req instanceof Request)?(Request)
+ // req:HttpConnection.getCurrentConnection().getRequest();
+ baseRequest.setMethod(HttpMethod.POST.asString());
+ baseRequest.setQueryParameters(jPost);
+ }
+ } else if (jUri != null) {
+ session.removeAttribute(J_URI);
+ }
+
+ return authentication;
+ }
+ }
+ return null;
+ }
+
private boolean isTokenExpired(FedizContext fedConfig, UserIdentity userIdentity) {
if (fedConfig.isDetectExpiredTokens()) {
try {
@@ -465,7 +480,8 @@ public class FederationAuthenticator extends LoginAuthenticator {
* {@link HttpServletResponse#sendError(int, String)} throws an
* {@link IOException}
*/
- protected void signInRedirectToIssuer(HttpServletRequest request, HttpServletResponse response, FedizProcessor processor, HttpSession session)
+ protected void signInRedirectToIssuer(HttpServletRequest request, HttpServletResponse response,
+ FedizProcessor processor, HttpSession session)
throws IOException {
//Not supported in jetty 7.6
@@ -486,7 +502,7 @@ public class FederationAuthenticator extends LoginAuthenticator {
}
}
- synchronized(session) {
+ synchronized (session) {
session.setAttribute(J_CONTEXT, redirectionResponse.getRequestState().getState());
}
@@ -504,7 +520,8 @@ public class FederationAuthenticator extends LoginAuthenticator {
}
- protected void signOutRedirectToIssuer(HttpServletRequest request, HttpServletResponse response, FedizProcessor processor)
+ protected void signOutRedirectToIssuer(HttpServletRequest request, HttpServletResponse response,
+ FedizProcessor processor)
throws IOException {
//Not supported in jetty 7.6
[2/2] cxf-fediz git commit: FEDIZ-186 - Add new
logoutRedirectToConstraint plugin configuration parameter
Posted by co...@apache.org.
FEDIZ-186 - Add new logoutRedirectToConstraint plugin configuration parameter
Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/e8889b43
Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/e8889b43
Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/e8889b43
Branch: refs/heads/master
Commit: e8889b4385348ff71bab8cebbd7ea70e68ea13d2
Parents: db80f26
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Wed Dec 21 14:54:00 2016 +0000
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Wed Dec 21 14:54:00 2016 +0000
----------------------------------------------------------------------
.../cxf/fediz/core/config/FedizContext.java | 8 +
.../cxf/fediz/core/handler/LogoutHandler.java | 31 +-
.../core/processor/FederationProcessorImpl.java | 43 ++-
.../src/main/resources/schemas/FedizConfig.xsd | 11 +
.../core/federation/FederationLogoutTest.java | 357 +++++++++++++++++++
.../test/resources/fediz_test_config_logout.xml | 88 +++++
6 files changed, 520 insertions(+), 18 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/e8889b43/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FedizContext.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FedizContext.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FedizContext.java
index 537b137..3a329e1 100644
--- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FedizContext.java
+++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FedizContext.java
@@ -30,6 +30,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
+import java.util.regex.Pattern;
import org.apache.cxf.fediz.core.config.jaxb.CertificateStores;
import org.apache.cxf.fediz.core.config.jaxb.ContextConfig;
@@ -69,6 +70,7 @@ public class FedizContext implements Closeable {
private KeyManager keyManager;
private KeyManager decryptionKeyManager;
private ClassLoader classloader;
+ private Pattern logoutRedirectToConstraint;
public FedizContext(ContextConfig config) {
@@ -170,6 +172,12 @@ public class FedizContext implements Closeable {
return config.getLogoutRedirectTo();
}
+ public Pattern getLogoutRedirectToConstraint() {
+ if (logoutRedirectToConstraint == null && config.getLogoutRedirectToConstraint() != null) {
+ logoutRedirectToConstraint = Pattern.compile(config.getLogoutRedirectToConstraint());
+ }
+ return logoutRedirectToConstraint;
+ }
public KeyManager getSigningKey() {
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/e8889b43/plugins/core/src/main/java/org/apache/cxf/fediz/core/handler/LogoutHandler.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/handler/LogoutHandler.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/handler/LogoutHandler.java
index 79d6fce..b547b00 100644
--- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/handler/LogoutHandler.java
+++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/handler/LogoutHandler.java
@@ -23,6 +23,8 @@ import java.io.InputStream;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
@@ -88,18 +90,31 @@ public class LogoutHandler implements RequestHandler<Boolean> {
protected boolean signoutCleanup(HttpServletRequest request, HttpServletResponse response) {
LOG.info("SignOutCleanup request found. Terminating user session.");
request.getSession().invalidate();
+
String wreply = request.getParameter(FederationConstants.PARAM_REPLY);
+ Pattern logoutRedirectToConstraint = fedizConfig.getLogoutRedirectToConstraint();
+
if (wreply != null && !wreply.isEmpty()) {
- try {
- LOG.debug("Redirecting user after logout to: {}", wreply);
- response.sendRedirect(URLEncoder.encode(wreply, "UTF-8"));
- } catch (IOException e) {
- LOG.error("Error redirecting user after logout: {}", e.getMessage());
+ if (logoutRedirectToConstraint == null) {
+ LOG.debug("No regular expression constraint configured for logout. Ignoring wreply parameter");
+ } else {
+ Matcher matcher = logoutRedirectToConstraint.matcher(wreply);
+ if (matcher.matches()) {
+ try {
+ LOG.debug("Redirecting user after logout to: {}", wreply);
+ response.sendRedirect(URLEncoder.encode(wreply, "UTF-8"));
+ return true;
+ } catch (IOException e) {
+ LOG.error("Error redirecting user after logout: {}", e.getMessage());
+ }
+ } else {
+ LOG.warn("The received wreply address {} does not match the configured constraint {}",
+ wreply, logoutRedirectToConstraint);
+ }
}
- } else {
- LOG.debug("No wreply parameter was set in logout action. Returning logout image");
- writeLogoutImage(response);
}
+
+ writeLogoutImage(response);
return true;
}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/e8889b43/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java
index b82777b..5cb626e 100644
--- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java
+++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java
@@ -34,6 +34,8 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
@@ -499,21 +501,42 @@ public class FederationProcessorImpl extends AbstractFedizProcessor {
StringBuilder sb = new StringBuilder();
sb.append(FederationConstants.PARAM_ACTION).append('=').append(FederationConstants.ACTION_SIGNOUT);
- String logoutRedirectTo = request.getParameter(FederationConstants.PARAM_REPLY);
- if (logoutRedirectTo == null || logoutRedirectTo.isEmpty()) {
- logoutRedirectTo = config.getLogoutRedirectTo();
- }
- if (logoutRedirectTo != null && !logoutRedirectTo.isEmpty()) {
-
- if (logoutRedirectTo.startsWith("/")) {
- logoutRedirectTo = extractFullContextPath(request).concat(logoutRedirectTo.substring(1));
+ // Match the 'wreply' parameter against the constraint
+ String logoutRedirectTo = null;
+ Pattern logoutRedirectToConstraint = config.getLogoutRedirectToConstraint();
+ if (request.getParameter(FederationConstants.PARAM_REPLY) != null) {
+ if (logoutRedirectToConstraint == null) {
+ LOG.debug("No regular expression constraint configured for logout. Ignoring wreply parameter");
} else {
- logoutRedirectTo = extractFullContextPath(request).concat(logoutRedirectTo);
+ Matcher matcher =
+ logoutRedirectToConstraint.matcher(request.getParameter(FederationConstants.PARAM_REPLY));
+ if (matcher.matches()) {
+ logoutRedirectTo = request.getParameter(FederationConstants.PARAM_REPLY);
+ } else {
+ LOG.warn("The received wreply address {} does not match the configured constraint {}",
+ logoutRedirectTo, logoutRedirectToConstraint);
+ }
}
-
+ }
+
+ if (logoutRedirectTo != null && !logoutRedirectTo.isEmpty()) {
LOG.debug("wreply={}", logoutRedirectTo);
sb.append('&').append(FederationConstants.PARAM_REPLY).append('=');
sb.append(URLEncoder.encode(logoutRedirectTo, "UTF-8"));
+ } else {
+ logoutRedirectTo = config.getLogoutRedirectTo();
+ if (logoutRedirectTo != null && !logoutRedirectTo.isEmpty()) {
+
+ if (logoutRedirectTo.startsWith("/")) {
+ logoutRedirectTo = extractFullContextPath(request).concat(logoutRedirectTo.substring(1));
+ } else {
+ logoutRedirectTo = extractFullContextPath(request).concat(logoutRedirectTo);
+ }
+
+ LOG.debug("wreply={}", logoutRedirectTo);
+ sb.append('&').append(FederationConstants.PARAM_REPLY).append('=');
+ sb.append(URLEncoder.encode(logoutRedirectTo, "UTF-8"));
+ }
}
redirectURL = redirectURL + "?" + sb.toString();
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/e8889b43/plugins/core/src/main/resources/schemas/FedizConfig.xsd
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/resources/schemas/FedizConfig.xsd b/plugins/core/src/main/resources/schemas/FedizConfig.xsd
index b556e8b..47b3a98 100644
--- a/plugins/core/src/main/resources/schemas/FedizConfig.xsd
+++ b/plugins/core/src/main/resources/schemas/FedizConfig.xsd
@@ -27,6 +27,7 @@
<xs:element ref="protocol" />
<xs:element ref="logoutURL" minOccurs="0" />
<xs:element ref="logoutRedirectTo" minOccurs="0" />
+ <xs:element ref="logoutRedirectToConstraint" minOccurs="0" />
</xs:sequence>
<xs:attribute name="name" use="required" type="xs:string" />
@@ -143,6 +144,16 @@
</xs:documentation>
</xs:annotation>
</xs:element>
+
+ <xs:element name="logoutRedirectToConstraint" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>A regular expression constraint on the 'wreply' parameter, which is used to obtain the URL to
+ navigate to after successful logout. If the constraint is not specified, then the 'wreply' parameter is ignored
+ and instead the URL is taken from the "logoutRedirectTo" configuration option.
+ Example: 'https://localhost:12345/logout.*/'
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
<xs:complexType name="federationProtocolType">
<xs:complexContent>
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/e8889b43/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationLogoutTest.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationLogoutTest.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationLogoutTest.java
new file mode 100644
index 0000000..dedc9f4
--- /dev/null
+++ b/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationLogoutTest.java
@@ -0,0 +1,357 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.fediz.core.federation;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLEncoder;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.cxf.fediz.common.SecurityTestUtil;
+import org.apache.cxf.fediz.core.FederationConstants;
+import org.apache.cxf.fediz.core.config.FedizConfigurator;
+import org.apache.cxf.fediz.core.config.FedizContext;
+import org.apache.cxf.fediz.core.handler.LogoutHandler;
+import org.easymock.EasyMock;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+
+/**
+ * Some tests for logout for WS-Federation
+ */
+public class FederationLogoutTest {
+ private static final String LOGOUT_URL = "https://localhost/fedizhelloworld/secure/logout";
+ private static final String LOGOUT_URI = "/secure/logout";
+ private static final String REPLY_URL = "https://localhost/fedizhelloworld/secure/wreply.html";
+ private static final String BAD_REPLY_URL = "https://localhost/fedizhelloworld/secure/badreply.html";
+
+ private static final String CONFIG_FILE = "fediz_test_config_logout.xml";
+
+ private static FedizConfigurator configurator;
+ private static DocumentBuilderFactory docBuilderFactory;
+
+ static {
+ docBuilderFactory = DocumentBuilderFactory.newInstance();
+ docBuilderFactory.setNamespaceAware(true);
+ }
+
+
+ @BeforeClass
+ public static void init() {
+ getFederationConfigurator();
+ Assert.assertNotNull(configurator);
+ }
+
+ @AfterClass
+ public static void cleanup() {
+ SecurityTestUtil.cleanup();
+ }
+
+
+ private static FedizConfigurator getFederationConfigurator() {
+ if (configurator != null) {
+ return configurator;
+ }
+ try {
+ configurator = new FedizConfigurator();
+ final URL resource = Thread.currentThread().getContextClassLoader()
+ .getResource(CONFIG_FILE);
+ File f = new File(resource.toURI());
+ configurator.loadConfig(f);
+ return configurator;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ @org.junit.Test
+ public void testSignoutCustomURL() throws Exception {
+ FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+
+ HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION)).andReturn(null).anyTimes();
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(null);
+ EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer(LOGOUT_URL));
+ EasyMock.expect(req.getRequestURI()).andReturn(LOGOUT_URI);
+ EasyMock.expect(req.getContextPath()).andReturn(LOGOUT_URI);
+ EasyMock.replay(req);
+
+ LogoutHandler logoutHandler = new LogoutHandler(config);
+ Assert.assertTrue(logoutHandler.canHandleRequest(req));
+
+ HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+ String expectedRedirectToIdP =
+ "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Flogout%2Findex.html";
+ resp.sendRedirect(expectedRedirectToIdP);
+ EasyMock.expectLastCall();
+ EasyMock.replay(resp);
+ logoutHandler.handleRequest(req, resp);
+ }
+
+ @org.junit.Test
+ public void testSignoutCustomURLWithWReply() throws Exception {
+ FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+
+ HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION)).andReturn(null).anyTimes();
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(REPLY_URL).anyTimes();
+ EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer(LOGOUT_URL));
+ EasyMock.expect(req.getRequestURI()).andReturn(LOGOUT_URI);
+ EasyMock.expect(req.getContextPath()).andReturn(LOGOUT_URI);
+ EasyMock.replay(req);
+
+ LogoutHandler logoutHandler = new LogoutHandler(config);
+ Assert.assertTrue(logoutHandler.canHandleRequest(req));
+
+ HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+ String expectedRedirectToIdP =
+ "http://url_to_the_issuer?wa=wsignout1.0&wreply=" + URLEncoder.encode(REPLY_URL, "UTF-8");
+ resp.sendRedirect(expectedRedirectToIdP);
+ EasyMock.expectLastCall();
+ EasyMock.replay(resp);
+ logoutHandler.handleRequest(req, resp);
+ }
+
+ @org.junit.Test
+ public void testSignoutCustomURLWithBadWReply() throws Exception {
+ FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+
+ HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION)).andReturn(null).anyTimes();
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(BAD_REPLY_URL).anyTimes();
+ EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer(LOGOUT_URL));
+ EasyMock.expect(req.getRequestURI()).andReturn(LOGOUT_URI);
+ EasyMock.expect(req.getContextPath()).andReturn(LOGOUT_URI);
+ EasyMock.replay(req);
+
+ LogoutHandler logoutHandler = new LogoutHandler(config);
+ Assert.assertTrue(logoutHandler.canHandleRequest(req));
+
+ HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+ String expectedRedirectToIdP =
+ "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Flogout%2Findex.html";
+ resp.sendRedirect(expectedRedirectToIdP);
+ EasyMock.expectLastCall();
+ EasyMock.replay(resp);
+ logoutHandler.handleRequest(req, resp);
+ }
+
+ @org.junit.Test
+ public void testSignoutCustomURLWithNoConfiguredConstraint() throws Exception {
+ FedizContext config = getFederationConfigurator().getFedizContext("ROOT2");
+
+ HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION)).andReturn(null).anyTimes();
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(REPLY_URL).anyTimes();
+ EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer(LOGOUT_URL));
+ EasyMock.expect(req.getRequestURI()).andReturn(LOGOUT_URI);
+ EasyMock.expect(req.getContextPath()).andReturn(LOGOUT_URI);
+ EasyMock.replay(req);
+
+ LogoutHandler logoutHandler = new LogoutHandler(config);
+ Assert.assertTrue(logoutHandler.canHandleRequest(req));
+
+ HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+ String expectedRedirectToIdP =
+ "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Flogout%2Findex.html";
+ resp.sendRedirect(expectedRedirectToIdP);
+ EasyMock.expectLastCall();
+ EasyMock.replay(resp);
+ logoutHandler.handleRequest(req, resp);
+ }
+
+ @org.junit.Test
+ public void testSignoutAction() throws Exception {
+ FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+
+ HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION))
+ .andReturn(FederationConstants.ACTION_SIGNOUT).anyTimes();
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(null);
+ EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer("https://localhost/fedizhelloworld/secure"));
+ EasyMock.expect(req.getRequestURI()).andReturn("/secure");
+ EasyMock.expect(req.getContextPath()).andReturn("/secure");
+ EasyMock.replay(req);
+
+ LogoutHandler logoutHandler = new LogoutHandler(config);
+ Assert.assertTrue(logoutHandler.canHandleRequest(req));
+
+ HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+ String expectedRedirectToIdP =
+ "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Findex.html";
+ resp.sendRedirect(expectedRedirectToIdP);
+ EasyMock.expectLastCall();
+ EasyMock.replay(resp);
+ logoutHandler.handleRequest(req, resp);
+ }
+
+ @org.junit.Test
+ public void testSignoutActionWithWReply() throws Exception {
+ FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+
+ HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION))
+ .andReturn(FederationConstants.ACTION_SIGNOUT).anyTimes();
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(REPLY_URL).anyTimes();
+ EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer("https://localhost/fedizhelloworld/secure"));
+ EasyMock.expect(req.getRequestURI()).andReturn("/secure");
+ EasyMock.expect(req.getContextPath()).andReturn("/secure");
+ EasyMock.replay(req);
+
+ LogoutHandler logoutHandler = new LogoutHandler(config);
+ Assert.assertTrue(logoutHandler.canHandleRequest(req));
+
+ HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+ String expectedRedirectToIdP =
+ "http://url_to_the_issuer?wa=wsignout1.0&wreply=" + URLEncoder.encode(REPLY_URL, "UTF-8");
+ resp.sendRedirect(expectedRedirectToIdP);
+ EasyMock.expectLastCall();
+ EasyMock.replay(resp);
+ logoutHandler.handleRequest(req, resp);
+ }
+
+ @org.junit.Test
+ public void testSignoutActionWithBadWReply() throws Exception {
+ FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+
+ HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION))
+ .andReturn(FederationConstants.ACTION_SIGNOUT).anyTimes();
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(BAD_REPLY_URL).anyTimes();
+ EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer("https://localhost/fedizhelloworld/secure"));
+ EasyMock.expect(req.getRequestURI()).andReturn("/secure");
+ EasyMock.expect(req.getContextPath()).andReturn("/secure");
+ EasyMock.replay(req);
+
+ LogoutHandler logoutHandler = new LogoutHandler(config);
+ Assert.assertTrue(logoutHandler.canHandleRequest(req));
+
+ HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+ String expectedRedirectToIdP =
+ "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Findex.html";
+ resp.sendRedirect(expectedRedirectToIdP);
+ EasyMock.expectLastCall();
+ EasyMock.replay(resp);
+ logoutHandler.handleRequest(req, resp);
+ }
+
+ @org.junit.Test
+ public void testSignoutActionWithNoConfiguredConstraint() throws Exception {
+ FedizContext config = getFederationConfigurator().getFedizContext("ROOT2");
+
+ HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION))
+ .andReturn(FederationConstants.ACTION_SIGNOUT).anyTimes();
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(REPLY_URL).anyTimes();
+ EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer("https://localhost/fedizhelloworld/secure"));
+ EasyMock.expect(req.getRequestURI()).andReturn("/secure");
+ EasyMock.expect(req.getContextPath()).andReturn("/secure");
+ EasyMock.replay(req);
+
+ LogoutHandler logoutHandler = new LogoutHandler(config);
+ Assert.assertTrue(logoutHandler.canHandleRequest(req));
+
+ HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+ String expectedRedirectToIdP =
+ "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Findex.html";
+ resp.sendRedirect(expectedRedirectToIdP);
+ EasyMock.expectLastCall();
+ EasyMock.replay(resp);
+ logoutHandler.handleRequest(req, resp);
+ }
+
+ @org.junit.Test
+ public void testSignoutCleanupWithWReply() throws Exception {
+ FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+
+ HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+ HttpSession session = EasyMock.createMock(HttpSession.class);
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION))
+ .andReturn(FederationConstants.ACTION_SIGNOUT_CLEANUP).anyTimes();
+ EasyMock.expect(req.getSession()).andReturn(session);
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(REPLY_URL).anyTimes();
+ EasyMock.replay(req);
+
+ LogoutHandler logoutHandler = new LogoutHandler(config);
+ Assert.assertTrue(logoutHandler.canHandleRequest(req));
+
+ HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+ String expectedRedirect = URLEncoder.encode(REPLY_URL, "UTF-8");
+ resp.sendRedirect(expectedRedirect);
+ EasyMock.expectLastCall();
+ EasyMock.replay(resp);
+ logoutHandler.handleRequest(req, resp);
+ }
+
+ @org.junit.Test
+ public void testSignoutCleanupWithBadWReply() throws Exception {
+ FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+
+ HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+ HttpSession session = EasyMock.createMock(HttpSession.class);
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION))
+ .andReturn(FederationConstants.ACTION_SIGNOUT_CLEANUP).anyTimes();
+ EasyMock.expect(req.getSession()).andReturn(session);
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(BAD_REPLY_URL).anyTimes();
+ EasyMock.replay(req);
+
+ LogoutHandler logoutHandler = new LogoutHandler(config);
+ Assert.assertTrue(logoutHandler.canHandleRequest(req));
+
+ HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+ resp.setContentType("image/jpeg");
+ ServletOutputStream outputStream = EasyMock.createMock(ServletOutputStream.class);
+ EasyMock.expect(resp.getOutputStream()).andReturn(outputStream);
+ EasyMock.expectLastCall();
+ EasyMock.replay(resp);
+ logoutHandler.handleRequest(req, resp);
+ }
+
+ @org.junit.Test
+ public void testSignoutCleanupWithNoConfiguredConstraint() throws Exception {
+ FedizContext config = getFederationConfigurator().getFedizContext("ROOT2");
+
+ HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+ HttpSession session = EasyMock.createMock(HttpSession.class);
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION))
+ .andReturn(FederationConstants.ACTION_SIGNOUT_CLEANUP).anyTimes();
+ EasyMock.expect(req.getSession()).andReturn(session);
+ EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(REPLY_URL).anyTimes();
+ EasyMock.replay(req);
+
+ LogoutHandler logoutHandler = new LogoutHandler(config);
+ Assert.assertTrue(logoutHandler.canHandleRequest(req));
+
+ HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+ resp.setContentType("image/jpeg");
+ ServletOutputStream outputStream = EasyMock.createMock(ServletOutputStream.class);
+ EasyMock.expect(resp.getOutputStream()).andReturn(outputStream);
+ EasyMock.expectLastCall();
+ EasyMock.replay(resp);
+ logoutHandler.handleRequest(req, resp);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/e8889b43/plugins/core/src/test/resources/fediz_test_config_logout.xml
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/resources/fediz_test_config_logout.xml b/plugins/core/src/test/resources/fediz_test_config_logout.xml
new file mode 100644
index 0000000..030281e
--- /dev/null
+++ b/plugins/core/src/test/resources/fediz_test_config_logout.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<FedizConfig>
+ <contextConfig name="ROOT">
+ <audienceUris>
+ <audienceItem>http://host_one:port/url</audienceItem>
+ </audienceUris>
+ <certificateStores>
+ <trustManager>
+ <keyStore file="ststrust.jks" password="storepass"
+ type="JKS" />
+ </trustManager>
+ </certificateStores>
+ <trustedIssuers>
+ <issuer certificateValidation="PeerTrust" />
+ </trustedIssuers>
+
+ <maximumClockSkew>1000</maximumClockSkew>
+ <protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:type="federationProtocolType" version="1.2">
+ <realm>target realm</realm>
+ <issuer>http://url_to_the_issuer</issuer>
+ <roleDelimiter>;</roleDelimiter>
+ <roleURI>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role</roleURI>
+ <authenticationType value="some auth type" type="String" />
+ <freshness>10000</freshness>
+ <reply>reply value</reply>
+ <request>REQUEST</request>
+ <claimTypesRequested>
+ <claimType type="a particular claim type" optional="true" />
+ </claimTypesRequested>
+ </protocol>
+ <logoutURL>secure/logout</logoutURL>
+ <logoutRedirectTo>/index.html</logoutRedirectTo>
+ <logoutRedirectToConstraint>.*wreply.html</logoutRedirectToConstraint>
+ </contextConfig>
+
+ <contextConfig name="ROOT2">
+ <audienceUris>
+ <audienceItem>http://host_one:port/url</audienceItem>
+ </audienceUris>
+ <certificateStores>
+ <trustManager>
+ <keyStore file="ststrust.jks" password="storepass"
+ type="JKS" />
+ </trustManager>
+ </certificateStores>
+ <trustedIssuers>
+ <issuer certificateValidation="PeerTrust" />
+ </trustedIssuers>
+
+ <maximumClockSkew>1000</maximumClockSkew>
+ <protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:type="federationProtocolType" version="1.2">
+ <realm>target realm</realm>
+ <issuer>http://url_to_the_issuer</issuer>
+ <roleDelimiter>;</roleDelimiter>
+ <roleURI>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role</roleURI>
+ <authenticationType value="some auth type" type="String" />
+ <freshness>10000</freshness>
+ <reply>reply value</reply>
+ <request>REQUEST</request>
+ <claimTypesRequested>
+ <claimType type="a particular claim type" optional="true" />
+ </claimTypesRequested>
+ </protocol>
+ <logoutURL>secure/logout</logoutURL>
+ <logoutRedirectTo>/index.html</logoutRedirectTo>
+ </contextConfig>
+
+</FedizConfig>