diff --git a/src/main/java/de/thm/arsnova/config/SecurityConfig.java b/src/main/java/de/thm/arsnova/config/SecurityConfig.java
index cbb810fddca8544baf8279762f15c7dedbf54abd..63a018f2e15268cba4948975b941f76d53cfad6f 100644
--- a/src/main/java/de/thm/arsnova/config/SecurityConfig.java
+++ b/src/main/java/de/thm/arsnova/config/SecurityConfig.java
@@ -23,6 +23,8 @@ import de.thm.arsnova.security.LoginAuthenticationFailureHandler;
 import de.thm.arsnova.security.LoginAuthenticationSucessHandler;
 import de.thm.arsnova.security.CustomLdapUserDetailsMapper;
 import de.thm.arsnova.security.RegisteredUserDetailsService;
+import de.thm.arsnova.security.jwt.JwtAuthenticationProvider;
+import de.thm.arsnova.security.jwt.JwtTokenFilter;
 import de.thm.arsnova.security.pac4j.OauthCallbackFilter;
 import de.thm.arsnova.security.pac4j.OauthAuthenticationProvider;
 import org.jasig.cas.client.validation.Cas20ProxyTicketValidator;
@@ -53,6 +55,7 @@ import org.springframework.security.config.annotation.method.configuration.Enabl
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
 import org.springframework.security.core.session.SessionRegistry;
 import org.springframework.security.core.session.SessionRegistryImpl;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@@ -67,6 +70,7 @@ import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
 import org.springframework.security.ldap.userdetails.LdapUserDetailsMapper;
 import org.springframework.security.web.AuthenticationEntryPoint;
 import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
 import org.springframework.security.web.authentication.logout.LogoutFilter;
 import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
 import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
@@ -132,11 +136,13 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
 	@Override
 	protected void configure(HttpSecurity http) throws Exception {
+		http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
 		http.exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint());
 		http.csrf().disable();
 		http.headers()
 			.addHeaderWriter(new HstsHeaderWriter(false));
 
