mirror of
				https://github.com/spring-projects/spring-security.git
				synced 2025-10-31 06:38:42 +00:00 
			
		
		
		
	
							parent
							
								
									f2da2c56be
								
							
						
					
					
						commit
						c8cc9717c9
					
				| @ -20,8 +20,6 @@ import org.springframework.security.core.Authentication; | |||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; | import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; | ||||||
| import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager; | import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager; | ||||||
| import org.springframework.security.oauth2.client.web.RemoveAuthorizedClientOAuth2AuthorizationFailureHandler; |  | ||||||
| import org.springframework.security.oauth2.client.web.SaveAuthorizedClientOAuth2AuthorizationSuccessHandler; |  | ||||||
| import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
| import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; | import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; | ||||||
| @ -94,8 +92,11 @@ public final class AuthorizedClientServiceOAuth2AuthorizedClientManager implemen | |||||||
| 		this.clientRegistrationRepository = clientRegistrationRepository; | 		this.clientRegistrationRepository = clientRegistrationRepository; | ||||||
| 		this.authorizedClientService = authorizedClientService; | 		this.authorizedClientService = authorizedClientService; | ||||||
| 		this.contextAttributesMapper = new DefaultContextAttributesMapper(); | 		this.contextAttributesMapper = new DefaultContextAttributesMapper(); | ||||||
| 		this.authorizationSuccessHandler = new SaveAuthorizedClientOAuth2AuthorizationSuccessHandler(authorizedClientService); | 		this.authorizationSuccessHandler = (authorizedClient, principal, attributes) -> | ||||||
| 		this.authorizationFailureHandler = new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler(authorizedClientService); | 				authorizedClientService.saveAuthorizedClient(authorizedClient, principal); | ||||||
|  | 		this.authorizationFailureHandler = new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler( | ||||||
|  | 				(clientRegistrationId, principal, attributes) -> | ||||||
|  | 						authorizedClientService.removeAuthorizedClient(clientRegistrationId, principal.getName())); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Nullable | 	@Nullable | ||||||
| @ -177,10 +178,9 @@ public final class AuthorizedClientServiceOAuth2AuthorizedClientManager implemen | |||||||
| 	 * Sets the {@link OAuth2AuthorizationSuccessHandler} that handles successful authorizations. | 	 * Sets the {@link OAuth2AuthorizationSuccessHandler} that handles successful authorizations. | ||||||
| 	 * | 	 * | ||||||
| 	 * <p> | 	 * <p> | ||||||
| 	 * A {@link SaveAuthorizedClientOAuth2AuthorizationSuccessHandler} is used by default. | 	 * The default saves {@link OAuth2AuthorizedClient}s in the {@link OAuth2AuthorizedClientService}. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param authorizationSuccessHandler the {@link OAuth2AuthorizationSuccessHandler} that handles successful authorizations | 	 * @param authorizationSuccessHandler the {@link OAuth2AuthorizationSuccessHandler} that handles successful authorizations | ||||||
| 	 * @see SaveAuthorizedClientOAuth2AuthorizationSuccessHandler |  | ||||||
| 	 * @since 5.3 | 	 * @since 5.3 | ||||||
| 	 */ | 	 */ | ||||||
| 	public void setAuthorizationSuccessHandler(OAuth2AuthorizationSuccessHandler authorizationSuccessHandler) { | 	public void setAuthorizationSuccessHandler(OAuth2AuthorizationSuccessHandler authorizationSuccessHandler) { | ||||||
|  | |||||||
| @ -18,8 +18,6 @@ package org.springframework.security.oauth2.client; | |||||||
| import org.springframework.security.core.Authentication; | import org.springframework.security.core.Authentication; | ||||||
| import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; | import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; | ||||||
| import org.springframework.security.oauth2.client.web.DefaultReactiveOAuth2AuthorizedClientManager; | import org.springframework.security.oauth2.client.web.DefaultReactiveOAuth2AuthorizedClientManager; | ||||||
| import org.springframework.security.oauth2.client.web.RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler; |  | ||||||
| import org.springframework.security.oauth2.client.web.SaveAuthorizedClientReactiveOAuth2AuthorizationSuccessHandler; |  | ||||||
| import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
| import org.springframework.util.Assert; | import org.springframework.util.Assert; | ||||||
| import org.springframework.web.server.ServerWebExchange; | import org.springframework.web.server.ServerWebExchange; | ||||||
| @ -91,8 +89,11 @@ public final class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager | |||||||
| 		Assert.notNull(authorizedClientService, "authorizedClientService cannot be null"); | 		Assert.notNull(authorizedClientService, "authorizedClientService cannot be null"); | ||||||
| 		this.clientRegistrationRepository = clientRegistrationRepository; | 		this.clientRegistrationRepository = clientRegistrationRepository; | ||||||
| 		this.authorizedClientService = authorizedClientService; | 		this.authorizedClientService = authorizedClientService; | ||||||
| 		this.authorizationSuccessHandler = new SaveAuthorizedClientReactiveOAuth2AuthorizationSuccessHandler(authorizedClientService); | 		this.authorizationSuccessHandler = (authorizedClient, principal, attributes) -> | ||||||
| 		this.authorizationFailureHandler = new RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler(authorizedClientService); | 				authorizedClientService.saveAuthorizedClient(authorizedClient, principal); | ||||||
|  | 		this.authorizationFailureHandler = new RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler( | ||||||
|  | 				(clientRegistrationId, principal, attributes) -> | ||||||
|  | 						this.authorizedClientService.removeAuthorizedClient(clientRegistrationId, principal.getName())); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
| @ -179,11 +180,9 @@ public final class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager | |||||||
| 	/** | 	/** | ||||||
| 	 * Sets the handler that handles successful authorizations. | 	 * Sets the handler that handles successful authorizations. | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>A {@link SaveAuthorizedClientReactiveOAuth2AuthorizationSuccessHandler} | 	 * The default saves {@link OAuth2AuthorizedClient}s in the {@link ReactiveOAuth2AuthorizedClientService}. | ||||||
| 	 * is used by default.</p> |  | ||||||
| 	 * | 	 * | ||||||
| 	 * @param authorizationSuccessHandler the handler that handles successful authorizations. | 	 * @param authorizationSuccessHandler the handler that handles successful authorizations. | ||||||
| 	 * @see SaveAuthorizedClientReactiveOAuth2AuthorizationSuccessHandler |  | ||||||
| 	 * @since 5.3 | 	 * @since 5.3 | ||||||
| 	 */ | 	 */ | ||||||
| 	public void setAuthorizationSuccessHandler(ReactiveOAuth2AuthorizationSuccessHandler authorizationSuccessHandler) { | 	public void setAuthorizationSuccessHandler(ReactiveOAuth2AuthorizationSuccessHandler authorizationSuccessHandler) { | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2019 the original author or authors. |  * Copyright 2002-2020 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -22,6 +22,7 @@ import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentia | |||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.core.AbstractOAuth2Token; | import org.springframework.security.oauth2.core.AbstractOAuth2Token; | ||||||
| import org.springframework.security.oauth2.core.AuthorizationGrantType; | import org.springframework.security.oauth2.core.AuthorizationGrantType; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | ||||||
| import org.springframework.util.Assert; | import org.springframework.util.Assert; | ||||||
| 
 | 
 | ||||||
| @ -79,8 +80,13 @@ public final class ClientCredentialsOAuth2AuthorizedClientProvider implements OA | |||||||
| 
 | 
 | ||||||
| 		OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = | 		OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = | ||||||
| 				new OAuth2ClientCredentialsGrantRequest(clientRegistration); | 				new OAuth2ClientCredentialsGrantRequest(clientRegistration); | ||||||
| 		OAuth2AccessTokenResponse tokenResponse = | 
 | ||||||
| 				this.accessTokenResponseClient.getTokenResponse(clientCredentialsGrantRequest); | 		OAuth2AccessTokenResponse tokenResponse; | ||||||
|  | 		try { | ||||||
|  | 			tokenResponse = this.accessTokenResponseClient.getTokenResponse(clientCredentialsGrantRequest); | ||||||
|  | 		} catch (OAuth2AuthorizationException ex) { | ||||||
|  | 			throw new ClientAuthorizationException(ex.getError(), clientRegistration.getRegistrationId(), ex); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		return new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(), tokenResponse.getAccessToken()); | 		return new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(), tokenResponse.getAccessToken()); | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2019 the original author or authors. |  * Copyright 2002-2020 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -21,6 +21,7 @@ import org.springframework.security.oauth2.client.endpoint.WebClientReactiveClie | |||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.core.AbstractOAuth2Token; | import org.springframework.security.oauth2.core.AbstractOAuth2Token; | ||||||
| import org.springframework.security.oauth2.core.AuthorizationGrantType; | import org.springframework.security.oauth2.core.AuthorizationGrantType; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
| import org.springframework.util.Assert; | import org.springframework.util.Assert; | ||||||
| import reactor.core.publisher.Mono; | import reactor.core.publisher.Mono; | ||||||
| 
 | 
 | ||||||
| @ -77,6 +78,8 @@ public final class ClientCredentialsReactiveOAuth2AuthorizedClientProvider imple | |||||||
| 
 | 
 | ||||||
| 		return Mono.just(new OAuth2ClientCredentialsGrantRequest(clientRegistration)) | 		return Mono.just(new OAuth2ClientCredentialsGrantRequest(clientRegistration)) | ||||||
| 				.flatMap(this.accessTokenResponseClient::getTokenResponse) | 				.flatMap(this.accessTokenResponseClient::getTokenResponse) | ||||||
|  | 				.onErrorMap(OAuth2AuthorizationException.class, | ||||||
|  | 						e -> new ClientAuthorizationException(e.getError(), clientRegistration.getRegistrationId(), e)) | ||||||
| 				.map(tokenResponse -> new OAuth2AuthorizedClient( | 				.map(tokenResponse -> new OAuth2AuthorizedClient( | ||||||
| 						clientRegistration, context.getPrincipal().getName(), tokenResponse.getAccessToken())); | 						clientRegistration, context.getPrincipal().getName(), tokenResponse.getAccessToken())); | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2019 the original author or authors. |  * Copyright 2002-2020 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -22,6 +22,7 @@ import org.springframework.security.oauth2.client.endpoint.OAuth2PasswordGrantRe | |||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.core.AbstractOAuth2Token; | import org.springframework.security.oauth2.core.AbstractOAuth2Token; | ||||||
| import org.springframework.security.oauth2.core.AuthorizationGrantType; | import org.springframework.security.oauth2.core.AuthorizationGrantType; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | ||||||
| import org.springframework.util.Assert; | import org.springframework.util.Assert; | ||||||
| import org.springframework.util.StringUtils; | import org.springframework.util.StringUtils; | ||||||
| @ -96,8 +97,13 @@ public final class PasswordOAuth2AuthorizedClientProvider implements OAuth2Autho | |||||||
| 
 | 
 | ||||||
| 		OAuth2PasswordGrantRequest passwordGrantRequest = | 		OAuth2PasswordGrantRequest passwordGrantRequest = | ||||||
| 				new OAuth2PasswordGrantRequest(clientRegistration, username, password); | 				new OAuth2PasswordGrantRequest(clientRegistration, username, password); | ||||||
| 		OAuth2AccessTokenResponse tokenResponse = | 
 | ||||||
| 				this.accessTokenResponseClient.getTokenResponse(passwordGrantRequest); | 		OAuth2AccessTokenResponse tokenResponse; | ||||||
|  | 		try { | ||||||
|  | 			tokenResponse = this.accessTokenResponseClient.getTokenResponse(passwordGrantRequest); | ||||||
|  | 		} catch (OAuth2AuthorizationException ex) { | ||||||
|  | 			throw new ClientAuthorizationException(ex.getError(), clientRegistration.getRegistrationId(), ex); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		return new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(), | 		return new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(), | ||||||
| 				tokenResponse.getAccessToken(), tokenResponse.getRefreshToken()); | 				tokenResponse.getAccessToken(), tokenResponse.getRefreshToken()); | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2019 the original author or authors. |  * Copyright 2002-2020 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -21,6 +21,7 @@ import org.springframework.security.oauth2.client.endpoint.WebClientReactivePass | |||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.core.AbstractOAuth2Token; | import org.springframework.security.oauth2.core.AbstractOAuth2Token; | ||||||
| import org.springframework.security.oauth2.core.AuthorizationGrantType; | import org.springframework.security.oauth2.core.AuthorizationGrantType; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
| import org.springframework.util.Assert; | import org.springframework.util.Assert; | ||||||
| import org.springframework.util.StringUtils; | import org.springframework.util.StringUtils; | ||||||
| import reactor.core.publisher.Mono; | import reactor.core.publisher.Mono; | ||||||
| @ -97,6 +98,8 @@ public final class PasswordReactiveOAuth2AuthorizedClientProvider implements Rea | |||||||
| 
 | 
 | ||||||
| 		return Mono.just(passwordGrantRequest) | 		return Mono.just(passwordGrantRequest) | ||||||
| 				.flatMap(this.accessTokenResponseClient::getTokenResponse) | 				.flatMap(this.accessTokenResponseClient::getTokenResponse) | ||||||
|  | 				.onErrorMap(OAuth2AuthorizationException.class, | ||||||
|  | 						e -> new ClientAuthorizationException(e.getError(), clientRegistration.getRegistrationId(), e)) | ||||||
| 				.map(tokenResponse -> new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(), | 				.map(tokenResponse -> new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(), | ||||||
| 						tokenResponse.getAccessToken(), tokenResponse.getRefreshToken())); | 						tokenResponse.getAccessToken(), tokenResponse.getRefreshToken())); | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2019 the original author or authors. |  * Copyright 2002-2020 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -21,6 +21,7 @@ import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResp | |||||||
| import org.springframework.security.oauth2.client.endpoint.OAuth2RefreshTokenGrantRequest; | import org.springframework.security.oauth2.client.endpoint.OAuth2RefreshTokenGrantRequest; | ||||||
| import org.springframework.security.oauth2.core.AbstractOAuth2Token; | import org.springframework.security.oauth2.core.AbstractOAuth2Token; | ||||||
| import org.springframework.security.oauth2.core.AuthorizationGrantType; | import org.springframework.security.oauth2.core.AuthorizationGrantType; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | ||||||
| import org.springframework.util.Assert; | import org.springframework.util.Assert; | ||||||
| 
 | 
 | ||||||
