Switched from the manual implemented authentication-layer to Spring Security
authorKai Moritz <kai@juplo.de>
Fri, 29 Jan 2016 12:49:43 +0000 (13:49 +0100)
committerKai Moritz <kai@juplo.de>
Thu, 26 May 2016 11:34:22 +0000 (13:34 +0200)
12 files changed:
pom.xml
src/main/java/de/juplo/yourshouter/SecurityContext.java [deleted file]
src/main/java/de/juplo/yourshouter/SecurityContextUserIdSource.java [deleted file]
src/main/java/de/juplo/yourshouter/SocialAuthenticationEntryPoint.java [new file with mode: 0644]
src/main/java/de/juplo/yourshouter/SocialConfig.java
src/main/java/de/juplo/yourshouter/SpringSecurityContextUserIdSource.java [new file with mode: 0644]
src/main/java/de/juplo/yourshouter/SpringSecuritySignInAdapter.java [new file with mode: 0644]
src/main/java/de/juplo/yourshouter/UserCookieGenerator.java [deleted file]
src/main/java/de/juplo/yourshouter/UserCookieInterceptor.java [deleted file]
src/main/java/de/juplo/yourshouter/UserCookieSignInAdapter.java [deleted file]
src/main/java/de/juplo/yourshouter/WebMvcConfig.java
src/main/java/de/juplo/yourshouter/WebSecurityConfig.java [new file with mode: 0644]

diff --git a/pom.xml b/pom.xml
index 91aaa8b..5c70ea4 100644 (file)
--- a/pom.xml
+++ b/pom.xml
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-thymeleaf</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-security</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.springframework.social</groupId>
       <artifactId>spring-social-facebook</artifactId>
       <groupId>org.springframework.social</groupId>
       <artifactId>spring-social-facebook-web</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.springframework.security</groupId>
-      <artifactId>spring-security-crypto</artifactId>
-      <scope>runtime</scope>
-    </dependency>
     <!-- Httpclient -->
     <dependency>
       <groupId>org.apache.httpcomponents</groupId>
diff --git a/src/main/java/de/juplo/yourshouter/SecurityContext.java b/src/main/java/de/juplo/yourshouter/SecurityContext.java
deleted file mode 100644 (file)
index 37ca54c..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-package de.juplo.yourshouter;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-
-/**
- * Simple SecurityContext that stores the currently signed-in connection in a
- * thread local.
- *
- * @author Kai Moritz
- */
-public final class SecurityContext
-{
-  private final static Logger LOG = LoggerFactory.getLogger(SecurityContext.class);
-  private final static ThreadLocal<String> CURRENT_USER = new ThreadLocal<>();
-
-
-  /**
-   * Fetches the ID of the current user from the thread-local.
-   *
-   * @return
-   *     The ID of the current user, or <code>null</code> if no user is known.
-   */
-  public static String getCurrentUser()
-  {
-    String user = CURRENT_USER.get();
-    LOG.debug("current user: {}", user);
-    return user;
-  }
-
-  /**
-   * Stores the given ID as the ID of the current user in the thread-local.
-   *
-   * @param user
-   *     The ID to store as the ID of the current user.
-   */
-  public static void setCurrentUser(String user)
-  {
-    LOG.debug("setting current user: {}", user);
-    CURRENT_USER.set(user);
-  }
-
-  /**
-   * Checks, if a user is signed in. That is, if the ID of a user is stored in
-   * the thread-local.
-   *
-   * @return
-   *   <code>true</code>, if a user is signed in, <code>false</code> otherwise.
-   */
-  public static boolean userSignedIn()
-  {
-    boolean signedIn = CURRENT_USER.get() != null;
-    LOG.debug("user signed in: {}", signedIn);
-    return signedIn;
-  }
-
-  /**
-   * Removes the ID of the current user from the thread-local.
-   */
-  public static void remove()
-  {
-    LOG.debug("removing current user");
-    CURRENT_USER.remove();
-  }
-}
diff --git a/src/main/java/de/juplo/yourshouter/SecurityContextUserIdSource.java b/src/main/java/de/juplo/yourshouter/SecurityContextUserIdSource.java
deleted file mode 100644 (file)
index 662da57..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-package de.juplo.yourshouter;
-
-import org.springframework.social.UserIdSource;
-import org.springframework.util.Assert;
-
-
-/**
- * Implementation of {@link UserIdSource}, that retrieves the ID of the current
- * user from the {@link SecurityContext}.
- *
- * @author Kai Moritz
- */
-public class SecurityContextUserIdSource implements UserIdSource
-{
-  /**
-   * Retrieves the ID of the current user from the {@link SecurityContext}.
-   * If no ID is found, an exception is thrown.
-   *
-   * @return The ID of the current user
-   * @throws IllegalStateException, if no current user is found.
-   */
-  @Override
-  public String getUserId()
-  {
-    Assert.state(SecurityContext.userSignedIn(), "No user signed in!");
-    return SecurityContext.getCurrentUser();
-  }
-}
diff --git a/src/main/java/de/juplo/yourshouter/SocialAuthenticationEntryPoint.java b/src/main/java/de/juplo/yourshouter/SocialAuthenticationEntryPoint.java
new file mode 100644 (file)
index 0000000..4c3671c
--- /dev/null
@@ -0,0 +1,50 @@
+package de.juplo.yourshouter;
+
+import java.io.IOException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Service;
+
+
+/**
+ * Specialized implementation of {@link AuthenticationEntryPoint}, that
+ * redirects to the social sign-in-page, to let the user decide to sign in or
+ * not.
+ *
+ * @author Kai Moritz
+ */
+@Service
+public class SocialAuthenticationEntryPoint implements AuthenticationEntryPoint
+{
+  private static final Logger LOG =
+      LoggerFactory.getLogger(SocialAuthenticationEntryPoint.class);
+
+
+  /**
+   * {@inheritDoc}
+   *
+   * To commence the sign-in through the Graph-API, we only have to redirect
+   * to our already implemented sign-in-page.
+   */
+  @Override
+  public void commence(
+      HttpServletRequest request,
+      HttpServletResponse response,
+      AuthenticationException exception
+      )
+      throws
+        IOException,
+        ServletException
+  {
+    LOG.info(
+        "redirecting unauthenticated request {} to /signin.html",
+        request.getRequestURI()
+        );
+    response.sendRedirect("/signin.html");
+  }
+}
index 4573fbb..7cc9a63 100644 (file)
@@ -11,6 +11,7 @@ import org.springframework.context.annotation.ScopedProxyMode;
 import org.springframework.social.UserIdSource;
 import org.springframework.core.env.Environment;
 import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.security.core.context.SecurityContext;
 import org.springframework.social.config.annotation.ConnectionFactoryConfigurer;
 import org.springframework.social.config.annotation.EnableSocial;
 import org.springframework.social.config.annotation.SocialConfigurerAdapter;
@@ -101,7 +102,7 @@ public class SocialConfig extends SocialConfigurerAdapter
   @Override
   public UserIdSource getUserIdSource()
   {
-    return new SecurityContextUserIdSource();
+    return new SpringSecurityContextUserIdSource();
   }
 
 
diff --git a/src/main/java/de/juplo/yourshouter/SpringSecurityContextUserIdSource.java b/src/main/java/de/juplo/yourshouter/SpringSecurityContextUserIdSource.java
new file mode 100644 (file)
index 0000000..d774060
--- /dev/null
@@ -0,0 +1,33 @@
+package de.juplo.yourshouter;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.social.UserIdSource;
+import org.springframework.util.Assert;
+
+
+/**
+ * Implementation of {@link UserIdSource}, that retrieves the ID of the current
+ * user from the {@link SecurityContext}.
+ *
+ * @author Kai Moritz
+ */
+public class SpringSecurityContextUserIdSource implements UserIdSource
+{
+  /**
+   * Retrieves the ID of the current user from the {@link SecurityContext}.
+   * If no ID is found, an exception is thrown.
+   *
+   * @return The ID of the current user
+   * @throws IllegalStateException, if no current user is found.
+   */
+  @Override
+  public String getUserId()
+  {
+    SecurityContext context = SecurityContextHolder.getContext();
+    Authentication authentication = context.getAuthentication();
+    Assert.state(authentication != null, "No user signed in!");
+    return authentication.getName();
+  }
+}
diff --git a/src/main/java/de/juplo/yourshouter/SpringSecuritySignInAdapter.java b/src/main/java/de/juplo/yourshouter/SpringSecuritySignInAdapter.java
new file mode 100644 (file)
index 0000000..05c978b
--- /dev/null
@@ -0,0 +1,72 @@
+package de.juplo.yourshouter;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.social.connect.Connection;
+import org.springframework.social.connect.web.SignInAdapter;
+import org.springframework.stereotype.Service;
+import org.springframework.web.context.request.NativeWebRequest;
+
+
+/**
+ * Simple implementation of {@link SignInAdapter}.
+ *
+ * This implementation signes in the user by storing him in the
+ * {@link SecurityContext} provided by Spring-Security, using the user-ID as
+ * principal.
+ *
+ * We configured Spring-Social to call this implementation, to sign in the
+ * user, after he was authenticated by Facebook.
+ *
+ * @author Kai Moritz
+ */
+@Service
+public class SpringSecuritySignInAdapter implements SignInAdapter
+{
+  private final static Logger LOG =
+      LoggerFactory.getLogger(SpringSecuritySignInAdapter.class);
+
+  /**
+   * 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.
+   *
+   * @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 ProviderSignInController#postSignInUrl}
+   */
+  @Override
+  public String signIn(
+      String user,
+      Connection<?> connection,
+      NativeWebRequest request
+      )
+  {
+    LOG.info(
+        "signing in user {} (connected via {})",
+        user,
+        connection.getKey().getProviderId()
+        );
+
+    SecurityContextHolder.getContext().setAuthentication(
+        new UsernamePasswordAuthenticationToken(user, null, null));
+
+    // We return null to trigger a redirect to "/".
+    return null;
+  }
+}
diff --git a/src/main/java/de/juplo/yourshouter/UserCookieGenerator.java b/src/main/java/de/juplo/yourshouter/UserCookieGenerator.java
deleted file mode 100644 (file)
index 48d7078..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-package de.juplo.yourshouter;
-
-
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.springframework.web.util.CookieGenerator;
-import org.thymeleaf.util.StringUtils;
-
-
-/**
- * Utility class for managing the cookie that remembers the user.
- *
- * @author Kai Moritz
- */
-final class UserCookieGenerator
-{
-  private final static Logger LOG =
-      LoggerFactory.getLogger(UserCookieGenerator.class);
-
-  public final static UserCookieGenerator INSTANCE = new UserCookieGenerator();
-
-
-  private final CookieGenerator generator = new CookieGenerator();
-
-
-  /**
-   * Constructs an instance of this class, using <code>user</code> as the
-   * cookie-name.
-   */
-  private UserCookieGenerator()
-  {
-    generator.setCookieName("user");
-  }
-
-
-  /**
-   * Creates a cookie with the name <code>user</code>, that stores the ID of
-   * the user for subsequent calls.
-   *
-   * @param user
-   *     The ID of the current user
-   * @param response
-   *     The {@link HttpServletResponse} to store the cookie in.
-   */
-  public void addCookie(String user, HttpServletResponse response)
-  {
-    LOG.debug("adding cookie {}={}", generator.getCookieName(), user);
-    generator.addCookie(response, user);
-  }
-
-  /**
-   * Removes the cookie with the name <code>user</code> by storing an empty
-   * string as its value.
-   *
-   * @param response
-   *     The {@link HttpServletResponse} to remove the cookie from.
-   */
-  public void removeCookie(HttpServletResponse response)
-  {
-    LOG.debug("removing cookie {}", generator.getCookieName());
-    generator.addCookie(response, "");
-  }
-
-  /**
-   * Reads the current value of the cookie with the name <code>user</code>.
-   *
-   * @param request
-   *   The {@link HttpServletRequest} to read the cookie-value from.
-   * @return
-   *   The value of the cookie with the name <code>user</code>, or
-   *   <code>null</code>, if no cookie by that name can be found or the value
-   *   of the cookie is an empty string.
-   */
-  public String readCookieValue(HttpServletRequest request)
-  {
-    String name = generator.getCookieName();
-    Cookie[] cookies = request.getCookies();
-    if (cookies != null)
-    {
-      for (Cookie cookie : cookies)
-      {
-        if (cookie.getName().equals(name))
-        {
-          String value = cookie.getValue();
-          if (!StringUtils.isEmptyOrWhitespace(value))
-          {
-            LOG.debug("found cookie {}={}", name, value);
-            return value;
-          }
-        }
-      }
-    }
-    LOG.debug("cookie \"{}\" not found!", name);
-    return null;
-  }
-}
diff --git a/src/main/java/de/juplo/yourshouter/UserCookieInterceptor.java b/src/main/java/de/juplo/yourshouter/UserCookieInterceptor.java
deleted file mode 100644 (file)
index 1b00e09..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-package de.juplo.yourshouter;
-
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.regex.Pattern;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.springframework.social.connect.UsersConnectionRepository;
-import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
-
-
-/**
- * Intercepts all requests to handle the user-cookie.
- *
- * @author Kai Moritz
- */
-public final class UserCookieInterceptor extends HandlerInterceptorAdapter
-{
-  private final static Logger LOG =
-      LoggerFactory.getLogger(UserCookieInterceptor.class);
-  private final static Pattern PATTERN = Pattern.compile("^/signin|canvas");
-
-
-  private final UsersConnectionRepository repository;
-
-
-  /**
-   * Creates an instance of this class, that uses the given instance of
-   * {@link UsersConnectionRepository}.
-   *
-   * @param repository
-   *     The instance of {@link UsersConnectionRepository} to use.
-   */
-  public UserCookieInterceptor(UsersConnectionRepository repository)
-  {
-    this.repository = repository;
-  }
-
-
-  /**
-   * Before a request is handled, the current user is loaded from the cookie,
-   * if the cookie is present and the user is known. If the user is not known,
-   * the cookie is removed.
-   *
-   * @param request
-   *     The {@link HttpServletRequest} that is intercepted.
-   * @param response
-   *     The {@link HttpServletResponse} that is intercepted.
-   * @param handler
-   *     The handler, that handles the intercepted request.
-   * @return
-   *     Always <code>true</code>, to indicate, that the intercepted request
-   *     should be handled normally.
-   * @throws java.io.IOException
-   *     if something wents wrong, while sending the redirect to the
-   *     sign-in-page.
-   */
-  @Override
-  public boolean preHandle(
-      HttpServletRequest request,
-      HttpServletResponse response,
-      Object handler
-      )
-      throws
-        IOException
-  {
-    if (PATTERN.matcher(request.getServletPath()).find())
-      return true;
-
-    String user = UserCookieGenerator.INSTANCE.readCookieValue(request);
-    if (user != null)
-    {
-      if (!repository
-          .findUserIdsConnectedTo("facebook", Collections.singleton(user))
-          .isEmpty()
-          )
-      {
-        LOG.info("loading user {} from cookie", user);
-        SecurityContext.setCurrentUser(user);
-        return true;
-      }
-      else
-      {
-        LOG.warn("user {} is not known!", user);
-        UserCookieGenerator.INSTANCE.removeCookie(response);
-      }
-    }
-
-    response.sendRedirect("/signin.html");
-    return false;
-  }
-
-  /**
-   * After a request, the user is removed from the security-context.
-   *
-   * @param request
-   *     The {@link HttpServletRequest} that is intercepted.
-   * @param response
-   *     The {@link HttpServletResponse} that is intercepted.
-   * @param handler
-   *     The handler, that handles the intercepted request.
-   * @param exception
-   *     If an exception was thrown during the handling of this request, it is
-   *     handed in through this parameter.
-   */
-  @Override
-  public void afterCompletion(
-      HttpServletRequest request,
-      HttpServletResponse response,
-      Object handler,
-      Exception exception
-      )
-  {
-    SecurityContext.remove();
-  }
-}
diff --git a/src/main/java/de/juplo/yourshouter/UserCookieSignInAdapter.java b/src/main/java/de/juplo/yourshouter/UserCookieSignInAdapter.java
deleted file mode 100644 (file)
index 88cf156..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-package de.juplo.yourshouter;
-
-import javax.servlet.http.HttpServletResponse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.social.connect.Connection;
-import org.springframework.social.connect.web.SignInAdapter;
-import org.springframework.stereotype.Service;
-import org.springframework.web.context.request.NativeWebRequest;
-
-
-/**
- * Simple implementation of {@link SignInAdapter}.
- *
- * We configured Spring-Social to call this implementation, to sign in the
- * user, after he was authenticated by Facebook.
- *
- * @author Kai Moritz
- */
-@Service
-public class UserCookieSignInAdapter implements SignInAdapter
-{
-  private final static Logger LOG =
-      LoggerFactory.getLogger(UserCookieSignInAdapter.class);
-
-
-  /**
-   * Stores the user in the security-context to sign him in.
-   * Also remembers the user for subsequent calls by storing the ID in the
-   * cookie.
-   *
-   * @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 UserCookieSignInAdapter}
-   * @see {@link ProviderSignInController#postSignInUrl}
-   */
-  @Override
-  public String signIn(
-      String user,
-      Connection<?> connection,
-      NativeWebRequest request
-      )
-  {
-    LOG.info(
-        "signing in user {} (connected via {})",
-        user,
-        connection.getKey().getProviderId()
-        );
-    SecurityContext.setCurrentUser(user);
-    UserCookieGenerator
-        .INSTANCE
-        .addCookie(user, request.getNativeResponse(HttpServletResponse.class));
-
-    // We return null to trigger a redirect to "/".
-    return null;
-  }
-}
index 6676ae6..d520d24 100644 (file)
@@ -2,12 +2,9 @@ package de.juplo.yourshouter;
 
 
 
-import javax.inject.Inject;
 
 import org.springframework.context.annotation.Configuration;
-import org.springframework.social.connect.UsersConnectionRepository;
 import org.springframework.web.servlet.config.annotation.EnableWebMvc;
-import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
 
@@ -21,24 +18,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
 @EnableWebMvc
 public class WebMvcConfig extends WebMvcConfigurerAdapter
 {
-  @Inject
-  private UsersConnectionRepository usersConnectionRepository;
-
-
-  /**
-   * Configure the {@link UserCookieInterceptor} to intercept all requests.
-   *
-   * @param registry
-   *     The {@link InterceptorRegistry} to use.
-   *
-   * @see {@link UserCookieInterceptor}
-   */
-  @Override
-  public void addInterceptors(InterceptorRegistry registry)
-  {
-    registry.addInterceptor(new UserCookieInterceptor(usersConnectionRepository));
-  }
-
   /**
    * {@inheritDoc}
    */
diff --git a/src/main/java/de/juplo/yourshouter/WebSecurityConfig.java b/src/main/java/de/juplo/yourshouter/WebSecurityConfig.java
new file mode 100644 (file)
index 0000000..738485e
--- /dev/null
@@ -0,0 +1,89 @@
+package de.juplo.yourshouter;
+
+import javax.inject.Inject;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
+
+
+@Configuration
+@EnableWebSecurity
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter
+{
+  @Inject
+  AuthenticationEntryPoint authenticationEntryPoint;
+
+  /**
+   * We have to disable the default-configuration, because some of it does
+   * not work along with the canvas-page:
+   * <ul>
+   * <li>
+   * The support for CSRF-tokens consideres the initial call of Facebook to
+   * the canvas-page of our app as invalid, because it is issued as a post
+   * and the CSRF-token is missing.
+   * </li>
+   * <li>
+   * In the default-configuration, the <code>X-Frame-Options: DENY</code> is
+   * set for every response. This prevents the browser from showing our
+   * response inside Facebook, becaus that is an iFrame and the header
+   * forbidds to display our content in a frame.
+   * </li>
+   * </ul>
+   */
+  public WebSecurityConfig()
+  {
+    super(true);
+  }
+
+
+  /**
+   * @{@inheritDoc}
+   *
+   * Override the default-implementation to configure the authentication
+   * mechanism of Spring Security.
+   *
+   * We drop the support of CSRF-tokens, inject our specialized implementation
+   * of the {@link AuthenticationEntryPoint}-interface , disable the headers,
+   * that deny, to display our content insiede a frame and configure the
+   * pages, that should be accessible without authentication.
+   * We also drop support for a logout-page and the default-login-in-page.
+   */
+  @Override
+  protected void configure(HttpSecurity http) throws Exception
+  {
+    http
+                               .addFilter(new WebAsyncManagerIntegrationFilter())
+        .exceptionHandling()
+            .authenticationEntryPoint(authenticationEntryPoint)
+            .and()
+        .headers()
+            .frameOptions().disable()
+            .and()
+                               .sessionManagement().and()
+                               .securityContext().and()
+                               .requestCache().and()
+                               .anonymous().and()
+                               .servletApi().and()
+        .authorizeRequests()
+            .antMatchers("/signin.html", "/signin/*", "/canvas/*").permitAll()
+            .anyRequest().authenticated();
+  }
+
+  /**
+   * {@inheritDoc}
+   *
+   * Override the default-implementation, to configure Spring Security to use
+   * in-memory authentication.
+   */
+  @Override
+  public void configure(AuthenticationManagerBuilder auth)
+      throws
+        Exception
+  {
+    auth.inMemoryAuthentication();
+  }
+}