Adding a Filter that plays like WSFederationAuthenticationModule and decuple the concept of session token #2

Closed
wants to merge 1 commit into
from
View
@@ -15,6 +15,8 @@ local.properties
.classpath
.settings/
.loadpath
+*.class
+classes/
# External tool builders
.externalToolBuilders/
@@ -94,4 +94,14 @@ public String getReply() {
public String[] getAudienceUris() {
return this.properties.getProperty("federation.audienceuris").split("\\|");
}
+
+ public Boolean getEnableManualRedirect() {
+ String manual = this.properties.getProperty("federation.enableManualRedirect");
+ if (manual != null && Boolean.parseBoolean(manual)) {
+ return true;
+ }
+
+ return false;
+ }
+
}
@@ -0,0 +1,32 @@
+package com.microsoft.samples.federation;
+
+import java.security.Principal;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+public final class FederatedHttpServletRequest extends HttpServletRequestWrapper {
+
+ private final transient FederatedPrincipal principal;
+
+ public FederatedHttpServletRequest(HttpServletRequest request, FederatedPrincipal principal) {
+ super(request);
+ this.principal = principal;
+ }
+
+ @Override
+ public Principal getUserPrincipal() {
+ return this.principal;
+ }
+
+ @Override
+ public String getRemoteUser() {
+ if (this.principal == null) {
+ return super.getRemoteUser();
+ }
+ else {
+ return this.principal.getName();
+ }
+ }
+}
+
@@ -29,7 +29,6 @@
import java.net.URI;
import java.net.URISyntaxException;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
@@ -42,7 +41,6 @@
import org.joda.time.format.ISODateTimeFormat;
public class FederatedLoginManager {
- private static final String PRINCIPAL_SESSION_VARIABLE = "FederatedPrincipal";
private static final DateTimeFormatter CHECKING_FORMAT = ISODateTimeFormat.dateTime().withZone(DateTimeZone.UTC);
private HttpServletRequest request;
@@ -61,36 +59,7 @@ protected FederatedLoginManager(HttpServletRequest request, FederatedAuthenticat
this.listener = listener;
}
- public FederatedPrincipal getPrincipal() {
- return (FederatedPrincipal) request.getSession().getAttribute(PRINCIPAL_SESSION_VARIABLE);
- }
-
- public List<Claim> getClaims() {
- return normalizeClaimList(((FederatedPrincipal) request.getSession().getAttribute(PRINCIPAL_SESSION_VARIABLE)).getClaims());
- }
-
- private List<Claim> normalizeClaimList(List<Claim> originalList) {
- if (originalList != null) {
- List<Claim> normalizedList = new ArrayList<Claim>();
-
- for (Claim currentClaim : originalList) {
- String[] claimValues = currentClaim.getClaimValues();
- for (String claimValue : claimValues) {
- normalizedList.add(new Claim(currentClaim.getClaimType(), claimValue));
- }
- }
-
- return normalizedList;
- }
-
- return null;
- }
-
- public boolean isAuthenticated() {
- return request.getSession().getAttribute(PRINCIPAL_SESSION_VARIABLE) != null;
- }
-
- public final void authenticate(String token, HttpServletResponse response) throws FederationException {
+ public final FederatedPrincipal authenticate(String token, HttpServletResponse response) throws FederationException {
List<Claim> claims = null;
try {
@@ -105,13 +74,10 @@ public final void authenticate(String token, HttpServletResponse response) throw
claims = validator.validate(token);
FederatedPrincipal principal = new FederatedPrincipal(claims);
- request.getSession().setAttribute(PRINCIPAL_SESSION_VARIABLE, principal);
if (listener != null) listener.OnAuthenticationSucceed(principal);
- response.setHeader("Location", request.getParameter("wctx"));
- response.setStatus(302);
-
+ return principal;
} catch (FederationException e) {
throw e;
} catch (Exception e) {
@@ -0,0 +1,143 @@
+package com.microsoft.samples.federation;
+
+import java.io.IOException;
+import java.util.regex.Pattern;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class WSFederationFilter implements Filter {
+
+ private static final String PRINCIPAL_SESSION_VARIABLE = "FederatedPrincipal";
+
+ private String loginPage;
+ private String excludedUrlsRegex;
+
+ public void init(FilterConfig config) throws ServletException {
+ this.loginPage = config.getInitParameter("login-page-url");
+ this.excludedUrlsRegex = config.getInitParameter("exclude-urls-regex");
+ }
+
+ public void doFilter(ServletRequest request, ServletResponse response,
+ FilterChain chain) throws IOException, ServletException {
+
+ FederatedPrincipal principal = null;
+ HttpServletRequest httpRequest = (HttpServletRequest) request;
+
+ HttpServletResponse httpResponse = (HttpServletResponse) response;
+
+ // is the request is a token?
+ if (this.isSignInResponse(httpRequest)) {
+ principal = this.authenticateWithToken(httpRequest, httpResponse);
+ this.writeSessionToken(httpRequest, principal);
+ this.redirectToOriginalUrl(httpRequest, httpResponse);
+ }
+
+ // is principal in session?
+ if (principal == null && this.sessionTokenExists(httpRequest)) {
+ principal = this.authenticateWithSessionToken(httpRequest, httpResponse);
+ }
+
+ // if not authenticated at this point, redirect to login page
+ boolean excludedUrl = httpRequest.getRequestURL().toString().contains(this.loginPage) ||
+ (this.excludedUrlsRegex != null &&
+ !this.excludedUrlsRegex.isEmpty() &&
+ Pattern.compile(this.excludedUrlsRegex).matcher(httpRequest.getRequestURL().toString()).find());
+
+ if (!excludedUrl && principal == null) {
+ if (!FederatedConfiguration.getInstance().getEnableManualRedirect()) {
+ this.redirectToIdentityProvider(httpRequest, httpResponse);
+ } else {
+ this.redirectToLoginPage(httpRequest, httpResponse);
+ }
+
+ return;
+ }
+
+ chain.doFilter(new FederatedHttpServletRequest(httpRequest, principal), response);
+ }
+
+ protected void redirectToLoginPage(HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
+ String encodedReturnUrl = URLUTF8Encoder.encode(getRequestPathAndQuery(httpRequest));
+ String redirect = this.loginPage + "?returnUrl=" + encodedReturnUrl;
+ httpResponse.setHeader("Location", redirect);
+ httpResponse.setStatus(302);
+ }
+
+ protected void redirectToIdentityProvider(HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
+ String wctx = getRequestPathAndQuery(httpRequest);
+ String redirect = FederatedLoginManager.getFederatedLoginUrl(wctx);
+
+ httpResponse.setHeader("Location", redirect);
+ httpResponse.setStatus(302);
+ }
+
+ protected void redirectToOriginalUrl(HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
+ String wctx = httpRequest.getParameter("wctx");
+ if (wctx != null) {
+ httpResponse.setHeader("Location", wctx);
+ httpResponse.setStatus(302);
+ }
+ }
+
+ protected Boolean isSignInResponse(HttpServletRequest request) {
+ if (request.getMethod().equals("POST") &&
+ request.getParameter("wa").equals("wsignin1.0") &&
+ request.getParameter("wresult") != null) {
+ return true;
+ }
+
+ return false;
+ }
+
+ protected Boolean sessionTokenExists(HttpServletRequest request) {
+ // this could use signed cookies instead of sessions
+ return request.getSession().getAttribute(PRINCIPAL_SESSION_VARIABLE) != null;
+ }
+
+ protected FederatedPrincipal authenticateWithSessionToken(HttpServletRequest request, HttpServletResponse response) throws IOException {
+ return (FederatedPrincipal) request.getSession().getAttribute(PRINCIPAL_SESSION_VARIABLE);
+ }
+
+ protected void writeSessionToken(HttpServletRequest request, FederatedPrincipal principal) throws IOException {
+ request.getSession().setAttribute(PRINCIPAL_SESSION_VARIABLE, principal);
+ }
+
+ protected FederatedPrincipal authenticateWithToken(HttpServletRequest request, HttpServletResponse response) throws IOException {
+ String token = request.getParameter("wresult").toString();
+
+ if (token == null) {
+ response.sendError(400, "You were supposed to send a wresult parameter with a token");
+ }
+
+ FederatedLoginManager loginManager = FederatedLoginManager.fromRequest(request, null);
+
+ try {
+ FederatedPrincipal principal = loginManager.authenticate(token, response);
+ return principal;
+ } catch (FederationException e) {
+ response.sendError(500, "Oops and error occurred validating the token.");
+ }
+
+ return null;
+ }
+
+ public void destroy() {
+ }
+
+ private static String getRequestPathAndQuery(HttpServletRequest req) {
+ String reqUri = req.getRequestURI().toString();
+ String queryString = req.getQueryString();
+ if (queryString != null) {
+ reqUri += "?" + queryString;
+ }
+
+ return reqUri;
+ }
+}