| @ -86,8 +87,13 @@ public final class RefreshTokenOAuth2AuthorizedClientProvider implements OAuth2A | |||||||
| 		OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest( | 		OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest( | ||||||
| 				authorizedClient.getClientRegistration(), authorizedClient.getAccessToken(), | 				authorizedClient.getClientRegistration(), authorizedClient.getAccessToken(), | ||||||
| 				authorizedClient.getRefreshToken(), scopes); | 				authorizedClient.getRefreshToken(), scopes); | ||||||
| 		OAuth2AccessTokenResponse tokenResponse = | 
 | ||||||
| 				this.accessTokenResponseClient.getTokenResponse(refreshTokenGrantRequest); | 		OAuth2AccessTokenResponse tokenResponse; | ||||||
|  | 		try { | ||||||
|  | 			tokenResponse = this.accessTokenResponseClient.getTokenResponse(refreshTokenGrantRequest); | ||||||
|  | 		} catch (OAuth2AuthorizationException ex) { | ||||||
|  | 			throw new ClientAuthorizationException(ex.getError(), authorizedClient.getClientRegistration().getRegistrationId(), ex); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		return new OAuth2AuthorizedClient(context.getAuthorizedClient().getClientRegistration(), | 		return new OAuth2AuthorizedClient(context.getAuthorizedClient().getClientRegistration(), | ||||||
| 				context.getPrincipal().getName(), tokenResponse.getAccessToken(), tokenResponse.getRefreshToken()); | 				context.getPrincipal().getName(), tokenResponse.getAccessToken(), tokenResponse.getRefreshToken()); | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2019 the original author or authors. |  * Copyright 2002-2020 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -21,6 +21,7 @@ import org.springframework.security.oauth2.client.endpoint.WebClientReactiveRefr | |||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.core.AbstractOAuth2Token; | import org.springframework.security.oauth2.core.AbstractOAuth2Token; | ||||||
| import org.springframework.security.oauth2.core.AuthorizationGrantType; | import org.springframework.security.oauth2.core.AuthorizationGrantType; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
| import org.springframework.util.Assert; | import org.springframework.util.Assert; | ||||||
| import reactor.core.publisher.Mono; | import reactor.core.publisher.Mono; | ||||||
| 
 | 
 | ||||||
| @ -88,6 +89,8 @@ public final class RefreshTokenReactiveOAuth2AuthorizedClientProvider implements | |||||||
| 
 | 
 | ||||||
| 		return Mono.just(refreshTokenGrantRequest) | 		return Mono.just(refreshTokenGrantRequest) | ||||||
| 				.flatMap(this.accessTokenResponseClient::getTokenResponse) | 				.flatMap(this.accessTokenResponseClient::getTokenResponse) | ||||||
|  | 				.onErrorMap(OAuth2AuthorizationException.class, | ||||||
|  | 						e -> new ClientAuthorizationException(e.getError(), clientRegistration.getRegistrationId(), e)) | ||||||
| 				.map(tokenResponse -> new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(), | 				.map(tokenResponse -> new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(), | ||||||
| 						tokenResponse.getAccessToken(), tokenResponse.getRefreshToken())); | 						tokenResponse.getAccessToken(), tokenResponse.getRefreshToken())); | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -13,19 +13,15 @@ | |||||||
|  * See the License for the specific language governing permissions and |  * See the License for the specific language governing permissions and | ||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  */ |  */ | ||||||
| package org.springframework.security.oauth2.client.web; | package org.springframework.security.oauth2.client; | ||||||
| 
 | 
 | ||||||
| import org.springframework.security.core.Authentication; | import org.springframework.security.core.Authentication; | ||||||
| import org.springframework.security.oauth2.client.ClientAuthorizationException; | import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository; | ||||||
| import org.springframework.security.oauth2.client.OAuth2AuthorizationFailureHandler; |  | ||||||
| import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; |  | ||||||
| import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; |  | ||||||
| import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2Error; | ||||||
| import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | ||||||
| import org.springframework.util.Assert; | import org.springframework.util.Assert; | ||||||
| 
 | 
 | ||||||
