diff --git a/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-resource-server-obo/src/main/java/com/azure/spring/sample/aad/configuration/AADSampleConfiguration.java b/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-resource-server-obo/src/main/java/com/azure/spring/sample/aad/configuration/AADSampleConfiguration.java index 41ff9abd115e4..aa5d147e11475 100644 --- a/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-resource-server-obo/src/main/java/com/azure/spring/sample/aad/configuration/AADSampleConfiguration.java +++ b/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-resource-server-obo/src/main/java/com/azure/spring/sample/aad/configuration/AADSampleConfiguration.java @@ -2,11 +2,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; -import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager; import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository; import org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction; import org.springframework.web.reactive.function.client.WebClient; diff --git a/sdk/spring/azure-spring-boot/src/main/java/com/azure/spring/aad/webapi/AADOAuth2OboAuthorizedClientRepository.java b/sdk/spring/azure-spring-boot/src/main/java/com/azure/spring/aad/webapi/AADOAuth2OboAuthorizedClientRepository.java index 5e649b9265b6f..348f7426b209e 100644 --- a/sdk/spring/azure-spring-boot/src/main/java/com/azure/spring/aad/webapi/AADOAuth2OboAuthorizedClientRepository.java +++ b/sdk/spring/azure-spring-boot/src/main/java/com/azure/spring/aad/webapi/AADOAuth2OboAuthorizedClientRepository.java @@ -101,7 +101,7 @@ public T loadAuthorizedClient(String registra request.setAttribute(oboAuthorizedClientAttributeName, (T) oAuth2AuthorizedClient); return (T) oAuth2AuthorizedClient; } catch (ExecutionException exception) { - // Handle conditional access policy for obo flow. + // Handle conditional access policy, step 1. // A user interaction is required, but we are in a web API, and therefore, we need to report back to the // client through a 'WWW-Authenticate' header https://tools.ietf.org/html/rfc6750#section-3.1 Optional.of(exception) diff --git a/sdk/spring/azure-spring-boot/src/main/java/com/azure/spring/aad/webapp/AADHandleConditionalAccessFilter.java b/sdk/spring/azure-spring-boot/src/main/java/com/azure/spring/aad/webapp/AADHandleConditionalAccessFilter.java index 8a5a8fff81d7b..469ea28b95e73 100644 --- a/sdk/spring/azure-spring-boot/src/main/java/com/azure/spring/aad/webapp/AADHandleConditionalAccessFilter.java +++ b/sdk/spring/azure-spring-boot/src/main/java/com/azure/spring/aad/webapp/AADHandleConditionalAccessFilter.java @@ -3,10 +3,10 @@ package com.azure.spring.aad.webapp; +import com.azure.spring.aad.AADClientRegistrationRepository; import com.azure.spring.autoconfigure.aad.Constants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.http.HttpHeaders; +import org.springframework.security.oauth2.client.ClientAuthorizationRequiredException; import org.springframework.util.StringUtils; import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.reactive.function.client.WebClientResponseException; @@ -32,11 +32,11 @@ */ public class AADHandleConditionalAccessFilter extends OncePerRequestFilter { - private static final Logger LOGGER = LoggerFactory.getLogger(AADHandleConditionalAccessFilter.class); @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException { + // Handle conditional access policy, step 2. try { filterChain.doFilter(request, response); } catch (Exception exception) { @@ -53,18 +53,19 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse if (authParameters != null && authParameters.containsKey(Constants.CONDITIONAL_ACCESS_POLICY_CLAIMS)) { request.getSession().setAttribute(Constants.CONDITIONAL_ACCESS_POLICY_CLAIMS, authParameters.get(Constants.CONDITIONAL_ACCESS_POLICY_CLAIMS)); - response.setStatus(302); - try { - response.sendRedirect(Constants.DEFAULT_AUTHORITY_ENDPOINT_URI); - } catch (IOException e) { - LOGGER.error("Failed to redirect at this response.", exception); - } - return; + // OAuth2AuthorizationRequestRedirectFilter will catch this exception to re-authorize. + throw new ClientAuthorizationRequiredException(AADClientRegistrationRepository.AZURE_CLIENT_REGISTRATION_ID); } throw exception; } } + /** + * Get claims filed form the header to re-authorize. + * + * @param wwwAuthenticateHeader httpHeader + * @return authParametersMap + */ private Map parseAuthParameters(String wwwAuthenticateHeader) { return Stream.of(wwwAuthenticateHeader) .filter(header -> !StringUtils.isEmpty(header)) diff --git a/sdk/spring/azure-spring-boot/src/main/java/com/azure/spring/aad/webapp/AADOAuth2AuthorizedClientRepository.java b/sdk/spring/azure-spring-boot/src/main/java/com/azure/spring/aad/webapp/AADOAuth2AuthorizedClientRepository.java index 0594b47efa49f..6e4fcd2a35710 100644 --- a/sdk/spring/azure-spring-boot/src/main/java/com/azure/spring/aad/webapp/AADOAuth2AuthorizedClientRepository.java +++ b/sdk/spring/azure-spring-boot/src/main/java/com/azure/spring/aad/webapp/AADOAuth2AuthorizedClientRepository.java @@ -7,6 +7,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.client.ClientAuthorizationRequiredException; import org.springframework.security.oauth2.client.OAuth2AuthorizationContext; import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider; @@ -68,6 +69,9 @@ public T loadAuthorizedClient(String id, if (repo.isClientNeedConsentWhenLogin(id)) { OAuth2AuthorizedClient azureClient = loadAuthorizedClient(getAzureClientId(), principal, request); + if (azureClient == null) { + throw new ClientAuthorizationRequiredException(AADClientRegistrationRepository.AZURE_CLIENT_REGISTRATION_ID); + } OAuth2AuthorizedClient fakeAuthzClient = createFakeAuthzClient(azureClient, id, principal); OAuth2AuthorizationContext.Builder contextBuilder = OAuth2AuthorizationContext.withAuthorizedClient(fakeAuthzClient); diff --git a/sdk/spring/azure-spring-boot/src/main/java/com/azure/spring/aad/webapp/AADWebSecurityConfigurerAdapter.java b/sdk/spring/azure-spring-boot/src/main/java/com/azure/spring/aad/webapp/AADWebSecurityConfigurerAdapter.java index b29a4f63ef281..5de78993ee16c 100644 --- a/sdk/spring/azure-spring-boot/src/main/java/com/azure/spring/aad/webapp/AADWebSecurityConfigurerAdapter.java +++ b/sdk/spring/azure-spring-boot/src/main/java/com/azure/spring/aad/webapp/AADWebSecurityConfigurerAdapter.java @@ -13,9 +13,9 @@ import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest; import org.springframework.security.oauth2.client.oidc.web.logout.OidcClientInitiatedLogoutSuccessHandler; import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; +import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter; import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver; import org.springframework.security.oauth2.core.oidc.user.OidcUser; -import org.springframework.security.web.access.ExceptionTranslationFilter; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import org.springframework.util.StringUtils; @@ -51,7 +51,7 @@ protected void configure(HttpSecurity http) throws Exception { .logout() .logoutSuccessHandler(oidcLogoutSuccessHandler()) .and() - .addFilterBefore(new AADHandleConditionalAccessFilter(), ExceptionTranslationFilter.class); + .addFilterAfter(new AADHandleConditionalAccessFilter(), OAuth2AuthorizationRequestRedirectFilter.class); // @formatter:off }