diff --git a/src/main/java/de/thm/arsnova/config/SecurityConfig.java b/src/main/java/de/thm/arsnova/config/SecurityConfig.java
index 6f43c5b03318d87277d2ff1a0477ab7d8543cfcf..4f85089c3a28687a5ec52ac577baa698917f0d2f 100644
--- a/src/main/java/de/thm/arsnova/config/SecurityConfig.java
+++ b/src/main/java/de/thm/arsnova/config/SecurityConfig.java
@@ -584,6 +584,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
 	public OauthCallbackFilter oauthCallbackFilter() throws Exception {
 		final OauthCallbackFilter callbackFilter = new OauthCallbackFilter(oauthConfig(), OAUTH_CALLBACK_PATH);
 		callbackFilter.setAuthenticationManager(authenticationManager());
+		callbackFilter.setAuthenticationSuccessHandler(successHandler());
+		callbackFilter.setAuthenticationFailureHandler(failureHandler());
 
 		return callbackFilter;
 	}
diff --git a/src/main/java/de/thm/arsnova/controller/AuthenticationController.java b/src/main/java/de/thm/arsnova/controller/AuthenticationController.java
index 7dead0ff264aa83cea65e9f328e1cb3c89f9d57b..eb7774be4b580855ac884958f19adfd6a5f1a4cc 100644
--- a/src/main/java/de/thm/arsnova/controller/AuthenticationController.java
+++ b/src/main/java/de/thm/arsnova/controller/AuthenticationController.java
@@ -18,44 +18,73 @@
 
 package de.thm.arsnova.controller;
 
+import java.io.IOException;
+import java.util.Arrays;
+import javax.servlet.ServletException;
+import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.pac4j.core.context.J2EContext;
+import org.pac4j.oidc.client.OidcClient;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.servlet.View;
+import org.springframework.web.servlet.view.RedirectView;
 
+import de.thm.arsnova.config.SecurityConfig;
 import de.thm.arsnova.model.ClientAuthentication;
 import de.thm.arsnova.model.LoginCredentials;
 import de.thm.arsnova.model.UserProfile;
+import de.thm.arsnova.security.LoginAuthenticationSucessHandler;
 import de.thm.arsnova.service.UserService;
 
 @RestController
 @RequestMapping("/auth")
 public class AuthenticationController {
 	private UserService userService;
+	private OidcClient oidcClient;
+	private CasAuthenticationEntryPoint casEntryPoint;
 
 	public AuthenticationController(final UserService userService) {
 		this.userService = userService;
 	}
 
-	@PostMapping("/login")
-	public ClientAuthentication login() {
-		return userService.getCurrentClientAuthentication();
+	@Autowired(required = false)
+	public void setOidcClient(final OidcClient oidcClient) {
+		this.oidcClient = oidcClient;
 	}
 
-	@PostMapping("/login/registered")
-	public ClientAuthentication loginRegistered(@RequestBody final LoginCredentials loginCredentials,
-			final HttpServletRequest request) {
-		final String loginId = loginCredentials.getLoginId().toLowerCase();
-		userService.authenticate(new UsernamePasswordAuthenticationToken(loginId, loginCredentials.getPassword()),
-				UserProfile.AuthProvider.ARSNOVA, request.getRemoteAddr());
-		return userService.getCurrentClientAuthentication();
+	@Autowired(required = false)
+	public void setCasEntryPoint(final CasAuthenticationEntryPoint casEntryPoint) {
+		this.casEntryPoint = casEntryPoint;
+	}
+
+	@PostMapping("/login")
+	public ClientAuthentication login(@RequestParam(defaultValue = "false") final boolean refresh,
+			final HttpServletRequest request, final HttpServletResponse response) {
+		if (request.getCookies() != null && Arrays.stream(request.getCookies())
+				.anyMatch(c -> c.getName().equalsIgnoreCase(LoginAuthenticationSucessHandler.AUTH_COOKIE_NAME))) {
+			/* Delete cookie */
+			final Cookie cookie = new Cookie(LoginAuthenticationSucessHandler.AUTH_COOKIE_NAME, null);
+			cookie.setPath(request.getContextPath());
+			cookie.setMaxAge(0);
+			response.addCookie(cookie);
+		}
+
+		return userService.getCurrentClientAuthentication(refresh);
 	}
 
 	@PostMapping("/login/guest")
 	public ClientAuthentication loginGuest(final HttpServletRequest request) {
-		final ClientAuthentication currentAuthentication = userService.getCurrentClientAuthentication();
+		final ClientAuthentication currentAuthentication = userService.getCurrentClientAuthentication(false);
 		if (currentAuthentication != null
 				&& currentAuthentication.getAuthProvider() == UserProfile.AuthProvider.ARSNOVA_GUEST) {
 			return currentAuthentication;
@@ -63,6 +92,51 @@ public class AuthenticationController {
 		userService.authenticate(new UsernamePasswordAuthenticationToken(null, null),
 				UserProfile.AuthProvider.ARSNOVA_GUEST, request.getRemoteAddr());
 
-		return userService.getCurrentClientAuthentication();
+		return userService.getCurrentClientAuthentication(false);
+	}
+
+	@PostMapping("/login/{providerId}")
+	public ClientAuthentication loginViaProvider(
+			@PathVariable final String providerId,
+			@RequestBody final LoginCredentials loginCredentials,
+			final HttpServletRequest request) {
+		switch (providerId) {
+			case "registered":
+				final String loginId = loginCredentials.getLoginId().toLowerCase();
+				userService.authenticate(new UsernamePasswordAuthenticationToken(
+						loginId, loginCredentials.getPassword()),
+						UserProfile.AuthProvider.ARSNOVA, request.getRemoteAddr());
+
+				return userService.getCurrentClientAuthentication(false);
+			case SecurityConfig.LDAP_PROVIDER_ID:
+				userService.authenticate(new UsernamePasswordAuthenticationToken(
+						loginCredentials.getLoginId(), loginCredentials.getPassword()),
+						UserProfile.AuthProvider.LDAP, request.getRemoteAddr());
+
+				return userService.getCurrentClientAuthentication(false);
+			default:
+				throw new IllegalArgumentException("Invalid provider ID.");
+		}
+	}
+
+	@GetMapping("/sso/{providerId}")
+	public View redirectToSso(@PathVariable final String providerId,
+			final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException {
+		switch (providerId) {
+			case SecurityConfig.OIDC_PROVIDER_ID:
+				if (oidcClient == null) {
+					throw new IllegalArgumentException("Invalid provider ID.");
+				}
+				return new RedirectView(
+						oidcClient.getRedirectAction(new J2EContext(request, response)).getLocation());
+			case SecurityConfig.CAS_PROVIDER_ID:
+				if (casEntryPoint == null) {
+					throw new IllegalArgumentException("Invalid provider ID.");
+				}
+				casEntryPoint.commence(request, response, null);
+				return null;
+			default:
+				throw new IllegalArgumentException("Invalid provider ID.");
+		}
 	}
 }
diff --git a/src/main/java/de/thm/arsnova/controller/v2/AuthenticationController.java b/src/main/java/de/thm/arsnova/controller/v2/AuthenticationController.java
index 9f2782e5242c3a7a864c76c0d7c391bdece9f1dc..dd0beb4fb9ccb2e10392cd129b528ba4280c51d6 100644
--- a/src/main/java/de/thm/arsnova/controller/v2/AuthenticationController.java
+++ b/src/main/java/de/thm/arsnova/controller/v2/AuthenticationController.java
@@ -66,6 +66,8 @@ import de.thm.arsnova.controller.AbstractController;
 import de.thm.arsnova.model.ServiceDescription;
 import de.thm.arsnova.model.UserProfile;
 import de.thm.arsnova.model.migration.v2.ClientAuthentication;
+import de.thm.arsnova.security.LoginAuthenticationFailureHandler;
+import de.thm.arsnova.security.LoginAuthenticationSucessHandler;
 import de.thm.arsnova.security.User;
 import de.thm.arsnova.service.UserService;
 import de.thm.arsnova.web.exceptions.UnauthorizedException;
@@ -208,8 +210,8 @@ public class AuthenticationController extends AbstractController {
 			}
 		}
 
-		request.getSession().setAttribute("ars-login-success-url", serverUrl + successUrl);
-		request.getSession().setAttribute("ars-login-failure-url", serverUrl + failureUrl);
+		request.getSession().setAttribute(LoginAuthenticationSucessHandler.URL_ATTRIBUTE, serverUrl + successUrl);
+		request.getSession().setAttribute(LoginAuthenticationFailureHandler.URL_ATTRIBUTE, serverUrl + failureUrl);
 
 		if (casProperties.isEnabled() && "cas".equals(type)) {
 			casEntryPoint.commence(request, response, null);
diff --git a/src/main/java/de/thm/arsnova/model/AuthenticationProvider.java b/src/main/java/de/thm/arsnova/model/AuthenticationProvider.java
index 961e5f2e7bb3fa95a2c8c6e56760466fbcab073c..d455a785bcbf4f52eb8aad983320e94b601c24e3 100644
--- a/src/main/java/de/thm/arsnova/model/AuthenticationProvider.java
+++ b/src/main/java/de/thm/arsnova/model/AuthenticationProvider.java
@@ -28,7 +28,7 @@ public class AuthenticationProvider {
 	public enum Type {
 		ANONYMOUS,
 		USERNAME_PASSWORD,
-		EXTERNAL
+		SSO
 	}
 
 	private String id;
@@ -51,7 +51,7 @@ public class AuthenticationProvider {
 				|| provider instanceof AuthenticationProviderProperties.Ldap) {
 			type = Type.USERNAME_PASSWORD;
 		} else {
-			type = Type.EXTERNAL;
+			type = Type.SSO;
 		}
 	}
 
diff --git a/src/main/java/de/thm/arsnova/security/LoginAuthenticationFailureHandler.java b/src/main/java/de/thm/arsnova/security/LoginAuthenticationFailureHandler.java
index c3330f1eb8584a65b7df30059e258e77e66c6121..d5b5f1600c06d0a2544fdcdf8e15fcad0f9468e1 100644
--- a/src/main/java/de/thm/arsnova/security/LoginAuthenticationFailureHandler.java
+++ b/src/main/java/de/thm/arsnova/security/LoginAuthenticationFailureHandler.java
@@ -34,6 +34,7 @@ import org.springframework.security.web.authentication.SimpleUrlAuthenticationFa
  */
 public class LoginAuthenticationFailureHandler extends
 		SimpleUrlAuthenticationFailureHandler {
+	public static final String URL_ATTRIBUTE = "ars-login-failure-url";
 
 	private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
 	private String failureUrl;
@@ -45,8 +46,8 @@ public class LoginAuthenticationFailureHandler extends
 			final AuthenticationException exception
 	) throws IOException, ServletException {
 		final HttpSession session = request.getSession();
-		if (session != null && session.getAttribute("ars-login-failure-url") != null) {
-			failureUrl = (String) session.getAttribute("ars-login-failure-url");
+		if (session != null && session.getAttribute(URL_ATTRIBUTE) != null) {
+			failureUrl = (String) session.getAttribute(URL_ATTRIBUTE);
 		}
 
 		redirectStrategy.sendRedirect(request, response, failureUrl);
diff --git a/src/main/java/de/thm/arsnova/security/LoginAuthenticationSucessHandler.java b/src/main/java/de/thm/arsnova/security/LoginAuthenticationSucessHandler.java
index fe16ae086ac33c41e5e49466ac570a9ed877cec1..07c8d5f8a17427c60f4dc603dbec1ec3d66024ce 100644
--- a/src/main/java/de/thm/arsnova/security/LoginAuthenticationSucessHandler.java
+++ b/src/main/java/de/thm/arsnova/security/LoginAuthenticationSucessHandler.java
@@ -18,29 +18,63 @@
 
 package de.thm.arsnova.security;
 
+import java.io.IOException;
+import javax.servlet.ServletException;
+import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.security.core.Authentication;
 import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
 
+import de.thm.arsnova.security.jwt.JwtService;
+
 /**
  * This class gets called when a user successfully logged in.
  */
 public class LoginAuthenticationSucessHandler extends
 		SimpleUrlAuthenticationSuccessHandler {
+	public static final String AUTH_COOKIE_NAME = "auth";
+	public static final String URL_ATTRIBUTE = "ars-login-success-url";
 
+	private JwtService jwtService;
 	private String targetUrl;
 
+	@Autowired
+	public void setJwtService(final JwtService jwtService) {
+		this.jwtService = jwtService;
+	}
+
 	@Override
 	protected String determineTargetUrl(
 			final HttpServletRequest request,
 			final HttpServletResponse response) {
-		final HttpSession session = request.getSession();
-		if (session == null || session.getAttribute("ars-login-success-url") == null) {
-			return targetUrl;
-		}
+		final HttpSession session = request.getSession(false);
+		final String url = (String) session.getAttribute(URL_ATTRIBUTE);
+		session.removeAttribute(URL_ATTRIBUTE);
 
-		return (String) session.getAttribute("ars-login-success-url");
+		return url;
+	}
+
+	@Override
+	public void onAuthenticationSuccess(final HttpServletRequest request, final HttpServletResponse response,
+			final Authentication authentication) throws IOException, ServletException {
+		final HttpSession session = request.getSession(false);
+		if (session == null || session.getAttribute(URL_ATTRIBUTE) == null) {
+			final String token = jwtService.createSignedToken((User) authentication.getPrincipal(), true);
+			final Cookie cookie = new Cookie(AUTH_COOKIE_NAME, token);
+			cookie.setPath(request.getContextPath());
+			cookie.setSecure(request.isSecure());
+			cookie.setHttpOnly(true);
+			response.addCookie(cookie);
+			response.setContentType(MediaType.TEXT_HTML_VALUE);
+			response.getWriter().println("<!DOCTYPE html><script>if (window.opener) window.close()</script>");
+
+			return;
+		}
+		super.onAuthenticationSuccess(request, response, authentication);
 	}
 
 	public void setTargetUrl(final String url) {
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 0c2dc71ecef4c4be8119efd63b8cf82b0217ca6f..f24a901895144a8e986d77ff654f4ec9017779da 100644
--- a/src/main/java/de/thm/arsnova/security/jwt/JwtService.java
+++ b/src/main/java/de/thm/arsnova/security/jwt/JwtService.java
@@ -46,6 +46,7 @@ public class JwtService {
 	private String serverId;
 	private TemporalAmount defaultValidityPeriod;
 	private TemporalAmount guestValidityPeriod;
+	private TemporalAmount temporaryValidityPeriod;
 	private JWTVerifier verifier;
 	private UserService userService;
 
@@ -56,19 +57,21 @@ public class JwtService {
 		this.serverId = securityProperties.getJwt().getServerId();
 		this.defaultValidityPeriod = securityProperties.getJwt().getValidityPeriod();
 		guestValidityPeriod = Duration.parse("P180D");
+		temporaryValidityPeriod = Duration.parse("PT30S");
 		algorithm = Algorithm.HMAC256(securityProperties.getJwt().getSecret());
 		verifier = JWT.require(algorithm)
 				.withAudience(serverId)
 				.build();
 	}
 
-	public String createSignedToken(final User user) {
+	public String createSignedToken(final User user, final boolean temporary) {
 		final String[] roles = user.getAuthorities().stream()
 				.map(ga -> ga.getAuthority())
 				.filter(ga -> ga.startsWith(ROLE_PREFIX))
 				.map(ga -> ga.substring(ROLE_PREFIX.length())).toArray(String[]::new);
-		final TemporalAmount expiresAt = user.getAuthProvider() == UserProfile.AuthProvider.ARSNOVA_GUEST
-				? guestValidityPeriod : defaultValidityPeriod;
+		final TemporalAmount expiresAt = temporary ? temporaryValidityPeriod
+				: (user.getAuthProvider() == UserProfile.AuthProvider.ARSNOVA_GUEST
+				? guestValidityPeriod : defaultValidityPeriod);
 		return JWT.create()
 				.withIssuer(serverId)
 				.withAudience(serverId)
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 b90d3a60d0b20c0e8b423ad8aa8c239a16fa5683..3a216a6e176f84675d42f611d40876adba241a23 100644
--- a/src/main/java/de/thm/arsnova/security/jwt/JwtTokenFilter.java
+++ b/src/main/java/de/thm/arsnova/security/jwt/JwtTokenFilter.java
@@ -19,12 +19,15 @@
 package de.thm.arsnova.security.jwt;
 
 import java.io.IOException;
+import java.util.Arrays;
+import java.util.Optional;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import javax.servlet.FilterChain;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -35,6 +38,8 @@ import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.stereotype.Component;
 import org.springframework.web.filter.GenericFilterBean;
 
+import de.thm.arsnova.security.LoginAuthenticationSucessHandler;
+
 @Component
 public class JwtTokenFilter extends GenericFilterBean {
 	private static final Pattern BEARER_TOKEN_PATTERN = Pattern.compile("Bearer (.*)", Pattern.CASE_INSENSITIVE);
@@ -51,28 +56,44 @@ public class JwtTokenFilter extends GenericFilterBean {
 			filterChain.doFilter(servletRequest, servletResponse);
 			return;
 		}
+
+		JwtToken token = null;
 		final String jwtHeader = httpServletRequest.getHeader(HttpHeaders.AUTHORIZATION);
 		if (jwtHeader != null) {
 			final Matcher tokenMatcher = BEARER_TOKEN_PATTERN.matcher(jwtHeader);
 			if (tokenMatcher.matches()) {
-				final JwtToken token = new JwtToken(tokenMatcher.group(1));
-				try {
-					final 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);
-				}
+				token = new JwtToken(tokenMatcher.group(1));
 			} else {
 				logger.debug("Unsupported authentication scheme.");
 			}
 		} else {
 			logger.debug("No authentication header present.");
+			/* Look for auth cookie if Authorization header is not present. */
+			if (httpServletRequest.getCookies() != null) {
+				final Optional<Cookie> cookie = Arrays.stream(httpServletRequest.getCookies())
+						.filter(c -> c.getName().equalsIgnoreCase(LoginAuthenticationSucessHandler.AUTH_COOKIE_NAME))
+						.findFirst();
+				if (cookie.isPresent()) {
+					logger.debug("Trying to use authentication from cookie.");
+					token = new JwtToken(cookie.get().getValue());
+				}
+			}
 		}
+
+		if (token != null) {
+			try {
+				final 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);
+			}
+		}
+
 		filterChain.doFilter(servletRequest, servletResponse);
 	}
 
diff --git a/src/main/java/de/thm/arsnova/service/UserService.java b/src/main/java/de/thm/arsnova/service/UserService.java
index bbfd163811c4f2dce21f2fe3f21cc035c0d97e58..d2b442f032cd1b877b3ebe0882d126d57be11909 100644
--- a/src/main/java/de/thm/arsnova/service/UserService.java
+++ b/src/main/java/de/thm/arsnova/service/UserService.java
@@ -39,7 +39,7 @@ public interface UserService extends EntityService<UserProfile> {
 
 	User getCurrentUser();
 
-	de.thm.arsnova.model.ClientAuthentication getCurrentClientAuthentication();
+	de.thm.arsnova.model.ClientAuthentication getCurrentClientAuthentication(boolean refresh);
 
 	boolean isAdmin(String username);
 
diff --git a/src/main/java/de/thm/arsnova/service/UserServiceImpl.java b/src/main/java/de/thm/arsnova/service/UserServiceImpl.java
index 21110d04c633b7d2b097036a4580503e7c694986..e5723926553a36dc85f9b94c29374f2fbf78274d 100644
--- a/src/main/java/de/thm/arsnova/service/UserServiceImpl.java
+++ b/src/main/java/de/thm/arsnova/service/UserServiceImpl.java
@@ -203,14 +203,14 @@ public class UserServiceImpl extends DefaultEntityServiceImpl<UserProfile> imple
 	}
 
 	@Override
-	public de.thm.arsnova.model.ClientAuthentication getCurrentClientAuthentication() {
+	public de.thm.arsnova.model.ClientAuthentication getCurrentClientAuthentication(final boolean refresh) {
 		final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
 		if (authentication == null || !(authentication.getPrincipal() instanceof User)) {
 			return null;
 		}
 		final User user = (User) authentication.getPrincipal();
-		final String jwt = authentication instanceof JwtToken
-				? (String) authentication.getCredentials() : jwtService.createSignedToken(user);
+		final String jwt = !refresh && authentication instanceof JwtToken
+				? (String) authentication.getCredentials() : jwtService.createSignedToken(user, false);
 
 		final ClientAuthentication clientAuthentication =
 				new ClientAuthentication(user.getId(), user.getUsername(),