| import javax.servlet.http.HttpServletRequest; |  | ||||||
| import javax.servlet.http.HttpServletResponse; |  | ||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
| import java.util.Collections; | import java.util.Collections; | ||||||
| import java.util.HashSet; | import java.util.HashSet; | ||||||
| @ -34,8 +30,8 @@ import java.util.Set; | |||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * An {@link OAuth2AuthorizationFailureHandler} that removes an {@link OAuth2AuthorizedClient} |  * An {@link OAuth2AuthorizationFailureHandler} that removes an {@link OAuth2AuthorizedClient} | ||||||
|  * from an {@link OAuth2AuthorizedClientRepository} or {@link OAuth2AuthorizedClientService} |  * when the {@link OAuth2Error#getErrorCode()} matches | ||||||
|  * for a specific set of OAuth 2.0 error codes. |  * one of the configured {@link OAuth2ErrorCodes OAuth 2.0 error codes}. | ||||||
|  * |  * | ||||||
|  * @author Joe Grandja |  * @author Joe Grandja | ||||||
|  * @since 5.3 |  * @since 5.3 | ||||||
| @ -74,73 +70,58 @@ public class RemoveAuthorizedClientOAuth2AuthorizationFailureHandler implements | |||||||
| 	private final Set<String> removeAuthorizedClientErrorCodes; | 	private final Set<String> removeAuthorizedClientErrorCodes; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * A delegate that removes an {@link OAuth2AuthorizedClient} from a | 	 * A delegate that removes an {@link OAuth2AuthorizedClient} from an | ||||||
| 	 * {@link OAuth2AuthorizedClientRepository} or {@link OAuth2AuthorizedClientService} | 	 * {@link OAuth2AuthorizedClientRepository} or {@link OAuth2AuthorizedClientService} | ||||||
| 	 * if the error code is one of the {@link #removeAuthorizedClientErrorCodes}. | 	 * if the error code is one of the {@link #removeAuthorizedClientErrorCodes}. | ||||||
| 	 */ | 	 */ | ||||||
| 	private final OAuth2AuthorizedClientRemover delegate; | 	private final OAuth2AuthorizedClientRemover delegate; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Removes an {@link OAuth2AuthorizedClient} from an | ||||||
|  | 	 * {@link OAuth2AuthorizedClientRepository} or {@link OAuth2AuthorizedClientService}. | ||||||
|  | 	 */ | ||||||
| 	@FunctionalInterface | 	@FunctionalInterface | ||||||
| 	private interface OAuth2AuthorizedClientRemover { | 	public interface OAuth2AuthorizedClientRemover { | ||||||
|  | 
 | ||||||
|  | 		/** | ||||||
|  | 		 * Removes the {@link OAuth2AuthorizedClient} associated to the | ||||||
|  | 		 * provided client registration identifier and End-User {@link Authentication} (Resource Owner). | ||||||
|  | 		 * | ||||||
|  | 		 * @param clientRegistrationId the identifier for the client's registration | ||||||
|  | 		 * @param principal the End-User {@link Authentication} (Resource Owner) | ||||||
|  | 		 * @param attributes an immutable {@code Map} of (optional) attributes present under certain conditions. | ||||||
|  | 		 *                   For example, this might contain a {@code javax.servlet.http.HttpServletRequest} | ||||||
|  | 		 *                   and {@code javax.servlet.http.HttpServletResponse} if the authorization was performed | ||||||
|  | 		 *                   within the context of a {@code javax.servlet.ServletContext}. | ||||||
|  | 		 */ | ||||||
| 		void removeAuthorizedClient(String clientRegistrationId, Authentication principal, Map<String, Object> attributes); | 		void removeAuthorizedClient(String clientRegistrationId, Authentication principal, Map<String, Object> attributes); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Constructs a {@code RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} using the provided parameters. | 	 * Constructs a {@code RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} using the provided parameters. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param authorizedClientRepository the repository from which authorized clients will be removed | 	 * @param authorizedClientRemover the {@link OAuth2AuthorizedClientRemover} used for removing an {@link OAuth2AuthorizedClient} | ||||||
| 	 *                                   if the error code is one of the {@link #DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES}. |  | ||||||
| 	 */ |  | ||||||
| 	public RemoveAuthorizedClientOAuth2AuthorizationFailureHandler(OAuth2AuthorizedClientRepository authorizedClientRepository) { |  | ||||||
| 		this(authorizedClientRepository, DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/** |  | ||||||
| 	 * Constructs a {@code RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} using the provided parameters. |  | ||||||
| 	 * |  | ||||||
| 	 * @param authorizedClientRepository the repository from which authorized clients will be removed |  | ||||||
| 	 *                                   if the error code is one of the {@link #removeAuthorizedClientErrorCodes}. |  | ||||||
| 	 * @param removeAuthorizedClientErrorCodes the OAuth 2.0 error codes which will trigger removal of an authorized client. |  | ||||||
| 	 * @see OAuth2ErrorCodes |  | ||||||
| 	 */ |  | ||||||
| 	public RemoveAuthorizedClientOAuth2AuthorizationFailureHandler( |  | ||||||
| 			OAuth2AuthorizedClientRepository authorizedClientRepository, |  | ||||||
| 			Set<String> removeAuthorizedClientErrorCodes) { |  | ||||||
| 		Assert.notNull(authorizedClientRepository, "authorizedClientRepository cannot be null"); |  | ||||||
| 		Assert.notNull(removeAuthorizedClientErrorCodes, "removeAuthorizedClientErrorCodes cannot be null"); |  | ||||||
| 		this.removeAuthorizedClientErrorCodes = Collections.unmodifiableSet(new HashSet<>(removeAuthorizedClientErrorCodes)); |  | ||||||
| 		this.delegate = (clientRegistrationId, principal, attributes) -> |  | ||||||
| 				authorizedClientRepository.removeAuthorizedClient(clientRegistrationId, principal, |  | ||||||
| 						(HttpServletRequest) attributes.get(HttpServletRequest.class.getName()), |  | ||||||
| 						(HttpServletResponse) attributes.get(HttpServletResponse.class.getName())); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/** |  | ||||||
| 	 * Constructs a {@code RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} using the provided parameters. |  | ||||||
| 	 * |  | ||||||
| 	 * @param authorizedClientService the service from which authorized clients will be removed |  | ||||||
| 	 *                                if the error code is one of the {@link #DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES}. | 	 *                                if the error code is one of the {@link #DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES}. | ||||||
| 	 */ | 	 */ | ||||||
| 	public RemoveAuthorizedClientOAuth2AuthorizationFailureHandler(OAuth2AuthorizedClientService authorizedClientService) { | 	public RemoveAuthorizedClientOAuth2AuthorizationFailureHandler(OAuth2AuthorizedClientRemover authorizedClientRemover) { | ||||||
| 		this(authorizedClientService, DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES); | 		this(authorizedClientRemover, DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Constructs a {@code RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} using the provided parameters. | 	 * Constructs a {@code RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} using the provided parameters. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param authorizedClientService the service from which authorized clients will be removed | 	 * @param authorizedClientRemover the {@link OAuth2AuthorizedClientRemover} used for removing an {@link OAuth2AuthorizedClient} | ||||||
| 	 *                                if the error code is one of the {@link #removeAuthorizedClientErrorCodes}. | 	 *                                if the error code is one of the {@link #removeAuthorizedClientErrorCodes}. | ||||||
| 	 * @param removeAuthorizedClientErrorCodes the OAuth 2.0 error codes which will trigger removal of an authorized client. | 	 * @param removeAuthorizedClientErrorCodes the OAuth 2.0 error codes which will trigger removal of an authorized client. | ||||||
| 	 * @see OAuth2ErrorCodes | 	 * @see OAuth2ErrorCodes | ||||||
| 	 */ | 	 */ | ||||||
| 	public RemoveAuthorizedClientOAuth2AuthorizationFailureHandler( | 	public RemoveAuthorizedClientOAuth2AuthorizationFailureHandler( | ||||||
| 			OAuth2AuthorizedClientService authorizedClientService, | 			OAuth2AuthorizedClientRemover authorizedClientRemover, | ||||||
| 			Set<String> removeAuthorizedClientErrorCodes) { | 			Set<String> removeAuthorizedClientErrorCodes) { | ||||||
| 		Assert.notNull(authorizedClientService, "authorizedClientService cannot be null"); | 		Assert.notNull(authorizedClientRemover, "authorizedClientRemover cannot be null"); | ||||||
| 		Assert.notNull(removeAuthorizedClientErrorCodes, "removeAuthorizedClientErrorCodes cannot be null"); | 		Assert.notNull(removeAuthorizedClientErrorCodes, "removeAuthorizedClientErrorCodes cannot be null"); | ||||||
| 		this.removeAuthorizedClientErrorCodes = Collections.unmodifiableSet(new HashSet<>(removeAuthorizedClientErrorCodes)); | 		this.removeAuthorizedClientErrorCodes = Collections.unmodifiableSet(new HashSet<>(removeAuthorizedClientErrorCodes)); | ||||||
| 		this.delegate = (clientRegistrationId, principal, attributes) -> | 		this.delegate = authorizedClientRemover; | ||||||
| 				authorizedClientService.removeAuthorizedClient(clientRegistrationId, principal.getName()); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
| @ -149,6 +130,7 @@ public class RemoveAuthorizedClientOAuth2AuthorizationFailureHandler implements | |||||||
| 
 | 
 | ||||||
| 		if (authorizationException instanceof ClientAuthorizationException && | 		if (authorizationException instanceof ClientAuthorizationException && | ||||||
| 				hasRemovalErrorCode(authorizationException)) { | 				hasRemovalErrorCode(authorizationException)) { | ||||||
|  | 
 | ||||||
| 			ClientAuthorizationException clientAuthorizationException = (ClientAuthorizationException) authorizationException; | 			ClientAuthorizationException clientAuthorizationException = (ClientAuthorizationException) authorizationException; | ||||||
| 			this.delegate.removeAuthorizedClient( | 			this.delegate.removeAuthorizedClient( | ||||||
| 					clientAuthorizationException.getClientRegistrationId(), principal, attributes); | 					clientAuthorizationException.getClientRegistrationId(), principal, attributes); | ||||||
| @ -13,17 +13,14 @@ | |||||||
|  * See the License for the specific language governing permissions and |  * See the License for the specific language governing permissions and | ||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  */ |  */ | ||||||
| package org.springframework.security.oauth2.client.web; | package org.springframework.security.oauth2.client; | ||||||
| 
 | 
 | ||||||
| import org.springframework.security.core.Authentication; | import org.springframework.security.core.Authentication; | ||||||
| import org.springframework.security.oauth2.client.ClientAuthorizationException; |  | ||||||
| import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizationFailureHandler; |  | ||||||
| import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientService; |  | ||||||
| import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; | import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; | ||||||
| import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2Error; | ||||||
| import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | ||||||
| import org.springframework.util.Assert; | import org.springframework.util.Assert; | ||||||
| import org.springframework.web.server.ServerWebExchange; |  | ||||||
| import reactor.core.publisher.Mono; | import reactor.core.publisher.Mono; | ||||||
| 
 | 
 | ||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
| @ -33,10 +30,9 @@ import java.util.Map; | |||||||
| import java.util.Set; | import java.util.Set; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * An authorization failure handler that removes authorized clients from a |  * A {@link ReactiveOAuth2AuthorizationFailureHandler} that removes an {@link OAuth2AuthorizedClient} | ||||||
|  * {@link ServerOAuth2AuthorizedClientRepository} |  * when the {@link OAuth2Error#getErrorCode()} matches | ||||||
|  * or a {@link ReactiveOAuth2AuthorizedClientService}. |  * one of the configured {@link OAuth2ErrorCodes OAuth 2.0 error codes}. | ||||||
|  * for specific OAuth 2.0 error codes. |  | ||||||
|  * |  * | ||||||
|  * @author Phil Clay |  * @author Phil Clay | ||||||
|  * @since 5.3 |  * @since 5.3 | ||||||
| @ -64,10 +60,8 @@ public class RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler imp | |||||||
| 			OAuth2ErrorCodes.INVALID_GRANT))); | 			OAuth2ErrorCodes.INVALID_GRANT))); | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * A delegate that removes clients from either a | 	 * A delegate that removes an {@link OAuth2AuthorizedClient} from a | ||||||
| 	 * {@link ServerOAuth2AuthorizedClientRepository} | 	 * {@link ServerOAuth2AuthorizedClientRepository} or {@link ReactiveOAuth2AuthorizedClientService} | ||||||
| 	 * or a |  | ||||||
| 	 * {@link ReactiveOAuth2AuthorizedClientService} |  | ||||||
| 	 * if the error code is one of the {@link #removeAuthorizedClientErrorCodes}. | 	 * if the error code is one of the {@link #removeAuthorizedClientErrorCodes}. | ||||||
| 	 */ | 	 */ | ||||||
| 	private final OAuth2AuthorizedClientRemover delegate; | 	private final OAuth2AuthorizedClientRemover delegate; | ||||||
| @ -78,81 +72,64 @@ public class RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler imp | |||||||
| 	 */ | 	 */ | ||||||
| 	private final Set<String> removeAuthorizedClientErrorCodes; | 	private final Set<String> removeAuthorizedClientErrorCodes; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Removes an {@link OAuth2AuthorizedClient} from a | ||||||
|  | 	 * {@link ServerOAuth2AuthorizedClientRepository} or {@link ReactiveOAuth2AuthorizedClientService}. | ||||||
|  | 	 */ | ||||||
| 	@FunctionalInterface | 	@FunctionalInterface | ||||||
| 	private interface OAuth2AuthorizedClientRemover { | 	public interface OAuth2AuthorizedClientRemover { | ||||||
| 		Mono<Void> removeAuthorizedClient( | 
 | ||||||
| 				String clientRegistrationId, | 		/** | ||||||
| 				Authentication principal, | 		 * Removes the {@link OAuth2AuthorizedClient} associated to the | ||||||
| 				Map<String, Object> attributes); | 		 * provided client registration identifier and End-User {@link Authentication} (Resource Owner). | ||||||
|  | 		 * | ||||||
|  | 		 * @param clientRegistrationId the identifier for the client's registration | ||||||
|  | 		 * @param principal the End-User {@link Authentication} (Resource Owner) | ||||||
|  | 		 * @param attributes an immutable {@code Map} of extra optional attributes present under certain conditions. | ||||||
|  | 		 *                   For example, this might contain a {@link org.springframework.web.server.ServerWebExchange ServerWebExchange} | ||||||
|  | 		 *                   if the authorization was performed within the context of a {@code ServerWebExchange}. | ||||||
|  | 		 * @return an empty {@link Mono} that completes after this handler has finished handling the event. | ||||||
|  | 		 */ | ||||||
|  | 		Mono<Void> removeAuthorizedClient(String clientRegistrationId, Authentication principal, Map<String, Object> attributes); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * @param authorizedClientRepository The repository from which authorized clients will be removed | 	 * Constructs a {@code RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} using the provided parameters. | ||||||
| 	 * 		  if the error code is one of the {@link #DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES}. | 	 * | ||||||
|  | 	 * @param authorizedClientRemover the {@link OAuth2AuthorizedClientRemover} used for removing an {@link OAuth2AuthorizedClient} | ||||||
|  | 	 *                                if the error code is one of the {@link #DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES}. | ||||||
| 	 */ | 	 */ | ||||||
| 	public RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler(ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { | 	public RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler(OAuth2AuthorizedClientRemover authorizedClientRemover) { | ||||||
| 		this(authorizedClientRepository, DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES); | 		this(authorizedClientRemover, DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * @param authorizedClientRepository The repository from which authorized clients will be removed | 	 * Constructs a {@code RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} using the provided parameters. | ||||||
| 	 * 		 if the error code is one of the {@code removeAuthorizedClientErrorCodes}. | 	 * | ||||||
| 	 * @param removeAuthorizedClientErrorCodes the OAuth 2.0 Error Codes which will trigger removal of an authorized client. | 	 * @param authorizedClientRemover the {@link OAuth2AuthorizedClientRemover} used for removing an {@link OAuth2AuthorizedClient} | ||||||
|  | 	 *                                if the error code is one of the {@link #removeAuthorizedClientErrorCodes}. | ||||||
|  | 	 * @param removeAuthorizedClientErrorCodes the OAuth 2.0 error codes which will trigger removal of an authorized client. | ||||||
| 	 * @see OAuth2ErrorCodes | 	 * @see OAuth2ErrorCodes | ||||||
| 	 */ | 	 */ | ||||||
| 	public RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler( | 	public RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler( | ||||||
| 			ServerOAuth2AuthorizedClientRepository authorizedClientRepository, | 			OAuth2AuthorizedClientRemover authorizedClientRemover, | ||||||
| 			Set<String> removeAuthorizedClientErrorCodes) { | 			Set<String> removeAuthorizedClientErrorCodes) { | ||||||
| 		Assert.notNull(authorizedClientRepository, "authorizedClientRepository cannot be null"); | 		Assert.notNull(authorizedClientRemover, "authorizedClientRemover cannot be null"); | ||||||
| 		Assert.notNull(removeAuthorizedClientErrorCodes, "removeAuthorizedClientErrorCodes cannot be null"); | 		Assert.notNull(removeAuthorizedClientErrorCodes, "removeAuthorizedClientErrorCodes cannot be null"); | ||||||
| 		this.removeAuthorizedClientErrorCodes = Collections.unmodifiableSet(new HashSet<>(removeAuthorizedClientErrorCodes)); | 		this.removeAuthorizedClientErrorCodes = Collections.unmodifiableSet(new HashSet<>(removeAuthorizedClientErrorCodes)); | ||||||
| 		this.delegate = (clientRegistrationId, principal, attributes) -> | 		this.delegate = authorizedClientRemover; | ||||||
| 				authorizedClientRepository.removeAuthorizedClient( |  | ||||||
| 						clientRegistrationId, |  | ||||||
| 						principal, |  | ||||||
| 						(ServerWebExchange) attributes.get(ServerWebExchange.class.getName())); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/** |  | ||||||
| 	 * @param authorizedClientService the service from which authorized clients will be removed |  | ||||||
| 	 * 		  if the error code is one of the {@link #DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES}. |  | ||||||
| 	 */ |  | ||||||
| 	public RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler(ReactiveOAuth2AuthorizedClientService authorizedClientService) { |  | ||||||
| 		this(authorizedClientService, DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/** |  | ||||||
| 	 * @param authorizedClientService the service from which authorized clients will be removed |  | ||||||
| 	 * 		  if the error code is one of the {@code removeAuthorizedClientErrorCodes}. |  | ||||||
| 	 * @param removeAuthorizedClientErrorCodes the OAuth 2.0 Error Codes which will trigger removal of an authorized client. |  | ||||||
| 	 * @see OAuth2ErrorCodes |  | ||||||
| 	 */ |  | ||||||
| 	public RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler( |  | ||||||
| 			ReactiveOAuth2AuthorizedClientService authorizedClientService, |  | ||||||
| 			Set<String> removeAuthorizedClientErrorCodes) { |  | ||||||
| 		Assert.notNull(authorizedClientService, "authorizedClientService cannot be null"); |  | ||||||
| 		Assert.notNull(removeAuthorizedClientErrorCodes, "removeAuthorizedClientErrorCodes cannot be null"); |  | ||||||
| 		this.removeAuthorizedClientErrorCodes = Collections.unmodifiableSet(new HashSet<>(removeAuthorizedClientErrorCodes)); |  | ||||||
| 		this.delegate = (clientRegistrationId, principal, attributes) -> |  | ||||||
| 				authorizedClientService.removeAuthorizedClient( |  | ||||||
| 						clientRegistrationId, |  | ||||||
| 						principal.getName()); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
| 	public Mono<Void> onAuthorizationFailure( | 	public Mono<Void> onAuthorizationFailure(OAuth2AuthorizationException authorizationException, | ||||||
| 			OAuth2AuthorizationException authorizationException, | 			Authentication principal, Map<String, Object> attributes) { | ||||||
| 			Authentication principal, |  | ||||||
| 			Map<String, Object> attributes) { |  | ||||||
| 
 | 
 | ||||||
| 		if (authorizationException instanceof ClientAuthorizationException | 		if (authorizationException instanceof ClientAuthorizationException | ||||||
| 				&& hasRemovalErrorCode(authorizationException)) { | 				&& hasRemovalErrorCode(authorizationException)) { | ||||||
| 
 | 
 | ||||||
| 			ClientAuthorizationException clientAuthorizationException = (ClientAuthorizationException) authorizationException; | 			ClientAuthorizationException clientAuthorizationException = (ClientAuthorizationException) authorizationException; | ||||||
| 			return this.delegate.removeAuthorizedClient( | 			return this.delegate.removeAuthorizedClient( | ||||||
| 					clientAuthorizationException.getClientRegistrationId(), | 					clientAuthorizationException.getClientRegistrationId(), principal, attributes); | ||||||
| 					principal, |  | ||||||
| 					attributes); |  | ||||||
| 		} else { | 		} else { | ||||||
| 			return Mono.empty(); | 			return Mono.empty(); | ||||||
| 		} | 		} | ||||||
| @ -17,10 +17,8 @@ package org.springframework.security.oauth2.client.endpoint; | |||||||
| 
 | 
 | ||||||
| import org.springframework.http.HttpHeaders; | import org.springframework.http.HttpHeaders; | ||||||
| import org.springframework.http.MediaType; | import org.springframework.http.MediaType; | ||||||
| import org.springframework.security.oauth2.client.ClientAuthorizationException; |  | ||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.core.ClientAuthenticationMethod; | import org.springframework.security.oauth2.core.ClientAuthenticationMethod; | ||||||
| import org.springframework.security.oauth2.core.OAuth2AuthorizationException; |  | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; | import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; | ||||||
| import org.springframework.util.Assert; | import org.springframework.util.Assert; | ||||||
| @ -167,38 +165,9 @@ abstract class AbstractWebClientReactiveOAuth2AccessTokenResponseClient<T extend | |||||||
| 	 */ | 	 */ | ||||||
| 	private Mono<OAuth2AccessTokenResponse> readTokenResponse(T grantRequest, ClientResponse response) { | 	private Mono<OAuth2AccessTokenResponse> readTokenResponse(T grantRequest, ClientResponse response) { | ||||||
| 		return response.body(oauth2AccessTokenResponse()) | 		return response.body(oauth2AccessTokenResponse()) | ||||||
| 				.onErrorMap(OAuth2AuthorizationException.class, e -> createClientAuthorizationException( |  | ||||||
| 						response, |  | ||||||
| 						clientRegistration(grantRequest).getRegistrationId(), |  | ||||||
| 						e)) |  | ||||||
| 				.map(tokenResponse -> populateTokenResponse(grantRequest, tokenResponse)); | 				.map(tokenResponse -> populateTokenResponse(grantRequest, tokenResponse)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** |  | ||||||
| 	 * Wraps the given {@link OAuth2AuthorizationException} in a {@link ClientAuthorizationException} |  | ||||||
| 	 * that provides response details, and a more descriptive exception message. |  | ||||||
| 	 * |  | ||||||
| 	 * @param response the token response |  | ||||||
| 	 * @param clientRegistrationId the id of the {@link ClientRegistration} for which a token is being requested |  | ||||||
| 	 * @param authorizationException the {@link OAuth2AuthorizationException} to wrap |  | ||||||
| 	 * @return the {@link ClientAuthorizationException} that wraps the given {@link OAuth2AuthorizationException} |  | ||||||
| 	 */ |  | ||||||
| 	private OAuth2AuthorizationException createClientAuthorizationException( |  | ||||||
| 			ClientResponse response, |  | ||||||
| 			String clientRegistrationId, |  | ||||||
| 			OAuth2AuthorizationException authorizationException) { |  | ||||||
| 
 |  | ||||||
| 		String message = String.format("Error retrieving OAuth 2.0 Access Token (HTTP Status Code: %s) %s", |  | ||||||
| 				response.rawStatusCode(), |  | ||||||
| 				authorizationException.getError()); |  | ||||||
| 
 |  | ||||||
| 		return new ClientAuthorizationException( |  | ||||||
| 				authorizationException.getError(), |  | ||||||
| 				clientRegistrationId, |  | ||||||
| 				message, |  | ||||||
| 				authorizationException); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Populates the given {@link OAuth2AccessTokenResponse} with additional details | 	 * Populates the given {@link OAuth2AccessTokenResponse} with additional details | ||||||
| 	 * from the grant request. | 	 * from the grant request. | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2020 the original author or authors. |  * Copyright 2002-2018 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -20,9 +20,9 @@ import org.springframework.http.RequestEntity; | |||||||
| import org.springframework.http.ResponseEntity; | import org.springframework.http.ResponseEntity; | ||||||
| import org.springframework.http.converter.FormHttpMessageConverter; | import org.springframework.http.converter.FormHttpMessageConverter; | ||||||
| import org.springframework.http.converter.HttpMessageConverter; | import org.springframework.http.converter.HttpMessageConverter; | ||||||
| import org.springframework.security.oauth2.client.ClientAuthorizationException; |  | ||||||
| import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler; | import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler; | ||||||
| import org.springframework.security.oauth2.core.AuthorizationGrantType; | import org.springframework.security.oauth2.core.AuthorizationGrantType; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
| import org.springframework.security.oauth2.core.OAuth2Error; | import org.springframework.security.oauth2.core.OAuth2Error; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | ||||||
| import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter; | import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter; | ||||||
| @ -30,7 +30,6 @@ import org.springframework.util.Assert; | |||||||
| import org.springframework.util.CollectionUtils; | import org.springframework.util.CollectionUtils; | ||||||
| import org.springframework.web.client.ResponseErrorHandler; | import org.springframework.web.client.ResponseErrorHandler; | ||||||
| import org.springframework.web.client.RestClientException; | import org.springframework.web.client.RestClientException; | ||||||
| import org.springframework.web.client.RestClientResponseException; |  | ||||||
| import org.springframework.web.client.RestOperations; | import org.springframework.web.client.RestOperations; | ||||||
| import org.springframework.web.client.RestTemplate; | import org.springframework.web.client.RestTemplate; | ||||||
| 
 | 
 | ||||||
| @ -75,22 +74,9 @@ public final class DefaultAuthorizationCodeTokenResponseClient implements OAuth2 | |||||||
| 		try { | 		try { | ||||||
| 			response = this.restOperations.exchange(request, OAuth2AccessTokenResponse.class); | 			response = this.restOperations.exchange(request, OAuth2AccessTokenResponse.class); | ||||||
| 		} catch (RestClientException ex) { | 		} catch (RestClientException ex) { | ||||||
| 			int statusCode = 500; | 			OAuth2Error oauth2Error = new OAuth2Error(INVALID_TOKEN_RESPONSE_ERROR_CODE, | ||||||
| 			if (ex instanceof RestClientResponseException) { | 					"An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + ex.getMessage(), null); | ||||||
| 				statusCode = ((RestClientResponseException) ex).getRawStatusCode(); | 			throw new OAuth2AuthorizationException(oauth2Error, ex); | ||||||
| 			} |  | ||||||
| 			OAuth2Error oauth2Error = new OAuth2Error( |  | ||||||
| 					INVALID_TOKEN_RESPONSE_ERROR_CODE, |  | ||||||
| 					"An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + ex.getMessage(), |  | ||||||
| 					null); |  | ||||||
| 			String message = String.format("Error retrieving OAuth 2.0 Access Token (HTTP Status Code: %s) %s", |  | ||||||
| 					statusCode, |  | ||||||
| 					oauth2Error); |  | ||||||
| 			throw new ClientAuthorizationException( |  | ||||||
| 					oauth2Error, |  | ||||||
| 					authorizationCodeGrantRequest.getClientRegistration().getRegistrationId(), |  | ||||||
| 					message, |  | ||||||
| 					ex); |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		OAuth2AccessTokenResponse tokenResponse = response.getBody(); | 		OAuth2AccessTokenResponse tokenResponse = response.getBody(); | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2020 the original author or authors. |  * Copyright 2002-2018 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -20,9 +20,9 @@ import org.springframework.http.RequestEntity; | |||||||
| import org.springframework.http.ResponseEntity; | import org.springframework.http.ResponseEntity; | ||||||
| import org.springframework.http.converter.FormHttpMessageConverter; | import org.springframework.http.converter.FormHttpMessageConverter; | ||||||
| import org.springframework.http.converter.HttpMessageConverter; | import org.springframework.http.converter.HttpMessageConverter; | ||||||
| import org.springframework.security.oauth2.client.ClientAuthorizationException; |  | ||||||
| import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler; | import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler; | ||||||
| import org.springframework.security.oauth2.core.AuthorizationGrantType; | import org.springframework.security.oauth2.core.AuthorizationGrantType; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
| import org.springframework.security.oauth2.core.OAuth2Error; | import org.springframework.security.oauth2.core.OAuth2Error; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | ||||||
| import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter; | import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter; | ||||||
| @ -30,7 +30,6 @@ import org.springframework.util.Assert; | |||||||
| import org.springframework.util.CollectionUtils; | import org.springframework.util.CollectionUtils; | ||||||
| import org.springframework.web.client.ResponseErrorHandler; | import org.springframework.web.client.ResponseErrorHandler; | ||||||
| import org.springframework.web.client.RestClientException; | import org.springframework.web.client.RestClientException; | ||||||
| import org.springframework.web.client.RestClientResponseException; |  | ||||||
| import org.springframework.web.client.RestOperations; | import org.springframework.web.client.RestOperations; | ||||||
| import org.springframework.web.client.RestTemplate; | import org.springframework.web.client.RestTemplate; | ||||||
| 
 | 
 | ||||||
| @ -75,22 +74,9 @@ public final class DefaultClientCredentialsTokenResponseClient implements OAuth2 | |||||||
| 		try { | 		try { | ||||||
| 			response = this.restOperations.exchange(request, OAuth2AccessTokenResponse.class); | 			response = this.restOperations.exchange(request, OAuth2AccessTokenResponse.class); | ||||||
| 		} catch (RestClientException ex) { | 		} catch (RestClientException ex) { | ||||||
| 			int statusCode = 500; | 			OAuth2Error oauth2Error = new OAuth2Error(INVALID_TOKEN_RESPONSE_ERROR_CODE, | ||||||
| 			if (ex instanceof RestClientResponseException) { | 					"An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + ex.getMessage(), null); | ||||||
| 				statusCode = ((RestClientResponseException) ex).getRawStatusCode(); | 			throw new OAuth2AuthorizationException(oauth2Error, ex); | ||||||
| 			} |  | ||||||
| 			OAuth2Error oauth2Error = new OAuth2Error( |  | ||||||
| 					INVALID_TOKEN_RESPONSE_ERROR_CODE, |  | ||||||
| 					"An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + ex.getMessage(), |  | ||||||
| 					null); |  | ||||||
| 			String message = String.format("Error retrieving OAuth 2.0 Access Token (HTTP Status Code: %s) %s", |  | ||||||
| 					statusCode, |  | ||||||
| 					oauth2Error); |  | ||||||
| 			throw new ClientAuthorizationException( |  | ||||||
| 					oauth2Error, |  | ||||||
| 					clientCredentialsGrantRequest.getClientRegistration().getRegistrationId(), |  | ||||||
| 					message, |  | ||||||
| 					ex); |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		OAuth2AccessTokenResponse tokenResponse = response.getBody(); | 		OAuth2AccessTokenResponse tokenResponse = response.getBody(); | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2020 the original author or authors. |  * Copyright 2002-2019 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -20,9 +20,9 @@ import org.springframework.http.RequestEntity; | |||||||
| import org.springframework.http.ResponseEntity; | import org.springframework.http.ResponseEntity; | ||||||
| import org.springframework.http.converter.FormHttpMessageConverter; | import org.springframework.http.converter.FormHttpMessageConverter; | ||||||
| import org.springframework.http.converter.HttpMessageConverter; | import org.springframework.http.converter.HttpMessageConverter; | ||||||
| import org.springframework.security.oauth2.client.ClientAuthorizationException; |  | ||||||
| import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler; | import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler; | ||||||
| import org.springframework.security.oauth2.core.AuthorizationGrantType; | import org.springframework.security.oauth2.core.AuthorizationGrantType; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
| import org.springframework.security.oauth2.core.OAuth2Error; | import org.springframework.security.oauth2.core.OAuth2Error; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | ||||||
| import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter; | import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter; | ||||||
| @ -30,7 +30,6 @@ import org.springframework.util.Assert; | |||||||
| import org.springframework.util.CollectionUtils; | import org.springframework.util.CollectionUtils; | ||||||
| import org.springframework.web.client.ResponseErrorHandler; | import org.springframework.web.client.ResponseErrorHandler; | ||||||
| import org.springframework.web.client.RestClientException; | import org.springframework.web.client.RestClientException; | ||||||
| import org.springframework.web.client.RestClientResponseException; |  | ||||||
| import org.springframework.web.client.RestOperations; | import org.springframework.web.client.RestOperations; | ||||||
| import org.springframework.web.client.RestTemplate; | import org.springframework.web.client.RestTemplate; | ||||||
| 
 | 
 | ||||||
| @ -75,22 +74,9 @@ public final class DefaultPasswordTokenResponseClient implements OAuth2AccessTok | |||||||
| 		try { | 		try { | ||||||
| 			response = this.restOperations.exchange(request, OAuth2AccessTokenResponse.class); | 			response = this.restOperations.exchange(request, OAuth2AccessTokenResponse.class); | ||||||
| 		} catch (RestClientException ex) { | 		} catch (RestClientException ex) { | ||||||
| 			int statusCode = 500; | 			OAuth2Error oauth2Error = new OAuth2Error(INVALID_TOKEN_RESPONSE_ERROR_CODE, | ||||||
| 			if (ex instanceof RestClientResponseException) { | 					"An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + ex.getMessage(), null); | ||||||
| 				statusCode = ((RestClientResponseException) ex).getRawStatusCode(); | 			throw new OAuth2AuthorizationException(oauth2Error, ex); | ||||||
| 			} |  | ||||||
| 			OAuth2Error oauth2Error = new OAuth2Error( |  | ||||||
| 					INVALID_TOKEN_RESPONSE_ERROR_CODE, |  | ||||||
| 					"An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + ex.getMessage(), |  | ||||||
| 					null); |  | ||||||
| 			String message = String.format("Error retrieving OAuth 2.0 Access Token (HTTP Status Code: %s) %s", |  | ||||||
| 					statusCode, |  | ||||||
| 					oauth2Error); |  | ||||||
| 			throw new ClientAuthorizationException( |  | ||||||
| 					oauth2Error, |  | ||||||
| 					passwordGrantRequest.getClientRegistration().getRegistrationId(), |  | ||||||
| 					message, |  | ||||||
| 					ex); |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		OAuth2AccessTokenResponse tokenResponse = response.getBody(); | 		OAuth2AccessTokenResponse tokenResponse = response.getBody(); | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2020 the original author or authors. |  * Copyright 2002-2019 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -20,9 +20,9 @@ import org.springframework.http.RequestEntity; | |||||||
| import org.springframework.http.ResponseEntity; | import org.springframework.http.ResponseEntity; | ||||||
| import org.springframework.http.converter.FormHttpMessageConverter; | import org.springframework.http.converter.FormHttpMessageConverter; | ||||||
| import org.springframework.http.converter.HttpMessageConverter; | import org.springframework.http.converter.HttpMessageConverter; | ||||||
| import org.springframework.security.oauth2.client.ClientAuthorizationException; |  | ||||||
| import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler; | import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler; | ||||||
| import org.springframework.security.oauth2.core.AuthorizationGrantType; | import org.springframework.security.oauth2.core.AuthorizationGrantType; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
| import org.springframework.security.oauth2.core.OAuth2Error; | import org.springframework.security.oauth2.core.OAuth2Error; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | ||||||
| import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter; | import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter; | ||||||
| @ -30,7 +30,6 @@ import org.springframework.util.Assert; | |||||||
| import org.springframework.util.CollectionUtils; | import org.springframework.util.CollectionUtils; | ||||||
| import org.springframework.web.client.ResponseErrorHandler; | import org.springframework.web.client.ResponseErrorHandler; | ||||||
| import org.springframework.web.client.RestClientException; | import org.springframework.web.client.RestClientException; | ||||||
| import org.springframework.web.client.RestClientResponseException; |  | ||||||
| import org.springframework.web.client.RestOperations; | import org.springframework.web.client.RestOperations; | ||||||
| import org.springframework.web.client.RestTemplate; | import org.springframework.web.client.RestTemplate; | ||||||
| 
 | 
 | ||||||
| @ -74,22 +73,9 @@ public final class DefaultRefreshTokenTokenResponseClient implements OAuth2Acces | |||||||
| 		try { | 		try { | ||||||
| 			response = this.restOperations.exchange(request, OAuth2AccessTokenResponse.class); | 			response = this.restOperations.exchange(request, OAuth2AccessTokenResponse.class); | ||||||
| 		} catch (RestClientException ex) { | 		} catch (RestClientException ex) { | ||||||
| 			int statusCode = 500; | 			OAuth2Error oauth2Error = new OAuth2Error(INVALID_TOKEN_RESPONSE_ERROR_CODE, | ||||||
| 			if (ex instanceof RestClientResponseException) { | 					"An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + ex.getMessage(), null); | ||||||
| 				statusCode = ((RestClientResponseException) ex).getRawStatusCode(); | 			throw new OAuth2AuthorizationException(oauth2Error, ex); | ||||||
| 			} |  | ||||||
| 			OAuth2Error oauth2Error = new OAuth2Error( |  | ||||||
| 					INVALID_TOKEN_RESPONSE_ERROR_CODE, |  | ||||||
| 					"An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + ex.getMessage(), |  | ||||||
| 					null); |  | ||||||
| 			String message = String.format("Error retrieving OAuth 2.0 Access Token (HTTP Status Code: %s) %s", |  | ||||||
| 					statusCode, |  | ||||||
| 					oauth2Error); |  | ||||||
| 			throw new ClientAuthorizationException( |  | ||||||
| 					oauth2Error, |  | ||||||
| 					refreshTokenGrantRequest.getClientRegistration().getRegistrationId(), |  | ||||||
| 					message, |  | ||||||
| 					ex); |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		OAuth2AccessTokenResponse tokenResponse = response.getBody(); | 		OAuth2AccessTokenResponse tokenResponse = response.getBody(); | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2020 the original author or authors. |  * Copyright 2002-2018 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -31,10 +31,10 @@ import com.nimbusds.oauth2.sdk.auth.Secret; | |||||||
| import com.nimbusds.oauth2.sdk.http.HTTPRequest; | import com.nimbusds.oauth2.sdk.http.HTTPRequest; | ||||||
| import com.nimbusds.oauth2.sdk.id.ClientID; | import com.nimbusds.oauth2.sdk.id.ClientID; | ||||||
| import org.springframework.http.MediaType; | import org.springframework.http.MediaType; | ||||||
| import org.springframework.security.oauth2.client.ClientAuthorizationException; |  | ||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.core.ClientAuthenticationMethod; | import org.springframework.security.oauth2.core.ClientAuthenticationMethod; | ||||||
| import org.springframework.security.oauth2.core.OAuth2AccessToken; | import org.springframework.security.oauth2.core.OAuth2AccessToken; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
| import org.springframework.security.oauth2.core.OAuth2Error; | import org.springframework.security.oauth2.core.OAuth2Error; | ||||||
| import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | ||||||
| @ -100,19 +100,9 @@ public class NimbusAuthorizationCodeTokenResponseClient implements OAuth2AccessT | |||||||
| 			httpRequest.setReadTimeout(30000); | 			httpRequest.setReadTimeout(30000); | ||||||
| 			tokenResponse = com.nimbusds.oauth2.sdk.TokenResponse.parse(httpRequest.send()); | 			tokenResponse = com.nimbusds.oauth2.sdk.TokenResponse.parse(httpRequest.send()); | ||||||
| 		} catch (ParseException | IOException ex) { | 		} catch (ParseException | IOException ex) { | ||||||
| 			int statusCode = 500; | 			OAuth2Error oauth2Error = new OAuth2Error(INVALID_TOKEN_RESPONSE_ERROR_CODE, | ||||||
| 			OAuth2Error oauth2Error = new OAuth2Error( | 					"An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + ex.getMessage(), null); | ||||||
| 					INVALID_TOKEN_RESPONSE_ERROR_CODE, | 			throw new OAuth2AuthorizationException(oauth2Error, ex); | ||||||
| 					"An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + ex.getMessage(), |  | ||||||
| 					null); |  | ||||||
| 			String message = String.format("Error retrieving OAuth 2.0 Access Token (HTTP Status Code: %s) %s", |  | ||||||
| 					statusCode, |  | ||||||
| 					oauth2Error); |  | ||||||
| 			throw new ClientAuthorizationException( |  | ||||||
| 					oauth2Error, |  | ||||||
| 					clientRegistration.getRegistrationId(), |  | ||||||
| 					message, |  | ||||||
| 					ex); |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (!tokenResponse.indicatesSuccess()) { | 		if (!tokenResponse.indicatesSuccess()) { | ||||||
| @ -127,7 +117,7 @@ public class NimbusAuthorizationCodeTokenResponseClient implements OAuth2AccessT | |||||||
| 						errorObject.getDescription(), | 						errorObject.getDescription(), | ||||||
| 						errorObject.getURI() != null ? errorObject.getURI().toString() : null); | 						errorObject.getURI() != null ? errorObject.getURI().toString() : null); | ||||||
| 			} | 			} | ||||||
| 			throw new ClientAuthorizationException(oauth2Error, clientRegistration.getRegistrationId()); | 			throw new OAuth2AuthorizationException(oauth2Error); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		AccessTokenResponse accessTokenResponse = (AccessTokenResponse) tokenResponse; | 		AccessTokenResponse accessTokenResponse = (AccessTokenResponse) tokenResponse; | ||||||
|  | |||||||
| @ -25,6 +25,7 @@ import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest; | |||||||
| import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; | import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; | ||||||
| import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; | import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; | ||||||
| import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider; | import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider; | ||||||
|  | import org.springframework.security.oauth2.client.RemoveAuthorizedClientOAuth2AuthorizationFailureHandler; | ||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; | import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; | ||||||
| import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
| @ -102,8 +103,15 @@ public final class DefaultOAuth2AuthorizedClientManager implements OAuth2Authori | |||||||
| 		this.clientRegistrationRepository = clientRegistrationRepository; | 		this.clientRegistrationRepository = clientRegistrationRepository; | ||||||
| 		this.authorizedClientRepository = authorizedClientRepository; | 		this.authorizedClientRepository = authorizedClientRepository; | ||||||
| 		this.contextAttributesMapper = new DefaultContextAttributesMapper(); | 		this.contextAttributesMapper = new DefaultContextAttributesMapper(); | ||||||
| 		this.authorizationSuccessHandler = new SaveAuthorizedClientOAuth2AuthorizationSuccessHandler(authorizedClientRepository); | 		this.authorizationSuccessHandler = (authorizedClient, principal, attributes) -> | ||||||
| 		this.authorizationFailureHandler = new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler(authorizedClientRepository); | 				authorizedClientRepository.saveAuthorizedClient(authorizedClient, principal, | ||||||
|  | 						(HttpServletRequest) attributes.get(HttpServletRequest.class.getName()), | ||||||
|  | 						(HttpServletResponse) attributes.get(HttpServletResponse.class.getName())); | ||||||
|  | 		this.authorizationFailureHandler = new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler( | ||||||
|  | 				(clientRegistrationId, principal, attributes) -> | ||||||
|  | 						authorizedClientRepository.removeAuthorizedClient(clientRegistrationId, principal, | ||||||
|  | 								(HttpServletRequest) attributes.get(HttpServletRequest.class.getName()), | ||||||
|  | 								(HttpServletResponse) attributes.get(HttpServletResponse.class.getName()))); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Nullable | 	@Nullable | ||||||
| @ -221,10 +229,9 @@ public final class DefaultOAuth2AuthorizedClientManager implements OAuth2Authori | |||||||
| 	 * Sets the {@link OAuth2AuthorizationSuccessHandler} that handles successful authorizations. | 	 * Sets the {@link OAuth2AuthorizationSuccessHandler} that handles successful authorizations. | ||||||
| 	 * | 	 * | ||||||
| 	 * <p> | 	 * <p> | ||||||
| 	 * A {@link SaveAuthorizedClientOAuth2AuthorizationSuccessHandler} is used by default. | 	 * The default saves {@link OAuth2AuthorizedClient}s in the {@link OAuth2AuthorizedClientRepository}. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param authorizationSuccessHandler the {@link OAuth2AuthorizationSuccessHandler} that handles successful authorizations | 	 * @param authorizationSuccessHandler the {@link OAuth2AuthorizationSuccessHandler} that handles successful authorizations | ||||||
| 	 * @see SaveAuthorizedClientOAuth2AuthorizationSuccessHandler |  | ||||||
| 	 * @since 5.3 | 	 * @since 5.3 | ||||||
| 	 */ | 	 */ | ||||||
| 	public void setAuthorizationSuccessHandler(OAuth2AuthorizationSuccessHandler authorizationSuccessHandler) { | 	public void setAuthorizationSuccessHandler(OAuth2AuthorizationSuccessHandler authorizationSuccessHandler) { | ||||||
|  | |||||||
| @ -23,6 +23,7 @@ import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizationFai | |||||||
| import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizationSuccessHandler; | import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizationSuccessHandler; | ||||||
| import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientManager; | import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientManager; | ||||||
| import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProvider; | import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProvider; | ||||||
|  | import org.springframework.security.oauth2.client.RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler; | ||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; | import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; | ||||||
| import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; | import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; | ||||||
| @ -101,8 +102,13 @@ public final class DefaultReactiveOAuth2AuthorizedClientManager implements React | |||||||
| 		Assert.notNull(authorizedClientRepository, "authorizedClientRepository cannot be null"); | 		Assert.notNull(authorizedClientRepository, "authorizedClientRepository cannot be null"); | ||||||
| 		this.clientRegistrationRepository = clientRegistrationRepository; | 		this.clientRegistrationRepository = clientRegistrationRepository; | ||||||
| 		this.authorizedClientRepository = authorizedClientRepository; | 		this.authorizedClientRepository = authorizedClientRepository; | ||||||
| 		this.authorizationSuccessHandler = new SaveAuthorizedClientReactiveOAuth2AuthorizationSuccessHandler(authorizedClientRepository); | 		this.authorizationSuccessHandler = (authorizedClient, principal, attributes) -> | ||||||
| 		this.authorizationFailureHandler = new RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler(authorizedClientRepository); | 				authorizedClientRepository.saveAuthorizedClient(authorizedClient, principal, | ||||||
|  | 						(ServerWebExchange) attributes.get(ServerWebExchange.class.getName())); | ||||||
|  | 		this.authorizationFailureHandler = new RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler( | ||||||
|  | 				(clientRegistrationId, principal, attributes) -> | ||||||
|  | 						authorizedClientRepository.removeAuthorizedClient(clientRegistrationId, principal, | ||||||
|  | 								(ServerWebExchange) attributes.get(ServerWebExchange.class.getName()))); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
| @ -230,11 +236,9 @@ public final class DefaultReactiveOAuth2AuthorizedClientManager implements React | |||||||
| 	/** | 	/** | ||||||
| 	 * Sets the handler that handles successful authorizations. | 	 * Sets the handler that handles successful authorizations. | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>A {@link SaveAuthorizedClientReactiveOAuth2AuthorizationSuccessHandler} | 	 * The default saves {@link OAuth2AuthorizedClient}s in the {@link ServerOAuth2AuthorizedClientRepository}. | ||||||
| 	 * is used by default.</p> |  | ||||||
| 	 * | 	 * | ||||||
| 	 * @param authorizationSuccessHandler the handler that handles successful authorizations. | 	 * @param authorizationSuccessHandler the handler that handles successful authorizations. | ||||||
| 	 * @see SaveAuthorizedClientReactiveOAuth2AuthorizationSuccessHandler |  | ||||||
| 	 * @since 5.3 | 	 * @since 5.3 | ||||||
| 	 */ | 	 */ | ||||||
| 	public void setAuthorizationSuccessHandler(ReactiveOAuth2AuthorizationSuccessHandler authorizationSuccessHandler) { | 	public void setAuthorizationSuccessHandler(ReactiveOAuth2AuthorizationSuccessHandler authorizationSuccessHandler) { | ||||||
|  | |||||||
| @ -1,77 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Copyright 2002-2020 the original author or authors. |  | ||||||
|  * |  | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  | ||||||
|  * you may not use this file except in compliance with the License. |  | ||||||
|  * You may obtain a copy of the License at |  | ||||||
|  * |  | ||||||
|  *      https://www.apache.org/licenses/LICENSE-2.0 |  | ||||||
|  * |  | ||||||
|  * Unless required by applicable law or agreed to in writing, software |  | ||||||
|  * distributed under the License is distributed on an "AS IS" BASIS, |  | ||||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||||
|  * See the License for the specific language governing permissions and |  | ||||||
|  * limitations under the License. |  | ||||||
|  */ |  | ||||||
| package org.springframework.security.oauth2.client.web; |  | ||||||
| 
 |  | ||||||
| import org.springframework.security.core.Authentication; |  | ||||||
| import org.springframework.security.oauth2.client.OAuth2AuthorizationSuccessHandler; |  | ||||||
| import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; |  | ||||||
| import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; |  | ||||||
| import org.springframework.util.Assert; |  | ||||||
| 
 |  | ||||||
| import javax.servlet.http.HttpServletRequest; |  | ||||||
| import javax.servlet.http.HttpServletResponse; |  | ||||||
| import java.util.Map; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * An {@link OAuth2AuthorizationSuccessHandler} that saves an {@link OAuth2AuthorizedClient} |  | ||||||
|  * in an {@link OAuth2AuthorizedClientRepository} or {@link OAuth2AuthorizedClientService}. |  | ||||||
|  * |  | ||||||
|  * @author Joe Grandja |  | ||||||
|  * @since 5.3 |  | ||||||
|  * @see OAuth2AuthorizedClient |  | ||||||
|  * @see OAuth2AuthorizedClientRepository |  | ||||||
|  * @see OAuth2AuthorizedClientService |  | ||||||
|  */ |  | ||||||
| public class SaveAuthorizedClientOAuth2AuthorizationSuccessHandler implements OAuth2AuthorizationSuccessHandler { |  | ||||||
| 
 |  | ||||||
| 	/** |  | ||||||
| 	 * A delegate that saves an {@link OAuth2AuthorizedClient} in an |  | ||||||
| 	 * {@link OAuth2AuthorizedClientRepository} or {@link OAuth2AuthorizedClientService}. |  | ||||||
| 	 */ |  | ||||||
| 	private final OAuth2AuthorizationSuccessHandler delegate; |  | ||||||
| 
 |  | ||||||
| 	/** |  | ||||||
| 	 * Constructs a {@code SaveAuthorizedClientOAuth2AuthorizationSuccessHandler} using the provided parameters. |  | ||||||
| 	 * |  | ||||||
| 	 * @param authorizedClientRepository The repository in which authorized clients will be saved. |  | ||||||
| 	 */ |  | ||||||
| 	public SaveAuthorizedClientOAuth2AuthorizationSuccessHandler( |  | ||||||
| 			OAuth2AuthorizedClientRepository authorizedClientRepository) { |  | ||||||
| 		Assert.notNull(authorizedClientRepository, "authorizedClientRepository cannot be null"); |  | ||||||
| 		this.delegate = (authorizedClient, principal, attributes) -> |  | ||||||
| 				authorizedClientRepository.saveAuthorizedClient(authorizedClient, principal, |  | ||||||
| 						(HttpServletRequest) attributes.get(HttpServletRequest.class.getName()), |  | ||||||
| 						(HttpServletResponse) attributes.get(HttpServletResponse.class.getName())); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/** |  | ||||||
| 	 * Constructs a {@code SaveAuthorizedClientOAuth2AuthorizationSuccessHandler} using the provided parameters. |  | ||||||
| 	 * |  | ||||||
| 	 * @param authorizedClientService The service in which authorized clients will be saved. |  | ||||||
| 	 */ |  | ||||||
| 	public SaveAuthorizedClientOAuth2AuthorizationSuccessHandler( |  | ||||||
| 			OAuth2AuthorizedClientService authorizedClientService) { |  | ||||||
| 		Assert.notNull(authorizedClientService, "authorizedClientService cannot be null"); |  | ||||||
| 		this.delegate = (authorizedClient, principal, attributes) -> |  | ||||||
| 				authorizedClientService.saveAuthorizedClient(authorizedClient, principal); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	@Override |  | ||||||
| 	public void onAuthorizationSuccess(OAuth2AuthorizedClient authorizedClient, |  | ||||||
| 			Authentication principal, Map<String, Object> attributes) { |  | ||||||
| 		this.delegate.onAuthorizationSuccess(authorizedClient, principal, attributes); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @ -1,80 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Copyright 2002-2020 the original author or authors. |  | ||||||
|  * |  | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  | ||||||
|  * you may not use this file except in compliance with the License. |  | ||||||
|  * You may obtain a copy of the License at |  | ||||||
|  * |  | ||||||
|  *      https://www.apache.org/licenses/LICENSE-2.0 |  | ||||||
|  * |  | ||||||
|  * Unless required by applicable law or agreed to in writing, software |  | ||||||
|  * distributed under the License is distributed on an "AS IS" BASIS, |  | ||||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||||
|  * See the License for the specific language governing permissions and |  | ||||||
|  * limitations under the License. |  | ||||||
|  */ |  | ||||||
| package org.springframework.security.oauth2.client.web; |  | ||||||
| 
 |  | ||||||
| import org.springframework.security.core.Authentication; |  | ||||||
| import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; |  | ||||||
| import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizationSuccessHandler; |  | ||||||
| import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientService; |  | ||||||
| import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; |  | ||||||
| import org.springframework.util.Assert; |  | ||||||
| import org.springframework.web.server.ServerWebExchange; |  | ||||||
| import reactor.core.publisher.Mono; |  | ||||||
| 
 |  | ||||||
| import java.util.Map; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * An authorization success handler that saves authorized clients in a |  | ||||||
|  * {@link ServerOAuth2AuthorizedClientRepository} |  | ||||||
|  * or a {@link ReactiveOAuth2AuthorizedClientService}. |  | ||||||
|  * |  | ||||||
|  * @author Phil Clay |  | ||||||
|  * @since 5.3 |  | ||||||
|  */ |  | ||||||
| public class SaveAuthorizedClientReactiveOAuth2AuthorizationSuccessHandler implements ReactiveOAuth2AuthorizationSuccessHandler { |  | ||||||
| 
 |  | ||||||
| 	/** |  | ||||||
| 	 * A delegate that saves clients in either a |  | ||||||
| 	 * {@link ServerOAuth2AuthorizedClientRepository} |  | ||||||
| 	 * or a |  | ||||||
| 	 * {@link ReactiveOAuth2AuthorizedClientService}. |  | ||||||
| 	 */ |  | ||||||
| 	private final ReactiveOAuth2AuthorizationSuccessHandler delegate; |  | ||||||
| 
 |  | ||||||
| 	/** |  | ||||||
| 	 * @param authorizedClientRepository The repository in which authorized clients will be saved. |  | ||||||
| 	 */ |  | ||||||
| 	public SaveAuthorizedClientReactiveOAuth2AuthorizationSuccessHandler(final ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { |  | ||||||
| 		Assert.notNull(authorizedClientRepository, "authorizedClientRepository cannot be null"); |  | ||||||
| 		this.delegate = (authorizedClient, principal, attributes) -> |  | ||||||
| 				authorizedClientRepository.saveAuthorizedClient( |  | ||||||
| 						authorizedClient, |  | ||||||
| 						principal, |  | ||||||
| 						(ServerWebExchange) attributes.get(ServerWebExchange.class.getName())); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/** |  | ||||||
| 	 * @param authorizedClientService The service in which authorized clients will be saved. |  | ||||||
| 	 */ |  | ||||||
| 	public SaveAuthorizedClientReactiveOAuth2AuthorizationSuccessHandler(final ReactiveOAuth2AuthorizedClientService authorizedClientService) { |  | ||||||
| 		Assert.notNull(authorizedClientService, "authorizedClientService cannot be null"); |  | ||||||
| 		this.delegate = (authorizedClient, principal, attributes) -> |  | ||||||
| 				authorizedClientService.saveAuthorizedClient( |  | ||||||
| 						authorizedClient, |  | ||||||
| 						principal); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	@Override |  | ||||||
| 	public Mono<Void> onAuthorizationSuccess( |  | ||||||
| 			OAuth2AuthorizedClient authorizedClient, |  | ||||||
| 			Authentication principal, |  | ||||||
| 			Map<String, Object> attributes) { |  | ||||||
| 		return this.delegate.onAuthorizationSuccess( |  | ||||||
| 				authorizedClient, |  | ||||||
| 				principal, |  | ||||||
| 				attributes); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @ -34,14 +34,13 @@ import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClient | |||||||
| import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProvider; | import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProvider; | ||||||
| import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProviderBuilder; | import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProviderBuilder; | ||||||
| import org.springframework.security.oauth2.client.RefreshTokenReactiveOAuth2AuthorizedClientProvider; | import org.springframework.security.oauth2.client.RefreshTokenReactiveOAuth2AuthorizedClientProvider; | ||||||
|  | import org.springframework.security.oauth2.client.RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler; | ||||||
| import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; | import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; | ||||||
| import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentialsGrantRequest; | import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentialsGrantRequest; | ||||||
| import org.springframework.security.oauth2.client.endpoint.ReactiveOAuth2AccessTokenResponseClient; | import org.springframework.security.oauth2.client.endpoint.ReactiveOAuth2AccessTokenResponseClient; | ||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; | import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; | ||||||
| import org.springframework.security.oauth2.client.web.DefaultReactiveOAuth2AuthorizedClientManager; | import org.springframework.security.oauth2.client.web.DefaultReactiveOAuth2AuthorizedClientManager; | ||||||
| import org.springframework.security.oauth2.client.web.RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler; |  | ||||||
| import org.springframework.security.oauth2.client.web.SaveAuthorizedClientReactiveOAuth2AuthorizationSuccessHandler; |  | ||||||
| import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; | import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; | ||||||
| import org.springframework.security.oauth2.client.web.server.UnAuthenticatedServerOAuth2AuthorizedClientRepository; | import org.springframework.security.oauth2.client.web.server.UnAuthenticatedServerOAuth2AuthorizedClientRepository; | ||||||
| import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
| @ -191,7 +190,10 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements | |||||||
| 																ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { | 																ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { | ||||||
| 
 | 
 | ||||||
| 		ReactiveOAuth2AuthorizationFailureHandler authorizationFailureHandler = | 		ReactiveOAuth2AuthorizationFailureHandler authorizationFailureHandler = | ||||||
| 				new RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler(authorizedClientRepository); | 				new RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler( | ||||||
|  | 						(clientRegistrationId, principal, attributes) -> | ||||||
|  | 								authorizedClientRepository.removeAuthorizedClient(clientRegistrationId, principal, | ||||||
|  | 										(ServerWebExchange) attributes.get(ServerWebExchange.class.getName()))); | ||||||
| 
 | 
 | ||||||
| 		this.authorizedClientManager = createDefaultAuthorizedClientManager( | 		this.authorizedClientManager = createDefaultAuthorizedClientManager( | ||||||
| 				clientRegistrationRepository, | 				clientRegistrationRepository, | ||||||
| @ -518,7 +520,9 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements | |||||||
| 				ReactiveOAuth2AuthorizationFailureHandler authorizationFailureHandler) { | 				ReactiveOAuth2AuthorizationFailureHandler authorizationFailureHandler) { | ||||||
| 			this.clientRegistrationRepository = clientRegistrationRepository; | 			this.clientRegistrationRepository = clientRegistrationRepository; | ||||||
| 			this.authorizedClientRepository = authorizedClientRepository; | 			this.authorizedClientRepository = authorizedClientRepository; | ||||||
| 			this.authorizationSuccessHandler = new SaveAuthorizedClientReactiveOAuth2AuthorizationSuccessHandler(authorizedClientRepository); | 			this.authorizationSuccessHandler = (authorizedClient, principal, attributes) -> | ||||||
|  | 					authorizedClientRepository.saveAuthorizedClient(authorizedClient, principal, | ||||||
|  | 							(ServerWebExchange) attributes.get(ServerWebExchange.class.getName())); | ||||||
| 			this.authorizationFailureHandler = authorizationFailureHandler; | 			this.authorizationFailureHandler = authorizationFailureHandler; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -31,6 +31,7 @@ import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; | |||||||
| import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider; | import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider; | ||||||
| import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder; | import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder; | ||||||
| import org.springframework.security.oauth2.client.RefreshTokenOAuth2AuthorizedClientProvider; | import org.springframework.security.oauth2.client.RefreshTokenOAuth2AuthorizedClientProvider; | ||||||
|  | import org.springframework.security.oauth2.client.RemoveAuthorizedClientOAuth2AuthorizationFailureHandler; | ||||||
| import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; | import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; | ||||||
| import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient; | import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient; | ||||||
| import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentialsGrantRequest; | import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentialsGrantRequest; | ||||||
| @ -38,7 +39,6 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio | |||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; | import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; | ||||||
| import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager; | import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager; | ||||||
| import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository; | import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository; | ||||||
| import org.springframework.security.oauth2.client.web.RemoveAuthorizedClientOAuth2AuthorizationFailureHandler; |  | ||||||
| import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
| import org.springframework.security.oauth2.core.OAuth2Error; | import org.springframework.security.oauth2.core.OAuth2Error; | ||||||
| import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | ||||||
| @ -212,8 +212,11 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement | |||||||
| 			OAuth2AuthorizedClientRepository authorizedClientRepository) { | 			OAuth2AuthorizedClientRepository authorizedClientRepository) { | ||||||
| 
 | 
 | ||||||
| 		OAuth2AuthorizationFailureHandler authorizationFailureHandler = | 		OAuth2AuthorizationFailureHandler authorizationFailureHandler = | ||||||
| 				new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler(authorizedClientRepository); | 				new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler( | ||||||
| 
 | 						(clientRegistrationId, principal, attributes) -> | ||||||
|  | 								authorizedClientRepository.removeAuthorizedClient(clientRegistrationId, principal, | ||||||
|  | 										(HttpServletRequest) attributes.get(HttpServletRequest.class.getName()), | ||||||
|  | 										(HttpServletResponse) attributes.get(HttpServletResponse.class.getName()))); | ||||||
| 		this.authorizedClientManager = createDefaultAuthorizedClientManager( | 		this.authorizedClientManager = createDefaultAuthorizedClientManager( | ||||||
| 				clientRegistrationRepository, authorizedClientRepository, authorizationFailureHandler); | 				clientRegistrationRepository, authorizedClientRepository, authorizationFailureHandler); | ||||||
| 		this.defaultAuthorizedClientManager = true; | 		this.defaultAuthorizedClientManager = true; | ||||||
|  | |||||||
| @ -23,14 +23,13 @@ import org.springframework.security.core.Authentication; | |||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; | import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; | ||||||
| import org.springframework.security.oauth2.client.registration.TestClientRegistrations; | import org.springframework.security.oauth2.client.registration.TestClientRegistrations; | ||||||
| import org.springframework.security.oauth2.client.web.RemoveAuthorizedClientOAuth2AuthorizationFailureHandler; |  | ||||||
| import org.springframework.security.oauth2.client.web.SaveAuthorizedClientOAuth2AuthorizationSuccessHandler; |  | ||||||
| import org.springframework.security.oauth2.core.OAuth2Error; | import org.springframework.security.oauth2.core.OAuth2Error; | ||||||
| import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | ||||||
| import org.springframework.security.oauth2.core.TestOAuth2AccessTokens; | import org.springframework.security.oauth2.core.TestOAuth2AccessTokens; | ||||||
| import org.springframework.security.oauth2.core.TestOAuth2RefreshTokens; | import org.springframework.security.oauth2.core.TestOAuth2RefreshTokens; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; | import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; | ||||||
| 
 | 
 | ||||||
|  | import java.util.Map; | ||||||
| import java.util.function.Function; | import java.util.function.Function; | ||||||
| 
 | 
 | ||||||
| import static org.assertj.core.api.Assertions.assertThat; | import static org.assertj.core.api.Assertions.assertThat; | ||||||
| @ -70,8 +69,15 @@ public class AuthorizedClientServiceOAuth2AuthorizedClientManagerTests { | |||||||
| 		this.authorizedClientService = mock(OAuth2AuthorizedClientService.class); | 		this.authorizedClientService = mock(OAuth2AuthorizedClientService.class); | ||||||
| 		this.authorizedClientProvider = mock(OAuth2AuthorizedClientProvider.class); | 		this.authorizedClientProvider = mock(OAuth2AuthorizedClientProvider.class); | ||||||
| 		this.contextAttributesMapper = mock(Function.class); | 		this.contextAttributesMapper = mock(Function.class); | ||||||
| 		this.authorizationSuccessHandler = spy(new SaveAuthorizedClientOAuth2AuthorizationSuccessHandler(this.authorizedClientService)); | 		this.authorizationSuccessHandler = spy(new OAuth2AuthorizationSuccessHandler() { | ||||||
| 		this.authorizationFailureHandler = spy(new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler(this.authorizedClientService)); | 			@Override | ||||||
|  | 			public void onAuthorizationSuccess(OAuth2AuthorizedClient authorizedClient, Authentication principal, Map<String, Object> attributes) { | ||||||
|  | 				authorizedClientService.saveAuthorizedClient(authorizedClient, principal); | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 		this.authorizationFailureHandler = spy(new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler( | ||||||
|  | 				(clientRegistrationId, principal, attributes) -> | ||||||
|  | 						this.authorizedClientService.removeAuthorizedClient(clientRegistrationId, principal.getName()))); | ||||||
| 		this.authorizedClientManager = new AuthorizedClientServiceOAuth2AuthorizedClientManager( | 		this.authorizedClientManager = new AuthorizedClientServiceOAuth2AuthorizedClientManager( | ||||||
| 				this.clientRegistrationRepository, this.authorizedClientService); | 				this.clientRegistrationRepository, this.authorizedClientService); | ||||||
| 		this.authorizedClientManager.setAuthorizedClientProvider(this.authorizedClientProvider); | 		this.authorizedClientManager.setAuthorizedClientProvider(this.authorizedClientProvider); | ||||||
|  | |||||||
| @ -24,10 +24,10 @@ import org.junit.Test; | |||||||
| import org.springframework.http.HttpHeaders; | import org.springframework.http.HttpHeaders; | ||||||
| import org.springframework.http.HttpStatus; | import org.springframework.http.HttpStatus; | ||||||
| import org.springframework.http.MediaType; | import org.springframework.http.MediaType; | ||||||
| import org.springframework.security.oauth2.client.ClientAuthorizationException; |  | ||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.client.registration.TestClientRegistrations; | import org.springframework.security.oauth2.client.registration.TestClientRegistrations; | ||||||
| import org.springframework.security.oauth2.core.OAuth2AccessToken; | import org.springframework.security.oauth2.core.OAuth2AccessToken; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange; | import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; | import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; | ||||||
| @ -41,7 +41,10 @@ import java.util.Map; | |||||||
| 
 | 
 | ||||||
| import static org.assertj.core.api.Assertions.assertThat; | import static org.assertj.core.api.Assertions.assertThat; | ||||||
| import static org.assertj.core.api.Assertions.assertThatThrownBy; | import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||||||
| import static org.mockito.Mockito.*; | import static org.mockito.Mockito.atLeastOnce; | ||||||
|  | import static org.mockito.Mockito.mock; | ||||||
|  | import static org.mockito.Mockito.verify; | ||||||
|  | import static org.mockito.Mockito.when; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * @author Rob Winch |  * @author Rob Winch | ||||||
| @ -178,7 +181,7 @@ public class WebClientReactiveAuthorizationCodeTokenResponseClientTests { | |||||||
| 		this.server.enqueue(jsonResponse(accessTokenErrorResponse).setResponseCode(HttpStatus.INTERNAL_SERVER_ERROR.value())); | 		this.server.enqueue(jsonResponse(accessTokenErrorResponse).setResponseCode(HttpStatus.INTERNAL_SERVER_ERROR.value())); | ||||||
| 
 | 
 | ||||||
| 		assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(authorizationCodeGrantRequest()).block()) | 		assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(authorizationCodeGrantRequest()).block()) | ||||||
| 			.isInstanceOfSatisfying(ClientAuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("unauthorized_client")) | 			.isInstanceOfSatisfying(OAuth2AuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("unauthorized_client")) | ||||||
| 			.hasMessageContaining("unauthorized_client"); | 			.hasMessageContaining("unauthorized_client"); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -189,7 +192,7 @@ public class WebClientReactiveAuthorizationCodeTokenResponseClientTests { | |||||||
| 		this.server.enqueue(jsonResponse(accessTokenErrorResponse).setResponseCode(HttpStatus.INTERNAL_SERVER_ERROR.value())); | 		this.server.enqueue(jsonResponse(accessTokenErrorResponse).setResponseCode(HttpStatus.INTERNAL_SERVER_ERROR.value())); | ||||||
| 
 | 
 | ||||||
| 		assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(authorizationCodeGrantRequest()).block()) | 		assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(authorizationCodeGrantRequest()).block()) | ||||||
| 				.isInstanceOf(ClientAuthorizationException.class) | 				.isInstanceOf(OAuth2AuthorizationException.class) | ||||||
| 				.hasMessageContaining("server_error"); | 				.hasMessageContaining("server_error"); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -204,7 +207,7 @@ public class WebClientReactiveAuthorizationCodeTokenResponseClientTests { | |||||||
| 		this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); | 		this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); | ||||||
| 
 | 
 | ||||||
| 		assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(authorizationCodeGrantRequest()).block()) | 		assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(authorizationCodeGrantRequest()).block()) | ||||||
| 				.isInstanceOf(ClientAuthorizationException.class) | 				.isInstanceOf(OAuth2AuthorizationException.class) | ||||||
| 				.hasMessageContaining("invalid_token_response"); | 				.hasMessageContaining("invalid_token_response"); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -24,17 +24,21 @@ import org.junit.Before; | |||||||
| import org.junit.Test; | import org.junit.Test; | ||||||
| import org.springframework.http.HttpHeaders; | import org.springframework.http.HttpHeaders; | ||||||
| import org.springframework.http.MediaType; | import org.springframework.http.MediaType; | ||||||
| import org.springframework.security.oauth2.client.ClientAuthorizationException; |  | ||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.client.registration.TestClientRegistrations; | import org.springframework.security.oauth2.client.registration.TestClientRegistrations; | ||||||
| import org.springframework.security.oauth2.core.ClientAuthenticationMethod; | import org.springframework.security.oauth2.core.ClientAuthenticationMethod; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | ||||||
| import org.springframework.web.reactive.function.client.WebClient; | import org.springframework.web.reactive.function.client.WebClient; | ||||||
| import org.springframework.web.reactive.function.client.WebClientResponseException; | import org.springframework.web.reactive.function.client.WebClientResponseException; | ||||||
| 
 | 
 | ||||||
| import static org.assertj.core.api.Assertions.assertThat; | import static org.assertj.core.api.Assertions.assertThat; | ||||||
| import static org.assertj.core.api.Assertions.assertThatThrownBy; | import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||||||
| import static org.mockito.Mockito.*; | import static org.mockito.Mockito.atLeastOnce; | ||||||
|  | import static org.mockito.Mockito.mock; | ||||||
|  | import static org.mockito.Mockito.validateMockitoUsage; | ||||||
|  | import static org.mockito.Mockito.verify; | ||||||
|  | import static org.mockito.Mockito.when; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * @author Rob Winch |  * @author Rob Winch | ||||||
| @ -157,10 +161,9 @@ public class WebClientReactiveClientCredentialsTokenResponseClientTests { | |||||||
| 		OAuth2ClientCredentialsGrantRequest request = new OAuth2ClientCredentialsGrantRequest(registration); | 		OAuth2ClientCredentialsGrantRequest request = new OAuth2ClientCredentialsGrantRequest(registration); | ||||||
| 
 | 
 | ||||||
| 		assertThatThrownBy(() -> this.client.getTokenResponse(request).block()) | 		assertThatThrownBy(() -> this.client.getTokenResponse(request).block()) | ||||||
| 				.isInstanceOfSatisfying(ClientAuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("invalid_token_response")) | 				.isInstanceOfSatisfying(OAuth2AuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("invalid_token_response")) | ||||||
| 				.hasMessageContaining("[invalid_token_response]") | 				.hasMessageContaining("[invalid_token_response]") | ||||||
| 				.hasMessageContaining("Empty OAuth 2.0 Access Token Response") | 				.hasMessageContaining("Empty OAuth 2.0 Access Token Response"); | ||||||
| 				.hasMessageContaining("HTTP Status Code: 301"); |  | ||||||
| 
 | 
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -24,11 +24,11 @@ import org.junit.Test; | |||||||
| import org.springframework.http.HttpHeaders; | import org.springframework.http.HttpHeaders; | ||||||
| import org.springframework.http.HttpMethod; | import org.springframework.http.HttpMethod; | ||||||
| import org.springframework.http.MediaType; | import org.springframework.http.MediaType; | ||||||
| import org.springframework.security.oauth2.client.ClientAuthorizationException; |  | ||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.client.registration.TestClientRegistrations; | import org.springframework.security.oauth2.client.registration.TestClientRegistrations; | ||||||
| import org.springframework.security.oauth2.core.ClientAuthenticationMethod; | import org.springframework.security.oauth2.core.ClientAuthenticationMethod; | ||||||
| import org.springframework.security.oauth2.core.OAuth2AccessToken; | import org.springframework.security.oauth2.core.OAuth2AccessToken; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | ||||||
| 
 | 
 | ||||||
| import java.time.Instant; | import java.time.Instant; | ||||||
| @ -148,10 +148,9 @@ public class WebClientReactivePasswordTokenResponseClientTests { | |||||||
| 				this.clientRegistrationBuilder.build(), this.username, this.password); | 				this.clientRegistrationBuilder.build(), this.username, this.password); | ||||||
| 
 | 
 | ||||||
| 		assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(passwordGrantRequest).block()) | 		assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(passwordGrantRequest).block()) | ||||||
| 				.isInstanceOfSatisfying(ClientAuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("invalid_token_response")) | 				.isInstanceOfSatisfying(OAuth2AuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("invalid_token_response")) | ||||||
| 				.hasMessageContaining("[invalid_token_response]") | 				.hasMessageContaining("[invalid_token_response]") | ||||||
| 				.hasMessageContaining("An error occurred parsing the Access Token response") | 				.hasMessageContaining("An error occurred parsing the Access Token response") | ||||||
| 				.hasMessageContaining("HTTP Status Code: 200") |  | ||||||
| 				.hasCauseInstanceOf(Throwable.class); | 				.hasCauseInstanceOf(Throwable.class); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -188,10 +187,8 @@ public class WebClientReactivePasswordTokenResponseClientTests { | |||||||
| 				this.clientRegistrationBuilder.build(), this.username, this.password); | 				this.clientRegistrationBuilder.build(), this.username, this.password); | ||||||
| 
 | 
 | ||||||
| 		assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(passwordGrantRequest).block()) | 		assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(passwordGrantRequest).block()) | ||||||
| 				.isInstanceOfSatisfying(ClientAuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("unauthorized_client")) | 				.isInstanceOfSatisfying(OAuth2AuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("unauthorized_client")) | ||||||
| 				.hasMessageContaining("[unauthorized_client]") | 				.hasMessageContaining("[unauthorized_client]"); | ||||||
| 				.hasMessageContaining("Error retrieving OAuth 2.0 Access Token") |  | ||||||
| 				.hasMessageContaining("HTTP Status Code: 400"); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| @ -202,10 +199,9 @@ public class WebClientReactivePasswordTokenResponseClientTests { | |||||||
| 				this.clientRegistrationBuilder.build(), this.username, this.password); | 				this.clientRegistrationBuilder.build(), this.username, this.password); | ||||||
| 
 | 
 | ||||||
| 		assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(passwordGrantRequest).block()) | 		assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(passwordGrantRequest).block()) | ||||||
| 				.isInstanceOfSatisfying(ClientAuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("invalid_token_response")) | 				.isInstanceOfSatisfying(OAuth2AuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("invalid_token_response")) | ||||||
| 				.hasMessageContaining("[invalid_token_response]") | 				.hasMessageContaining("[invalid_token_response]") | ||||||
| 				.hasMessageContaining("Empty OAuth 2.0 Access Token Response") | 				.hasMessageContaining("Empty OAuth 2.0 Access Token Response"); | ||||||
| 				.hasMessageContaining("HTTP Status Code: 500"); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private MockResponse jsonResponse(String json) { | 	private MockResponse jsonResponse(String json) { | ||||||
|  | |||||||
| @ -24,11 +24,11 @@ import org.junit.Test; | |||||||
| import org.springframework.http.HttpHeaders; | import org.springframework.http.HttpHeaders; | ||||||
| import org.springframework.http.HttpMethod; | import org.springframework.http.HttpMethod; | ||||||
| import org.springframework.http.MediaType; | import org.springframework.http.MediaType; | ||||||
| import org.springframework.security.oauth2.client.ClientAuthorizationException; |  | ||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.client.registration.TestClientRegistrations; | import org.springframework.security.oauth2.client.registration.TestClientRegistrations; | ||||||
| import org.springframework.security.oauth2.core.ClientAuthenticationMethod; | import org.springframework.security.oauth2.core.ClientAuthenticationMethod; | ||||||
| import org.springframework.security.oauth2.core.OAuth2AccessToken; | import org.springframework.security.oauth2.core.OAuth2AccessToken; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2AuthorizationException; | ||||||
| import org.springframework.security.oauth2.core.OAuth2RefreshToken; | import org.springframework.security.oauth2.core.OAuth2RefreshToken; | ||||||
| import org.springframework.security.oauth2.core.TestOAuth2AccessTokens; | import org.springframework.security.oauth2.core.TestOAuth2AccessTokens; | ||||||
| import org.springframework.security.oauth2.core.TestOAuth2RefreshTokens; | import org.springframework.security.oauth2.core.TestOAuth2RefreshTokens; | ||||||
| @ -153,7 +153,7 @@ public class WebClientReactiveRefreshTokenTokenResponseClientTests { | |||||||
| 				this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken); | 				this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken); | ||||||
| 
 | 
 | ||||||
| 		assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest).block()) | 		assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest).block()) | ||||||
| 				.isInstanceOf(ClientAuthorizationException.class) | 				.isInstanceOf(OAuth2AuthorizationException.class) | ||||||
| 				.hasMessageContaining("[invalid_token_response]") | 				.hasMessageContaining("[invalid_token_response]") | ||||||
| 				.hasMessageContaining("An error occurred parsing the Access Token response") | 				.hasMessageContaining("An error occurred parsing the Access Token response") | ||||||
| 				.hasCauseInstanceOf(Throwable.class); | 				.hasCauseInstanceOf(Throwable.class); | ||||||
| @ -192,9 +192,8 @@ public class WebClientReactiveRefreshTokenTokenResponseClientTests { | |||||||
| 				this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken); | 				this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken); | ||||||
| 
 | 
 | ||||||
| 		assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest).block()) | 		assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest).block()) | ||||||
| 				.isInstanceOfSatisfying(ClientAuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("unauthorized_client")) | 				.isInstanceOfSatisfying(OAuth2AuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("unauthorized_client")) | ||||||
| 				.hasMessageContaining("[unauthorized_client]") | 				.hasMessageContaining("[unauthorized_client]"); | ||||||
| 				.hasMessageContaining("HTTP Status Code: 400"); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| @ -205,10 +204,9 @@ public class WebClientReactiveRefreshTokenTokenResponseClientTests { | |||||||
| 				this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken); | 				this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken); | ||||||
| 
 | 
 | ||||||
| 		assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest).block()) | 		assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest).block()) | ||||||
| 				.isInstanceOfSatisfying(ClientAuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("invalid_token_response")) | 				.isInstanceOfSatisfying(OAuth2AuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("invalid_token_response")) | ||||||
| 				.hasMessageContaining("[invalid_token_response]") | 				.hasMessageContaining("[invalid_token_response]") | ||||||
| 				.hasMessageContaining("Empty OAuth 2.0 Access Token Response") | 				.hasMessageContaining("Empty OAuth 2.0 Access Token Response"); | ||||||
| 				.hasMessageContaining("HTTP Status Code: 500"); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private MockResponse jsonResponse(String json) { | 	private MockResponse jsonResponse(String json) { | ||||||
|  | |||||||
| @ -29,6 +29,7 @@ import org.springframework.security.oauth2.client.OAuth2AuthorizationSuccessHand | |||||||
| import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest; | import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest; | ||||||
| import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; | import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; | ||||||
| import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider; | import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider; | ||||||
|  | import org.springframework.security.oauth2.client.RemoveAuthorizedClientOAuth2AuthorizationFailureHandler; | ||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; | import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; | ||||||
| import org.springframework.security.oauth2.client.registration.TestClientRegistrations; | import org.springframework.security.oauth2.client.registration.TestClientRegistrations; | ||||||
| @ -84,8 +85,19 @@ public class DefaultOAuth2AuthorizedClientManagerTests { | |||||||
| 		this.authorizedClientRepository = mock(OAuth2AuthorizedClientRepository.class); | 		this.authorizedClientRepository = mock(OAuth2AuthorizedClientRepository.class); | ||||||
| 		this.authorizedClientProvider = mock(OAuth2AuthorizedClientProvider.class); | 		this.authorizedClientProvider = mock(OAuth2AuthorizedClientProvider.class); | ||||||
| 		this.contextAttributesMapper = mock(Function.class); | 		this.contextAttributesMapper = mock(Function.class); | ||||||
| 		this.authorizationSuccessHandler = spy(new SaveAuthorizedClientOAuth2AuthorizationSuccessHandler(this.authorizedClientRepository)); | 		this.authorizationSuccessHandler = spy(new OAuth2AuthorizationSuccessHandler() { | ||||||
| 		this.authorizationFailureHandler = spy(new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler(this.authorizedClientRepository)); | 			@Override | ||||||
|  | 			public void onAuthorizationSuccess(OAuth2AuthorizedClient authorizedClient, Authentication principal, Map<String, Object> attributes) { | ||||||
|  | 				authorizedClientRepository.saveAuthorizedClient(authorizedClient, principal, | ||||||
|  | 						(HttpServletRequest) attributes.get(HttpServletRequest.class.getName()), | ||||||
|  | 						(HttpServletResponse) attributes.get(HttpServletResponse.class.getName())); | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 		this.authorizationFailureHandler = spy(new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler( | ||||||
|  | 				(clientRegistrationId, principal, attributes) -> | ||||||
|  | 						authorizedClientRepository.removeAuthorizedClient(clientRegistrationId, principal, | ||||||
|  | 								(HttpServletRequest) attributes.get(HttpServletRequest.class.getName()), | ||||||
|  | 								(HttpServletResponse) attributes.get(HttpServletResponse.class.getName())))); | ||||||
| 		this.authorizedClientManager = new DefaultOAuth2AuthorizedClientManager( | 		this.authorizedClientManager = new DefaultOAuth2AuthorizedClientManager( | ||||||
| 				this.clientRegistrationRepository, this.authorizedClientRepository); | 				this.clientRegistrationRepository, this.authorizedClientRepository); | ||||||
| 		this.authorizedClientManager.setAuthorizedClientProvider(this.authorizedClientProvider); | 		this.authorizedClientManager.setAuthorizedClientProvider(this.authorizedClientProvider); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user