From 89999a6d37a1117e8663c71f31c710d21159695a Mon Sep 17 00:00:00 2001 From: Klaus Richarz Date: Thu, 8 Feb 2024 17:13:14 +0100 Subject: [PATCH] #294 use azure easy auth x-ms-client-principal --- pom.xml | 8 +- .../AzureEasyAuthSecurityConfiguration.java | 75 +++++++++++++++---- .../resources/application-production.yaml | 5 -- src/main/resources/application-test.yaml | 5 -- 4 files changed, 65 insertions(+), 28 deletions(-) diff --git a/pom.xml b/pom.xml index 53c39efc9..b9ce463c2 100644 --- a/pom.xml +++ b/pom.xml @@ -37,10 +37,6 @@ org.springframework.boot spring-boot-starter-actuator - - org.springframework.boot - spring-boot-starter-oauth2-resource-server - org.springframework.boot spring-boot-configuration-processor @@ -52,6 +48,10 @@ runtime true + + com.jayway.jsonpath + json-path + org.projectlombok lombok diff --git a/src/main/java/org/tb/common/configuration/AzureEasyAuthSecurityConfiguration.java b/src/main/java/org/tb/common/configuration/AzureEasyAuthSecurityConfiguration.java index 27b48910a..d4492d253 100644 --- a/src/main/java/org/tb/common/configuration/AzureEasyAuthSecurityConfiguration.java +++ b/src/main/java/org/tb/common/configuration/AzureEasyAuthSecurityConfiguration.java @@ -1,23 +1,38 @@ package org.tb.common.configuration; +import com.jayway.jsonpath.JsonPath; +import java.nio.charset.Charset; +import java.util.Base64; +import java.util.List; +import java.util.Set; +import javax.servlet.http.HttpServletRequest; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.DefaultAuthenticationEventPublisher; +import org.springframework.security.authentication.ProviderManager; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; -import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; -import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver; -import org.springframework.security.oauth2.server.resource.web.HeaderBearerTokenResolver; +import org.springframework.security.core.userdetails.AuthenticationUserDetailsService; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; +import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider; +import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; +import org.tb.employee.domain.Employee; @Configuration @Profile({ "production", "test" }) public class AzureEasyAuthSecurityConfiguration { @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http.authorizeRequests(authz -> authz.antMatchers("/do/**", "**/*.jsp", "/rest/**").authenticated()) - .oauth2ResourceServer(oauth2 -> oauth2.jwt()); + public SecurityFilterChain filterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception { + http.addFilter(preAuthenticatedProcessingFilter(authenticationManager)).authorizeRequests(authz -> authz.antMatchers("/do/**", "**/*.jsp", "/rest/**").authenticated()); http.csrf().disable(); return http.build(); } @@ -28,17 +43,49 @@ public WebSecurityCustomizer ignoringCustomizer() { } @Bean - BearerTokenResolver bearerTokenResolver() { - // TODO move to application.yml - HeaderBearerTokenResolver bearerTokenResolver = new HeaderBearerTokenResolver("x-ms-token-aad-id-token"); - return bearerTokenResolver; + public AuthenticationManager authenticationManager(AuthenticationProvider authenticationProvider, ApplicationEventPublisher publisher) { + ProviderManager providerManager = new ProviderManager(authenticationProvider); + providerManager.setAuthenticationEventPublisher(new DefaultAuthenticationEventPublisher(publisher)); + return providerManager; + } + + private AbstractPreAuthenticatedProcessingFilter preAuthenticatedProcessingFilter(AuthenticationManager authenticationManager) { + AbstractPreAuthenticatedProcessingFilter preAuthenticatedProcessingFilter = new AbstractPreAuthenticatedProcessingFilter() { + @Override + protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) { + String claimsBase64 = request.getHeader("x-ms-client-principal"); + String claims = new String(Base64.getDecoder().decode(claimsBase64.getBytes()), Charset.forName("UTF-8")); + List employeeSigns = JsonPath.read(claims, "$.claims[?(@.typ=='mailnickname')].val"); + String employeeSign = employeeSigns.get(0); + if(employeeSign == null) { + Employee loginEmployee = (Employee) request.getSession().getAttribute("loginEmployee"); + if(loginEmployee != null) { + employeeSign = loginEmployee.getSign(); + } + } + return employeeSign; + } + + @Override + protected Object getPreAuthenticatedCredentials(HttpServletRequest request) { + return "N/A"; + } + }; + preAuthenticatedProcessingFilter.setAuthenticationManager(authenticationManager); + preAuthenticatedProcessingFilter.setCheckForPrincipalChanges(true); + return preAuthenticatedProcessingFilter; } @Bean - public JwtAuthenticationConverter customJwtAuthenticationConverter() { - JwtAuthenticationConverter converter = new JwtAuthenticationConverter(); - converter.setPrincipalClaimName("mailnickname"); - return converter; + public AuthenticationProvider authenticationProvider() { + PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider(); + provider.setPreAuthenticatedUserDetailsService(new AuthenticationUserDetailsService() { + @Override + public UserDetails loadUserDetails(PreAuthenticatedAuthenticationToken token) throws UsernameNotFoundException { + return new User(token.getName(), "N/A", Set.of()); + } + }); + return provider; } } diff --git a/src/main/resources/application-production.yaml b/src/main/resources/application-production.yaml index dede347d6..b4194c7af 100644 --- a/src/main/resources/application-production.yaml +++ b/src/main/resources/application-production.yaml @@ -8,8 +8,3 @@ spring: resources: cache: period: 1d - security: - oauth2: - resourceserver: - jwt: - issuer-uri: https://login.microsoftonline.com/0af2c34e-4e40-42d9-89ab-e095b8151308/v2.0 diff --git a/src/main/resources/application-test.yaml b/src/main/resources/application-test.yaml index dede347d6..b4194c7af 100644 --- a/src/main/resources/application-test.yaml +++ b/src/main/resources/application-test.yaml @@ -8,8 +8,3 @@ spring: resources: cache: period: 1d - security: - oauth2: - resourceserver: - jwt: - issuer-uri: https://login.microsoftonline.com/0af2c34e-4e40-42d9-89ab-e095b8151308/v2.0