diff --git a/alfa-service/pom.xml b/alfa-service/pom.xml
index 0f4827be47ecc8c9af69e268a612b133bf61ecfd..afa097c22d300291d6de9d645039bc4f1f465371 100644
--- a/alfa-service/pom.xml
+++ b/alfa-service/pom.xml
@@ -57,6 +57,7 @@
 			<groupId>org.springframework.boot</groupId>
 			<artifactId>spring-boot-starter-web</artifactId>
 			<version>2.7.16</version>
+			
 		</dependency>
 		<dependency>
 			<groupId>org.springframework.boot</groupId>
@@ -84,37 +85,20 @@
 	      <groupId>org.springframework.boot</groupId>
 	      <artifactId>spring-boot-starter-security</artifactId>
 	      <version>2.7.16</version>
-	      <exclusions>
-	        <exclusion>
-	            <groupId>org.springframework.security</groupId>
-	            <artifactId>spring-security-config</artifactId>
-	        </exclusion>
-	        <exclusion>
-	            <groupId>org.springframework.security</groupId>
-	            <artifactId>spring-security-web</artifactId>
-	        </exclusion>
-	      </exclusions>
 	    </dependency>
 	    <dependency>
-	      <groupId>org.springframework.security</groupId>
-	      <artifactId>spring-security-config</artifactId>
-	      <version>5.8.7</version>
-	    </dependency>
-	    <dependency>
-	      <groupId>org.springframework.security</groupId>
-	      <artifactId>spring-security-web</artifactId>
-	      <version>5.8.7</version>
-	    </dependency>
-
+		    <groupId>org.springframework.boot</groupId>
+		    <artifactId>spring-boot-starter-oauth2-client</artifactId>
+		    <version>2.7.16</version>
+		</dependency>
 		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-spring-boot-starter</artifactId>
-			<version>20.0.3</version>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
+			<version>2.7.16</version>
 		</dependency>
 		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-admin-client</artifactId>
-			<version>20.0.3</version>
+		    <groupId>com.jayway.jsonpath</groupId>
+		    <artifactId>json-path</artifactId>
 		</dependency>
 
 		<!-- jwt -->
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/EnvironmentController.java b/alfa-service/src/main/java/de/ozgcloud/alfa/EnvironmentController.java
index 0103a54760c7db79f34c0ab0980a0b569383108b..6312425734f9c38f93c530272881183560d9f5ed 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/EnvironmentController.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/EnvironmentController.java
@@ -25,7 +25,6 @@ package de.ozgcloud.alfa;
 
 import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*;
 
