Redirect to originally requested page after sign-in
authorKai Moritz <kai@juplo.de>
Sat, 30 Jan 2016 11:19:18 +0000 (12:19 +0100)
committerKai Moritz <kai@juplo.de>
Thu, 26 May 2016 11:34:25 +0000 (13:34 +0200)
src/main/java/de/juplo/yourshouter/SocialAuthenticationEntryPoint.java
src/main/java/de/juplo/yourshouter/SpringSecuritySignInAdapter.java

index 4c3671c..f119314 100644 (file)
@@ -4,6 +4,7 @@ import java.io.IOException;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.security.core.AuthenticationException;
@@ -24,12 +25,24 @@ public class SocialAuthenticationEntryPoint implements AuthenticationEntryPoint
   private static final Logger LOG =
       LoggerFactory.getLogger(SocialAuthenticationEntryPoint.class);
 
+  public final static String REDIRECT_ATTRIBUTE =
+      SocialAuthenticationEntryPoint.class.getCanonicalName() + ".REDIRECT";
+
 
   /**
    * {@inheritDoc}
    *
-   * To commence the sign-in through the Graph-API, we only have to redirect
+   * To commence the sign-in through the Graph-API, we have to redirect
    * to our already implemented sign-in-page.
+   * <p>
+   * We store the originally requested page in the {@link HttpSession}, to be
+   * redirect back to that page after a successful authentication in
+   * {@link SpringSecuritySignInAdapter}.
+   * <p>
+   * Only the first request of a ressource, that requires authentication, will
+   * trigger the redirect to the sing-in-page.
+   *
+   * @see SpringSecuritySignInAdapter
    */
   @Override
   public void commence(
@@ -41,10 +54,29 @@ public class SocialAuthenticationEntryPoint implements AuthenticationEntryPoint
         IOException,
         ServletException
   {
-    LOG.info(
-        "redirecting unauthenticated request {} to /signin.html",
-        request.getRequestURI()
-        );
-    response.sendRedirect("/signin.html");
+    HttpSession session = request.getSession();
+    if (session.getAttribute(REDIRECT_ATTRIBUTE) == null)
+    {
+      LOG.info(
+          "redirecting unauthenticated request to {}",
+          request.getRequestURI()
+          );
+      StringBuffer url = request.getRequestURL();
+      if (request.getQueryString() != null)
+      {
+        url.append('?');
+        url.append(request.getQueryString());
+      }
+      session.setAttribute(REDIRECT_ATTRIBUTE, url.toString());
+      response.sendRedirect("/signin.html");
+    }
+    else
+    {
+      LOG.info(
+          "redirect to sign-in already in progress, forbidding access to {}",
+          request.getRequestURI()
+          );
+      response.sendError(HttpServletResponse.SC_FORBIDDEN);
+    }
   }
 }
index 05c978b..24cf904 100644 (file)
@@ -1,6 +1,8 @@
 package de.juplo.yourshouter;
 
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -31,23 +33,20 @@ public class SpringSecuritySignInAdapter implements SignInAdapter
       LoggerFactory.getLogger(SpringSecuritySignInAdapter.class);
 
   /**
+   * {@inheritDoc}
+   *
    * Stores the user in the {@link SecurityContext} provided by Spring Security
    * to sign him in. Spring Security will automatically persist the
    * authentication in the user-session for subsequent requests.
+   * <p>
+   * If an originally requested ressource was stored in the {@link HttpSession}
+   * by the {@link SocialAuthenticationEntryPoint}, that URL will be returned,
+   * so that the {@link RequestCache} can restore the request.
+   * Otherwise, <code>null</code> will be returned, to indicate, that the user
+   * should be redirected to the default-post-sign-in-URL (configured in
+   * {@link ProviderSinInController}) after a successfull authentication.
    *
-   * @param user
-   *     The user-ID. We configured Spring-Social to call
-   *     {@link UserCookieSignInAdapter} to extract a user-ID from the
-   *     connection.
-   * @param connection
-   *     The connection. In our case a connection to Facebook.
-   * @param request
-   *     The actual request. We need it, to store the cookie.
-   * @return
-   *     We return <code>null</code>, to indicate, that the user should be
-   *     redirected to the default-post-sign-in-URL (configured in
-   *     {@link ProviderSinInController}) after a successfull authentication.
-   *
+   * @see {@link SocialAuthenticationEntryPoint}
    * @see {@link ProviderSignInController#postSignInUrl}
    */
   @Override
@@ -66,7 +65,20 @@ public class SpringSecuritySignInAdapter implements SignInAdapter
     SecurityContextHolder.getContext().setAuthentication(
         new UsernamePasswordAuthenticationToken(user, null, null));
 
-    // We return null to trigger a redirect to "/".
-    return null;
+    HttpSession session =
+        request.getNativeRequest(HttpServletRequest.class).getSession();
+    String redirect =
+        (String)session
+            .getAttribute(SocialAuthenticationEntryPoint.REDIRECT_ATTRIBUTE);
+    if (redirect != null)
+    {
+      LOG.info("redirecting to originally requested resource {}", redirect);
+      session.removeAttribute(SocialAuthenticationEntryPoint.REDIRECT_ATTRIBUTE);
+    }
+    else
+    {
+      LOG.info("found no original request in session, redirecting to default");
+    }
+    return redirect;
   }
 }