+		http.addFilterBefore(jwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
 		if (casEnabled) {
 			http.addFilter(casAuthenticationFilter());
 			http.addFilter(casLogoutFilter());
@@ -150,6 +156,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
 	@Override
 	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
 		List<String> providers = new ArrayList<>();
+		auth.authenticationProvider(jwtAuthenticationProvider());
 		if (ldapEnabled) {
 			providers.add("ldap");
 			auth.authenticationProvider(ldapAuthenticationProvider());
@@ -200,6 +207,17 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
 		return new Http403ForbiddenEntryPoint();
 	}
 
+	@Bean
+	public JwtAuthenticationProvider jwtAuthenticationProvider() {
+		return new JwtAuthenticationProvider();
+	}
+
+	@Bean
+	public JwtTokenFilter jwtTokenFilter() throws Exception {
+		JwtTokenFilter jwtTokenFilter = new JwtTokenFilter();
+		return jwtTokenFilter;
+	}
+
 	@Bean
 	LoginAuthenticationSucessHandler successHandler() {
 		final LoginAuthenticationSucessHandler successHandler = new LoginAuthenticationSucessHandler();
diff --git a/src/main/java/de/thm/arsnova/security/jwt/JwtAuthenticationProvider.java b/src/main/java/de/thm/arsnova/security/jwt/JwtAuthenticationProvider.java
index ac7d51b46379a822f8d249bd778603f459805918..569a4df5f46c8288a3290a80d7dde9726b21bc6a 100644
--- a/src/main/java/de/thm/arsnova/security/jwt/JwtAuthenticationProvider.java
+++ b/src/main/java/de/thm/arsnova/security/jwt/JwtAuthenticationProvider.java
@@ -1,6 +1,7 @@
 package de.thm.arsnova.security.jwt;
 
 import de.thm.arsnova.security.User;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.authentication.AuthenticationProvider;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;
@@ -8,10 +9,6 @@ import org.springframework.security.core.AuthenticationException;
 public class JwtAuthenticationProvider implements AuthenticationProvider {
 	private JwtService jwtService;
 
-	public JwtAuthenticationProvider(final JwtService jwtService) {
-		this.jwtService = jwtService;
-	}
-
 	@Override
 	public Authentication authenticate(final Authentication authentication) throws AuthenticationException {
 		final String token = (String) authentication.getCredentials();
@@ -24,4 +21,9 @@ public class JwtAuthenticationProvider implements AuthenticationProvider {
 	public boolean supports(final Class<?> aClass) {
 		return JwtToken.class.isAssignableFrom(aClass);
 	}
+
+	@Autowired
+	public void setJwtService(final JwtService jwtService) {
+		this.jwtService = jwtService;
+	}
 }
diff --git a/src/main/java/de/thm/arsnova/security/jwt/JwtService.java b/src/main/java/de/thm/arsnova/security/jwt/JwtService.java
index f1620aaee8146fc16d6f9323a065b3681c6dc616..ee5bb47fffd51db137e57099bff9303f5e394207 100644
--- a/src/main/java/de/thm/arsnova/security/jwt/JwtService.java
+++ b/src/main/java/de/thm/arsnova/security/jwt/JwtService.java
@@ -71,6 +71,6 @@ public class JwtService {
 		final Collection<GrantedAuthority> authorities = decodedJwt.getClaim(ROLES_CLAIM_NAME).asList(String.class).stream()
 				.map(role -> new SimpleGrantedAuthority(ROLE_PREFIX + role)).collect(Collectors.toList());
 
-		return new User(userService.get(userId), authorities);
+		return userService.loadUser(userId, authorities);
 	}
 }
diff --git a/src/main/java/de/thm/arsnova/security/jwt/JwtToken.java b/src/main/java/de/thm/arsnova/security/jwt/JwtToken.java
index f7ce5cea3d421d8a3fed6e97572db5f8787ef87c..ecce14b5bebb2669ab1007b076a6cb858f2538dc 100644
--- a/src/main/java/de/thm/arsnova/security/jwt/JwtToken.java
+++ b/src/main/java/de/thm/arsnova/security/jwt/JwtToken.java
@@ -16,6 +16,7 @@ public class JwtToken extends AbstractAuthenticationToken {
 		super(grantedAuthorities);
 		this.token = token;
 		this.principal = principal;
+		setAuthenticated(!grantedAuthorities.isEmpty());
 	}
 
 	public JwtToken(final String token) {
diff --git a/src/main/java/de/thm/arsnova/security/jwt/JwtTokenFilter.java b/src/main/java/de/thm/arsnova/security/jwt/JwtTokenFilter.java
index 282a3c16b825e9fa3b2bc4fd9cd2c9e53ec010d4..f8c5e2e062e3676799da5e7154de2cd7722642da 100644
--- a/src/main/java/de/thm/arsnova/security/jwt/JwtTokenFilter.java
+++ b/src/main/java/de/thm/arsnova/security/jwt/JwtTokenFilter.java
@@ -1,29 +1,50 @@
 package de.thm.arsnova.security.jwt;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.core.Authentication;
-import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
-import org.springframework.security.web.authentication.preauth.PreAuthenticatedCredentialsNotFoundException;
-import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.GenericFilterBean;
 
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
 
-public class JwtTokenFilter extends AbstractAuthenticationProcessingFilter {
+@Component
+public class JwtTokenFilter extends GenericFilterBean {
 	private static final String JWT_HEADER_NAME = "Arsnova-Auth-Token";
-
-	protected JwtTokenFilter() {
-		super(new AntPathRequestMatcher("/**"));
-	}
+	private static final Logger logger = LoggerFactory.getLogger(JwtTokenFilter.class);
+	private JwtAuthenticationProvider jwtAuthenticationProvider;
 
 	@Override
-	public Authentication attemptAuthentication(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse) throws AuthenticationException {
-		String jwtHeader = httpServletRequest.getHeader(JWT_HEADER_NAME);
-		if (jwtHeader == null) {
-			throw new PreAuthenticatedCredentialsNotFoundException("No authentication header present.");
+	public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
+		String jwtHeader = ((HttpServletRequest) servletRequest).getHeader(JWT_HEADER_NAME);
+		if (jwtHeader != null) {
+			JwtToken token = new JwtToken(jwtHeader);
+			try {
+				Authentication authenticatedToken = jwtAuthenticationProvider.authenticate(token);
+				if (authenticatedToken != null) {
+					logger.debug("Storing JWT to SecurityContext: {}", authenticatedToken);
+					SecurityContextHolder.getContext().setAuthentication(authenticatedToken);
+				} else {
+					logger.debug("Could not authenticate JWT.");
+				}
+			} catch (final Exception e) {
+				logger.debug("JWT authentication failed", e);
+			}
+		} else {
+			logger.debug("No authentication header present.");
 		}
-		JwtToken token = new JwtToken(jwtHeader);
+		filterChain.doFilter(servletRequest, servletResponse);
+	}
 
-		return getAuthenticationManager().authenticate(token);
+	@Autowired
+	public void setJwtAuthenticationProvider(final JwtAuthenticationProvider jwtAuthenticationProvider) {
+		this.jwtAuthenticationProvider = jwtAuthenticationProvider;
 	}
 }
diff --git a/src/main/java/de/thm/arsnova/services/UserService.java b/src/main/java/de/thm/arsnova/services/UserService.java
index 2fab0d042d3c909e4f37b868b47c9db678d1f0f4..814bcd84cfd9ab1356b23a3c93bf5bc201fa6f01 100644
--- a/src/main/java/de/thm/arsnova/services/UserService.java
+++ b/src/main/java/de/thm/arsnova/services/UserService.java
@@ -73,6 +73,8 @@ public interface UserService extends EntityService<UserProfile> {
 	User loadUser(UserProfile.AuthProvider authProvider, String loginId,
 			Collection<GrantedAuthority> grantedAuthorities, boolean autoCreate) throws UsernameNotFoundException;
 
+	User loadUser(String userId, Collection<GrantedAuthority> grantedAuthorities);
+
 	UserProfile getByAuthProviderAndLoginId(UserProfile.AuthProvider authProvider, String loginId);
 
 	UserProfile getByUsername(String username);
diff --git a/src/main/java/de/thm/arsnova/services/UserServiceImpl.java b/src/main/java/de/thm/arsnova/services/UserServiceImpl.java
index c9ce4bd48c955d690f8c7387b66f0f6c8618af8d..87ef81be2697919b16e7cf2a89092622f4e91130 100644
--- a/src/main/java/de/thm/arsnova/services/UserServiceImpl.java
+++ b/src/main/java/de/thm/arsnova/services/UserServiceImpl.java
@@ -398,6 +398,18 @@ public class UserServiceImpl extends DefaultEntityServiceImpl<UserProfile> imple
 		return new User(userProfile, grantedAuthorities);
 	}
 
+	@Override
+	public User loadUser(final String userId, final Collection<GrantedAuthority> grantedAuthorities)
+			throws UsernameNotFoundException {
+		logger.debug("Load user: UserId: {}", userId);
+		UserProfile userProfile = userRepository.findOne(userId);
+		if (userProfile == null) {
+			throw new UsernameNotFoundException("User does not exist.");
+		}
+
+		return new User(userProfile, grantedAuthorities);
+	}
+
 	@Override
 	public UserProfile getByAuthProviderAndLoginId(final UserProfile.AuthProvider authProvider, final String loginId) {
 		return userRepository.findByAuthProviderAndLoginId(authProvider, loginId);