-import org.keycloak.adapters.springboot.KeycloakSpringBootProperties;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -37,7 +36,7 @@ import org.springframework.web.bind.annotation.RestController;
 public class EnvironmentController {
 
 	@Autowired
-	private KeycloakSpringBootProperties kcProperties;
+	private KeycloakProperties keycloakProperties;
 
 	@Value("${goofy.production}")
 	private boolean production = true;
@@ -46,14 +45,10 @@ public class EnvironmentController {
 	public FrontendEnvironment getFrontendEnvironment() {
 		return FrontendEnvironment.builder()//
 				.production(production)//
-				.remoteHost(apiRoot())//
-				.authServer(kcProperties.getAuthServerUrl())//
-				.clientId(kcProperties.getResource())//
-				.realm(kcProperties.getRealm())
+				.remoteHost(linkTo(RootController.class).toUri().toString())//
+				.authServer(keycloakProperties.getAuthServerUrl())//
+				.clientId(keycloakProperties.getResource())//
+				.realm(keycloakProperties.getRealm())
 				.build();
 	}
-
-	private String apiRoot() {
-		return linkTo(RootController.class).toUri().toString();
-	}
 }
\ No newline at end of file
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/JwtAuthConverter.java b/alfa-service/src/main/java/de/ozgcloud/alfa/JwtAuthConverter.java
new file mode 100644
index 0000000000000000000000000000000000000000..a2579c5e464af4f38f095b2eb6f139398362bbe2
--- /dev/null
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/JwtAuthConverter.java
@@ -0,0 +1,83 @@
+package de.ozgcloud.alfa;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.commons.collections.MapUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.lang.NonNull;
+import org.springframework.security.authentication.AbstractAuthenticationToken;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.oauth2.jwt.Jwt;
+import org.springframework.security.oauth2.jwt.JwtClaimNames;
+import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
+import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
+import org.springframework.stereotype.Component;
+
+@Component
+public class JwtAuthConverter implements Converter<Jwt, AbstractAuthenticationToken> {
+
+	private final JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
+
+	@Value("${jwt.auth.converter.principle-attribute}")
+	private String principleAttribute;
+	@Value("${jwt.auth.converter.resource-id}")
+	private String resourceId;
+
+	private static final String SIMPLE_GRANT_AUTHORITY_PREFIX = "ROLE_";
+
+	@Override
+	public AbstractAuthenticationToken convert(@NonNull Jwt jwt) {
+		return new JwtAuthenticationToken(jwt, getAuthorities(jwt), getPrincipleClaimName(jwt));
+	}
+
+	private String getPrincipleClaimName(Jwt jwt) {
+		return MapUtils.getString(jwt.getClaims(), getClaimName());
+	}
+
+	private String getClaimName() {
+		return Optional.ofNullable(principleAttribute).orElse(JwtClaimNames.SUB);
+	}
+
+	private Set<GrantedAuthority> getAuthorities(Jwt jwt) {
+		return Stream.concat(jwtGrantedAuthoritiesConverter.convert(jwt).stream(), extractResourceRoles(jwt).stream()).collect(Collectors.toSet());
+	}
+
+	private Collection<? extends GrantedAuthority> extractResourceRoles(Jwt jwt) {
+		if (Objects.isNull(getResourceAccess(jwt))) {
+			return Collections.emptySet();
+		}
+
+		var resourceAccess = getResourceAccess(jwt);
+		if (Objects.isNull(resourceAccess.get(resourceId))) {
+			return Collections.emptySet();
+		}
+		return extractRoles(getClaimMapFromMap(resourceAccess, resourceId));
+	}
+
+	private Map<String, Object> getResourceAccess(Jwt jwt) {
+		return jwt.getClaimAsMap("resource_access");
+	}
+
+	@SuppressWarnings("unchecked")
+	private Map<String, Object> getClaimMapFromMap(Map<String, Object> claimMap, String claimName) {
+		return MapUtils.getMap(claimMap, claimName);
+	}
+
+	private Set<SimpleGrantedAuthority> extractRoles(Map<String, Object> resource) {
+		return getRoles(resource).stream().map(role -> new SimpleGrantedAuthority(SIMPLE_GRANT_AUTHORITY_PREFIX + role)).collect(Collectors.toSet());
+	}
+
+	@SuppressWarnings("unchecked")
+	private Collection<String> getRoles(Map<String, Object> resource) {
+		return (Collection<String>) resource.get("roles");
+	}
+}
\ No newline at end of file
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/KeycloakProperties.java b/alfa-service/src/main/java/de/ozgcloud/alfa/KeycloakProperties.java
new file mode 100644
index 0000000000000000000000000000000000000000..c29d67d881715958dfdfe003c3981292dc8f55e1
--- /dev/null
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/KeycloakProperties.java
@@ -0,0 +1,31 @@
+package de.ozgcloud.alfa;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+@Configuration
+@ConfigurationProperties(prefix = KeycloakProperties.PREFIX)
+public class KeycloakProperties {
+
+	static final String PREFIX = "ozgcloud.keycloak";
+
+	/**
+	 * Keycloak auth server url
+	 */
+	private String authServerUrl;
+
+	/**
+	 * Keycloak realm
+	 */
+	private String realm;
+
+	/**
+	 * Keycloak client
+	 */
+	private String resource;
+}
\ No newline at end of file
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/SecurityConfiguration.java b/alfa-service/src/main/java/de/ozgcloud/alfa/SecurityConfiguration.java
index b4b58515539b57b624f699cded4194c2e1ef4263..c8de75605a3a632175628325b50f122df47879ee 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/SecurityConfiguration.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/SecurityConfiguration.java
@@ -23,16 +23,21 @@
  */
 package de.ozgcloud.alfa;
 
-import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
-import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
-import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
+import java.util.Objects;
+
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
 import org.springframework.http.HttpMethod;
+import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
 import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.config.http.SessionCreationPolicy;
-import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
+import org.springframework.security.web.SecurityFilterChain;
 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
 import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
 import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
@@ -42,47 +47,65 @@ import org.springframework.security.web.header.writers.frameoptions.XFrameOption
 
 import de.ozgcloud.alfa.common.downloadtoken.DownloadTokenAuthenticationFilter;
 
+@Configuration
+@EnableWebSecurity
 @EnableMethodSecurity(securedEnabled = true, prePostEnabled = true)
-@KeycloakConfiguration
-public class SecurityConfiguration extends KeycloakWebSecurityConfigurerAdapter {
+public class SecurityConfiguration {
 
 	@Autowired
 	private DownloadTokenAuthenticationFilter downloadTokenFilter;
 
-	@Override
-	protected void configure(HttpSecurity http) throws Exception {
-		super.configure(http);
+	@Autowired
+	private JwtAuthConverter jwtAuthConverter;
+
+	@Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}")
+	private String jwkSetUri;
+
+	@Order(2)
+	@Bean
+	SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 		http.csrf(csrf -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()));
 
-		http.sessionManagement(management -> management.sessionCreationPolicy(SessionCreationPolicy.STATELESS)).authorizeHttpRequests()//
-				.requestMatchers(HttpMethod.GET, "/api/environment").permitAll()//
-				.requestMatchers(HttpMethod.GET, "/assets/**").permitAll()//
-				.requestMatchers(HttpMethod.GET, "/vorgang/**").permitAll()//
-				.requestMatchers(HttpMethod.GET, "/meine/**").permitAll()//
-				.requestMatchers(HttpMethod.GET, "/alle/**").permitAll()//
-				.requestMatchers(HttpMethod.GET, "/unassigned/**").permitAll()//
-				.requestMatchers("/api").authenticated()//
-				.requestMatchers("/api/**").authenticated()//
-				.requestMatchers("/actuator").permitAll()//
-				.requestMatchers("/actuator/**").permitAll()//
-				.requestMatchers("/").permitAll()//
-				.requestMatchers("/*").permitAll()//
-				.anyRequest().denyAll();
+		http.sessionManagement(management -> management.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
+
+		http.authorizeHttpRequests()//
+				.antMatchers(HttpMethod.GET, "/api/environment").permitAll()//
+				.antMatchers(HttpMethod.GET, "/assets/**").permitAll()//
+				.antMatchers(HttpMethod.GET, "/vorgang/**").permitAll()//
+				.antMatchers(HttpMethod.GET, "/meine/**").permitAll()//
+				.antMatchers(HttpMethod.GET, "/alle/**").permitAll()//
+				.antMatchers(HttpMethod.GET, "/unassigned/**").permitAll()//
+				.antMatchers(HttpMethod.GET, "/oauth2/**").permitAll()//
+				.antMatchers(HttpMethod.GET, "/login/**").permitAll()//
+				.antMatchers("/api").authenticated()//
+				.antMatchers("/api/**").authenticated()//
+				.antMatchers("/actuator").permitAll()//
+				.antMatchers("/actuator/**").permitAll()//
+				.antMatchers("/").permitAll()//
+				.antMatchers("/*").permitAll()//
+				.anyRequest().denyAll().and();
+
+		http.oauth2ResourceServer(server -> {
+			server.jwt().jwtAuthenticationConverter(jwtAuthConverter);
+
+			if (Objects.nonNull(jwkSetUri)) {
+				server.jwt().jwkSetUri(jwkSetUri);
+			}
+		});
 
 		http.headers(headers -> headers.addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN)));
 		http.addFilterBefore(downloadTokenFilter, UsernamePasswordAuthenticationFilter.class);
-	}
 
-	@Autowired
-	public void configureGlobal(AuthenticationManagerBuilder auth) {
-		KeycloakAuthenticationProvider keyCloakAuthProvider = keycloakAuthenticationProvider();
-		keyCloakAuthProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
-		auth.authenticationProvider(keyCloakAuthProvider);
+		return http.build();
 	}
 
-	@Override
+	@Bean
 	protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
 		return new NullAuthenticatedSessionStrategy();
 	}
 
+	@Bean
+	AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
+		return http.getSharedObject(AuthenticationManagerBuilder.class).build();
+	}
 }
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/WebConfig.java b/alfa-service/src/main/java/de/ozgcloud/alfa/WebConfig.java
index 2074b2e67f74c77f5b00ff6c9a8f6b6f8e0bd7ed..a0669a9539fecfa3fb4bb46020f5c85f9f133dde 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/WebConfig.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/WebConfig.java
@@ -26,9 +26,6 @@ package de.ozgcloud.alfa;
 import java.io.IOException;
 import java.util.concurrent.TimeUnit;
 
-import org.keycloak.adapters.KeycloakConfigResolver;
-import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
-import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.core.io.Resource;
 import org.springframework.http.CacheControl;
@@ -36,6 +33,8 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 import org.springframework.web.servlet.resource.PathResourceResolver;
 
+import lombok.NoArgsConstructor;
+
 @Configuration
 public class WebConfig implements WebMvcConfigurer {
 
@@ -43,7 +42,6 @@ public class WebConfig implements WebMvcConfigurer {
 
 	@Override
 	public void addResourceHandlers(ResourceHandlerRegistry registry) {
-
 		registry.addResourceHandler("/*.js", "/*.css", "/*.ttf", "/*.woff", "/*.woff2", "/*.eot",
 				"/**/*.svg", "/*.svf", "/*.otf", "/*.ico", "/**/*.png")
 				.addResourceLocations(RESOURCE_LOCATION)
@@ -56,18 +54,20 @@ public class WebConfig implements WebMvcConfigurer {
 				.setCacheControl(CacheControl.noStore())
 				.setUseLastModified(false)
 				.resourceChain(true)
-				.addResolver(new PathResourceResolver() {
-					@Override
-					protected Resource getResource(String resourcePath, Resource location) throws IOException {
-						Resource requestedResource = location.createRelative(resourcePath);
-						return requestedResource.exists() && requestedResource.isReadable() ? requestedResource
-								: super.getResource("index.html", location);
-					}
-				});
+				.addResolver(new OzgCloudPathResourceResolver());
 	}
 
-	@Bean
-	public KeycloakConfigResolver keyCloakConfigResolver() {
-		return new KeycloakSpringBootConfigResolver();
+	@NoArgsConstructor
+	static class OzgCloudPathResourceResolver extends PathResourceResolver {
+
+		@Override
+		protected Resource getResource(String resourcePath, Resource location) throws IOException {
+			var requestedResource = location.createRelative(resourcePath);
+
+			if (requestedResource.exists() && requestedResource.isReadable()) {
+				return requestedResource;
+			}
+			return super.getResource("index.html", location);
+		}
 	}
-}
+}
\ No newline at end of file
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/common/binaryfile/DownloadAuthenticationHandler.java b/alfa-service/src/main/java/de/ozgcloud/alfa/common/binaryfile/DownloadAuthenticationHandler.java
index ad7639749de0b76fa04e88485ae985ba110f6718..ee46850a3953a45a759529e3ba3513766bfc62a8 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/common/binaryfile/DownloadAuthenticationHandler.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/common/binaryfile/DownloadAuthenticationHandler.java
@@ -39,7 +39,7 @@ public class DownloadAuthenticationHandler {
 
 	boolean check(FileId fileId, Authentication auth) {
 		if (auth instanceof UsernamePasswordAuthenticationToken userPasswordToken) {
-			GoofyUserWithFileId user = (GoofyUserWithFileId) userPasswordToken.getPrincipal();
+			var user = (GoofyUserWithFileId) userPasswordToken.getPrincipal();
 			return Objects.nonNull(fileId) && fileId.equals(user.getFileId()) && auth.isAuthenticated();
 		}
 
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/common/downloadtoken/DownloadTokenAuthenticationFilter.java b/alfa-service/src/main/java/de/ozgcloud/alfa/common/downloadtoken/DownloadTokenAuthenticationFilter.java
index 297aa8e7a22308f54ca8a3781c92e3742eeb6adf..b8f3f00358092931c6b8a96bb8b1680879539ad9 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/common/downloadtoken/DownloadTokenAuthenticationFilter.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/common/downloadtoken/DownloadTokenAuthenticationFilter.java
@@ -31,7 +31,6 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.commons.lang3.StringUtils;
-import org.apache.http.HttpStatus;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Component;
@@ -52,7 +51,7 @@ public class DownloadTokenAuthenticationFilter extends OncePerRequestFilter {
 		try {
 			downloadTokenService.handleToken(request, getDownloadToken(request));
 		} catch (TechnicalException e) {
-			response.setStatus(HttpStatus.SC_UNAUTHORIZED);
+			response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
 			return;
 		}
 
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/common/user/CurrentUserService.java b/alfa-service/src/main/java/de/ozgcloud/alfa/common/user/CurrentUserService.java
index 94b9c3900b2f7decee285d35e220fd28463a5fe5..8425d6052b7dde99dc4ba6839d4d3dff2ed5989b 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/common/user/CurrentUserService.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/common/user/CurrentUserService.java
@@ -27,15 +27,13 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 
-import org.keycloak.KeycloakPrincipal;
-import org.keycloak.representations.AccessToken;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
 import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.stereotype.Service;
 
 import de.itvsh.kop.common.errorhandling.TechnicalException;
@@ -50,6 +48,10 @@ public class CurrentUserService {
 
 	static final String USER_ATTRIBUTE_ORGANISATIONSEINHEIT_ID = "organisationseinheitId";
 
+	static final String KEYCLOAK_USER_PREFERRED_USERNAME = "preferred_username";
+	static final String KEYCLOAK_USER_GIVEN_NAME = "given_name";
+	static final String KEYCLOAK_USER_FAMILY_NAME = "family_name";
+
 	@Autowired
 	private UserService userService;
 	@Autowired
@@ -65,30 +67,28 @@ public class CurrentUserService {
 		return CurrentUserHelper.containsRole(reachableRoles, role);
 	}
 
-	public Collection<GrantedAuthority> getAuthorities() {
-		return Collections.unmodifiableCollection(new HashSet<GrantedAuthority>(CurrentUserHelper.getAuthentication().getAuthorities()));
-	}
-
 	public UserProfile getUser() {
-		var dlUser = getDownloadUser();
-		if (dlUser.isPresent()) {
-			return dlUser.get();
-		}
-
-		Optional<AccessToken> token = getCurrentSecurityToken();
+		return getDownloadUser().orElseGet(this::buildUserProfile);
+	}
 
+	private UserProfile buildUserProfile() {
 		var userBuilder = UserProfile.builder()
 				.id(getUserId())
 				.authorities(getAuthorities());
 
-		token.ifPresent(t -> userBuilder.userName(t.getPreferredUsername())
-				.firstName(t.getGivenName())
-				.lastName(t.getFamilyName())
-				.organisationseinheitIds(getOrganisationseinheitId(t.getOtherClaims())));
+		getCurrentSecurityToken().ifPresent(token -> userBuilder
+				.userName(token.getClaimAsString(KEYCLOAK_USER_PREFERRED_USERNAME))
+				.firstName(token.getClaimAsString(KEYCLOAK_USER_GIVEN_NAME))
+				.lastName(token.getClaimAsString(KEYCLOAK_USER_FAMILY_NAME))
+				.organisationseinheitIds(getOrganisationsEinheitIds(token)));
 
 		return userBuilder.build();
 	}
 
+	public Collection<GrantedAuthority> getAuthorities() {
+		return Collections.unmodifiableCollection(new HashSet<GrantedAuthority>(CurrentUserHelper.getAuthentication().getAuthorities()));
+	}
+
 	public UserId getUserId() {
 		return findUserId()
 				.orElseThrow(() -> new TechnicalException("Cannot find internal UserId. Check sync with UserManager or Token Mapper in keycloak."));
@@ -96,13 +96,14 @@ public class CurrentUserService {
 
 	public Optional<UserId> findUserId() {
 		return Optional.ofNullable(
-						getSingleClaimValue(ATTRIBUTE_NAME_USER_ID).map(UserId::from)
-								.orElseGet(() -> userService.getInternalId(CurrentUserHelper.getCurrentUserId()).orElse(null)))
+				getSingleClaimValue(ATTRIBUTE_NAME_USER_ID).map(UserId::from)
+						.orElseGet(() -> userService.getInternalId(CurrentUserHelper.getCurrentUserId()).orElse(null)))
 				.filter(Objects::nonNull);
 	}
 
-	List<String> getOrganisationseinheitId(Map<String, Object> claims) {
-		return Optional.ofNullable(claims.get(USER_ATTRIBUTE_ORGANISATIONSEINHEIT_ID))
+	List<String> getOrganisationsEinheitIds(Jwt jwt) {
+		return Optional.ofNullable(jwt)
+				.map(token -> token.getClaim(USER_ATTRIBUTE_ORGANISATIONSEINHEIT_ID))
 				.map(col -> (Collection<?>) col).orElse(Collections.emptyList()) // NOSONAR - Collection.class::cast has type-safty issue
 				.stream().map(Object::toString).toList();
 	}
@@ -114,19 +115,19 @@ public class CurrentUserService {
 				.map(GoofyUserWithFileId::getUser);
 	}
 
-	Optional<AccessToken> getCurrentSecurityToken() {
-		Object principal = CurrentUserHelper.getAuthentication().getPrincipal();
+	Optional<String> getSingleClaimValue(String attributeName) {
+		return getCurrentSecurityToken()
+				.map(token -> token.getClaim(attributeName))
+				.map(String.class::cast);
+	}
+
+	Optional<Jwt> getCurrentSecurityToken() {
+		var principal = CurrentUserHelper.getAuthentication().getPrincipal();
 
-		if (principal instanceof KeycloakPrincipal<?> kcPrincipal) {
-			return Optional.of(kcPrincipal.getKeycloakSecurityContext().getToken());
+		if (principal instanceof Jwt kcPrincipal) {
+			return Optional.of(kcPrincipal);
 		}
 
 		return Optional.empty();
 	}
-
-	Optional<String> getSingleClaimValue(String attributeName) {
-		return getCurrentSecurityToken()
-				.map(token -> token.getOtherClaims().get(attributeName))
-				.map(String.class::cast);
-	}
 }
\ No newline at end of file
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/historie/HistorieCommandHandler.java b/alfa-service/src/main/java/de/ozgcloud/alfa/historie/HistorieCommandHandler.java
index dc735be8bf8f3da848fd631fa28612ff23a444fb..fe54b77f7a60a44ac005f05864c7819587701b36 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/historie/HistorieCommandHandler.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/historie/HistorieCommandHandler.java
@@ -27,8 +27,8 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.function.Predicate;
 
-import org.apache.commons.codec.binary.StringUtils;
 import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/EnvironmentControllerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/EnvironmentControllerTest.java
index 145d1e512f80ce0538074b74fde6272c7269e12a..bb29e2e75e420ce3d6745bd83998973566af9d70 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/EnvironmentControllerTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/EnvironmentControllerTest.java
@@ -29,12 +29,14 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import org.keycloak.adapters.springboot.KeycloakSpringBootProperties;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 
+import lombok.SneakyThrows;
+
 class EnvironmentControllerTest {
 
 	private final String PATH = "/api/environment";
@@ -42,7 +44,7 @@ class EnvironmentControllerTest {
 	@InjectMocks
 	private EnvironmentController controller;
 	@Mock
-	private KeycloakSpringBootProperties kcProperties;
+	private KeycloakProperties keycloakProperties;
 
 	private MockMvc mockMvc;
 
@@ -52,22 +54,30 @@ class EnvironmentControllerTest {
 	}
 
 	@Test
-	void loadEnvironment() throws Exception {
-		mockMvc.perform(get(PATH)).andExpect(status().isOk());
+	void shouldReturnOk() throws Exception {
+		var response = doRequest();
+
+		response.andExpect(status().isOk());
 	}
 
 	@Test
 	void shouldHaveProductionTrueAsDefault() throws Exception {
-		mockMvc.perform(get(PATH)).andExpect(status().is2xxSuccessful())//
-				.andExpect(jsonPath("$.production").value(true));
+		var response = doRequest();
+
+		response.andExpect(jsonPath("$.production").value(true));
 	}
 
 	@Test
 	void shouldHaveClientId() throws Exception {
 		var client = "goofy";
+		when(keycloakProperties.getResource()).thenReturn(client);
+		var response = doRequest();
 
-		when(kcProperties.getResource()).thenReturn(client);
+		response.andExpect(jsonPath("$.clientId").value(client));
+	}
 
-		mockMvc.perform(get(PATH)).andExpect(jsonPath("$.clientId").value(client));
+	@SneakyThrows
+	private ResultActions doRequest() {
+		return mockMvc.perform(get(PATH));
 	}
 }
\ No newline at end of file
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/common/binaryfile/DownloadAuthenticationHandlerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/common/binaryfile/DownloadAuthenticationHandlerTest.java
index 155ac009c8fc0b9604f993dd188a71fde2ed1355..d9cc748ca8211b95706ca0ad8af73fea013a1693 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/common/binaryfile/DownloadAuthenticationHandlerTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/common/binaryfile/DownloadAuthenticationHandlerTest.java
@@ -29,9 +29,10 @@ import static org.mockito.Mockito.*;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
-import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
+import org.mockito.Mock;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.core.Authentication;
+import org.springframework.security.oauth2.jwt.Jwt;
 
 class DownloadAuthenticationHandlerTest {
 
@@ -40,18 +41,22 @@ class DownloadAuthenticationHandlerTest {
 	@Nested
 	class TestAuthorizationKeycloak {
 
+		@Mock
+		private Jwt jwt;
+
 		private Authentication authentication = mock(Authentication.class);
 
 		@BeforeEach
 		void init() {
 			when(authentication.isAuthenticated()).thenReturn(Boolean.TRUE);
-			KeycloakAuthenticationToken keycloakToken = mock(KeycloakAuthenticationToken.class);
-			when(authentication.getPrincipal()).thenReturn(keycloakToken);
+			when(authentication.getPrincipal()).thenReturn(jwt);
 		}
 
 		@Test
 		void shouldAuthenticate() {
-			assertThat(downloadAuthorizationHandler.check(FileId.createNew(), authentication)).isTrue();
+			var check = downloadAuthorizationHandler.check(FileId.createNew(), authentication);
+
+			assertThat(check).isTrue();
 		}
 	}
 
@@ -69,23 +74,32 @@ class DownloadAuthenticationHandlerTest {
 
 		@Test
 		void shouldAuthenticate() {
-			assertThat(downloadAuthorizationHandler.check(fileId, authentication)).isTrue();
+			var check = downloadAuthorizationHandler.check(fileId, authentication);
+
+			assertThat(check).isTrue();
 		}
 
 		@Test
 		void shouldNotAuthenticateWrongFileId() {
-			assertThat(downloadAuthorizationHandler.check(FileId.createNew(), authentication)).isFalse();
+			var check = downloadAuthorizationHandler.check(FileId.createNew(), authentication);
+
+			assertThat(check).isFalse();
 		}
 
 		@Test
 		void shouldNotAuthenticateNoFileId() {
-			assertThat(downloadAuthorizationHandler.check(null, authentication)).isFalse();
+			var check = downloadAuthorizationHandler.check(null, authentication);
+
+			assertThat(check).isFalse();
 		}
 
 		@Test
 		void shouldNotAuthenticate() {
 			when(authentication.isAuthenticated()).thenReturn(Boolean.FALSE);
-			assertThat(downloadAuthorizationHandler.check(fileId, authentication)).isFalse();
+
+			var check = downloadAuthorizationHandler.check(fileId, authentication);
+
+			assertThat(check).isFalse();
 		}
 	}
 }
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/common/user/CurrentUserServiceTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/common/user/CurrentUserServiceTest.java
index f22c42b6cb253d3b2a1956e9f741d1aaa7c6a076..d1f47b8ac1203f0f06f9841ea7562783987d9f8d 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/common/user/CurrentUserServiceTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/common/user/CurrentUserServiceTest.java
@@ -34,8 +34,9 @@ import java.util.Optional;
 
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
-import org.keycloak.representations.AccessToken;
+import org.mockito.Mock;
 import org.mockito.Spy;
+import org.springframework.security.oauth2.jwt.Jwt;
 
 class CurrentUserServiceTest {
 
@@ -45,34 +46,39 @@ class CurrentUserServiceTest {
 	@Nested
 	class TestGetOrganisationseinheit {
 
+		@Mock
+		private Jwt jwt;
+
 		@Test
 		void shouldReturnOrganisationseinheitIdsFromMap() {
-			Map<String, Object> claims = Map.of(CurrentUserService.USER_ATTRIBUTE_ORGANISATIONSEINHEIT_ID, List.of("1", "2"));
+			when(jwt.getClaim(CurrentUserService.USER_ATTRIBUTE_ORGANISATIONSEINHEIT_ID)).thenReturn(List.of("1", "2"));
 
-			var result = service.getOrganisationseinheitId(claims);
+			var result = service.getOrganisationsEinheitIds(jwt);
 
 			assertThat(result).contains("1").contains("2");
 		}
 
 		@Test
 		void shouldReturnOrgaIdAsString() {
-			var result = service.getOrganisationseinheitId(Map.of(CurrentUserService.USER_ATTRIBUTE_ORGANISATIONSEINHEIT_ID, List.of("1", 2)));
+			when(jwt.getClaim(CurrentUserService.USER_ATTRIBUTE_ORGANISATIONSEINHEIT_ID)).thenReturn(List.of("1", 2));
+
+			var result = service.getOrganisationsEinheitIds(jwt);
 
 			assertThat(result).contains("1").contains("2");
 		}
 
 		@Test
 		void shouldReturnEmptyList() {
-			Map<String, Object> claims = Map.of(CurrentUserService.USER_ATTRIBUTE_ORGANISATIONSEINHEIT_ID, Collections.emptyList());
+			when(jwt.getClaim(CurrentUserService.USER_ATTRIBUTE_ORGANISATIONSEINHEIT_ID)).thenReturn(Collections.emptyList());
 
-			var result = service.getOrganisationseinheitId(claims);
+			var result = service.getOrganisationsEinheitIds(jwt);
 
 			assertThat(result).isEmpty();
 		}
 
 		@Test
 		void shouldReturnEmptyListIfNotExists() {
-			var result = service.getOrganisationseinheitId(Collections.emptyMap());
+			var result = service.getOrganisationsEinheitIds(null);
 
 			assertThat(result).isEmpty();
 		}
@@ -98,8 +104,8 @@ class CurrentUserServiceTest {
 
 		@Test
 		void shouldReturnUserAttribute() {
-			var token = new AccessToken();
-			token.setOtherClaims(ATTRIBUTE_NAME, ATTRIBUTE_VALUE);
+			var claims = Map.<String, Object>of(ATTRIBUTE_NAME, ATTRIBUTE_VALUE);
+			var token = new Jwt("dummyTokenValue", null, null, Collections.singletonMap("dummyHeader", "DummyHeaderValue"), claims);
 			doReturn(Optional.of(token)).when(service).getCurrentSecurityToken();
 
 			var attribute = service.getSingleClaimValue(ATTRIBUTE_NAME);
@@ -109,7 +115,8 @@ class CurrentUserServiceTest {
 
 		@Test
 		void shouldReturnEmpty() {
-			var token = new AccessToken();
+			var token = new Jwt("dummyTokenValue", null, null, Collections.singletonMap("dummyHeader", "DummyHeaderValue"),
+					Collections.singletonMap("dummyClaim", "DummyClaimValue"));
 			doReturn(Optional.of(token)).when(service).getCurrentSecurityToken();
 
 			var attribute = service.getSingleClaimValue(ATTRIBUTE_NAME);
diff --git a/goofy-server/pom.xml b/goofy-server/pom.xml
index b05c91b03da1dd016cc49bdc0ddbb33ef2844cce..58579ddc04e285c4a014834c83ed9160472438ef 100644
--- a/goofy-server/pom.xml
+++ b/goofy-server/pom.xml
@@ -40,50 +40,7 @@
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-security</artifactId>
       <version>2.7.16</version>
-      <exclusions>
-        <exclusion>
-            <groupId>org.springframework.security</groupId>
-            <artifactId>spring-security-config</artifactId>
-        </exclusion>
-        <exclusion>
-            <groupId>org.springframework.security</groupId>
-            <artifactId>spring-security-web</artifactId>
-        </exclusion>
-      </exclusions>
     </dependency>
-    <dependency>
-      <groupId>org.springframework.security</groupId>
-      <artifactId>spring-security-config</artifactId>
-      <exclusions>
-        <exclusion>
-            <groupId>org.springframework.security</groupId>
-            <artifactId>spring-security-core</artifactId>
-        </exclusion>
-      </exclusions>
-      <version>5.8.7</version>
-    </dependency>
-    <dependency>
-      <groupId>org.springframework.security</groupId>
-      <artifactId>spring-security-core</artifactId>
-      <exclusions>
-        <exclusion>
-            <groupId>org.springframework.security</groupId>
-            <artifactId>spring-security-crypto</artifactId>
-        </exclusion>
-      </exclusions>
-      <version>5.8.7</version>
-    </dependency>
-    <dependency>
-      <groupId>org.springframework.security</groupId>
-      <artifactId>spring-security-crypto</artifactId>
-      <version>5.8.7</version>
-    </dependency>
-    <dependency>
-      <groupId>org.springframework.security</groupId>
-      <artifactId>spring-security-web</artifactId>
-      <version>5.8.7</version>
-    </dependency>
-
   </dependencies>
 
   <build>
diff --git a/goofy-server/src/main/resources/application-dev.yml b/goofy-server/src/main/resources/application-dev.yml
index be7dc4d1adb0c218ef1d2c908b35b8fbd2142632..f40a7a1ac1d60f9273e9d670b0696a8b9fd5dc50 100644
--- a/goofy-server/src/main/resources/application-dev.yml
+++ b/goofy-server/src/main/resources/application-dev.yml
@@ -1,11 +1,6 @@
 goofy:
   production: false
 
-keycloak:
-  auth-server-url: https://sso.dev.by.ozg-cloud.de
-  realm: by-kiel-dev
-  resource: alfa
-
 server:
   error:
     include-stacktrace: always
@@ -14,4 +9,7 @@ ozgcloud:
   feature:
      vorgang-export: true
   stage:
-    production: false
\ No newline at end of file
+    production: false
+  keycloak:
+    auth-server-url: https://sso.dev.by.ozg-cloud.de
+    realm: by-kiel-dev
\ No newline at end of file
diff --git a/goofy-server/src/main/resources/application-e2e.yml b/goofy-server/src/main/resources/application-e2e.yml
index 6b4c84428d26ff921ab8c233062ebd1b8837dce4..285c643223b91da42101e8ff5ab2327b8bd06720 100644
--- a/goofy-server/src/main/resources/application-e2e.yml
+++ b/goofy-server/src/main/resources/application-e2e.yml
@@ -15,4 +15,4 @@ ozgcloud:
      createBescheid: true
   user-assistance:
      documentation:
-        url: /assets/benutzerleitfaden/Benutzerleitfaden_2.5.pdf
\ No newline at end of file
+        url: /assets/benutzerleitfaden/benutzerleitfaden.pdf
\ No newline at end of file
diff --git a/goofy-server/src/main/resources/application-local.yml b/goofy-server/src/main/resources/application-local.yml
index 4f0e0f12aab2ad4c7fd4c89d4263a8a03ccaa8e2..11b20f5d0b48ca03e09809d0c83c4af9db1d08ad 100644
--- a/goofy-server/src/main/resources/application-local.yml
+++ b/goofy-server/src/main/resources/application-local.yml
@@ -7,11 +7,6 @@ logging:
 goofy:
   production: false
 
-keycloak:
-  auth-server-url: http://localhost:8088
-  realm: sh-kiel-dev #TODO adjust
-  resource: sh-kiel-dev-goofy #TODO adjust
-
 server:
   error:
     include-stacktrace: always
@@ -30,4 +25,9 @@ grpc:
       
 ozgcloud:
   feature:
-    vorgang-export: true
\ No newline at end of file
+    vorgang-export: true
+  user-assistance:
+     documentation:
+        url: /assets/benutzerleitfaden/benutzerleitfaden.pdf
+  keycloak:
+    auth-server-url: http://localhost:8088
\ No newline at end of file
diff --git a/goofy-server/src/main/resources/application-remotekc.yml b/goofy-server/src/main/resources/application-remotekc.yml
index f27d8bf81a26dd58d2b10d44b8b01eb89add3c8f..20d8a33c22dfe39d946824c8a39230d95478f223 100644
--- a/goofy-server/src/main/resources/application-remotekc.yml
+++ b/goofy-server/src/main/resources/application-remotekc.yml
@@ -1,6 +1,4 @@
-keycloak: 
-  realm: by-kiel-dev
-  resource: alfa
-  public-client: true
-  use-resource-role-mappings: true
-  auth-server-url: https://sso.dev.by.ozg-cloud.de
+ozgcloud:
+   keycloak:
+      auth-server-url: https://sso.dev.by.ozg-cloud.de
+      realm: by-kiel-dev
\ No newline at end of file
diff --git a/goofy-server/src/main/resources/application.yml b/goofy-server/src/main/resources/application.yml
index a84e4da06ffa475b8240b43d5301fe68a85cbbda..a3d23ad996201e37050106a4eebcbcb26bc1edaa 100644
--- a/goofy-server/src/main/resources/application.yml
+++ b/goofy-server/src/main/resources/application.yml
@@ -4,7 +4,19 @@ logging:
     '[de.itvsh]': INFO
     '[de.ozgcloud]': INFO,
     '[org.springframework.security]': WARN
-    '[org.keycloak.adapters]': WARN
+
+
+ozgcloud:
+   keycloak:
+      auth-server-url: https://sso.dev.by.ozg-cloud.de
+      realm: by-kiel-dev
+      resource: ${jwt.auth.converter.resource-id}
+      
+jwt:
+  auth:
+    converter:
+      resource-id: alfa
+      principle-attribute: preferred_username  
 
 spring:
   mvc:
@@ -19,7 +31,13 @@ spring:
     multipart:
       max-file-size: 2GB
       max-request-size: 2GB
-
+  security:
+    oauth2:
+      resourceserver:
+        jwt:
+          issuer-uri: ${ozgcloud.keycloak.auth-server-url}/realms/${ozgcloud.keycloak.realm}
+          jwk-set-uri: ${spring.security.oauth2.resourceserver.jwt.issuer-uri}/protocol/openid-connect/certs
+            
 server:
   http2:
     enabled: true
@@ -52,13 +70,6 @@ management:
 goofy:
   production: true
     
-keycloak:
-  auth-server-url: http://localhost:8088
-  realm: sh-kiel-dev
-  resource: sh-kiel-dev-goofy
-  public-client: true
-  use-resource-role-mappings: true
-
 grpc:
   client:
     pluto: