Fix package tangles

Issue #7699 #7840
This commit is contained in:
Joe Grandja 2020-02-21 16:47:24 -05:00
parent f2da2c56be
commit c8cc9717c9
28 changed files with 236 additions and 469 deletions

View File

@ -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.ClientRegistrationRepository;
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.OAuth2ErrorCodes;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
@ -94,8 +92,11 @@ public final class AuthorizedClientServiceOAuth2AuthorizedClientManager implemen
this.clientRegistrationRepository = clientRegistrationRepository;
this.authorizedClientService = authorizedClientService;
this.contextAttributesMapper = new DefaultContextAttributesMapper();
this.authorizationSuccessHandler = new SaveAuthorizedClientOAuth2AuthorizationSuccessHandler(authorizedClientService);
this.authorizationFailureHandler = new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler(authorizedClientService);
this.authorizationSuccessHandler = (authorizedClient, principal, attributes) ->
authorizedClientService.saveAuthorizedClient(authorizedClient, principal);
this.authorizationFailureHandler = new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler(
(clientRegistrationId, principal, attributes) ->
authorizedClientService.removeAuthorizedClient(clientRegistrationId, principal.getName()));
}
@Nullable
@ -177,10 +178,9 @@ public final class AuthorizedClientServiceOAuth2AuthorizedClientManager implemen
* Sets the {@link OAuth2AuthorizationSuccessHandler} that handles successful authorizations.
*
* <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
* @see SaveAuthorizedClientOAuth2AuthorizationSuccessHandler
* @since 5.3
*/
public void setAuthorizationSuccessHandler(OAuth2AuthorizationSuccessHandler authorizationSuccessHandler) {

View File

@ -18,8 +18,6 @@ package org.springframework.security.oauth2.client;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
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.util.Assert;
import org.springframework.web.server.ServerWebExchange;
@ -91,8 +89,11 @@ public final class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager
Assert.notNull(authorizedClientService, "authorizedClientService cannot be null");
this.clientRegistrationRepository = clientRegistrationRepository;
this.authorizedClientService = authorizedClientService;
this.authorizationSuccessHandler = new SaveAuthorizedClientReactiveOAuth2AuthorizationSuccessHandler(authorizedClientService);
this.authorizationFailureHandler = new RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler(authorizedClientService);
this.authorizationSuccessHandler = (authorizedClient, principal, attributes) ->
authorizedClientService.saveAuthorizedClient(authorizedClient, principal);
this.authorizationFailureHandler = new RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler(
(clientRegistrationId, principal, attributes) ->
this.authorizedClientService.removeAuthorizedClient(clientRegistrationId, principal.getName()));
}
@Override
@ -179,11 +180,9 @@ public final class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager
/**
* Sets the handler that handles successful authorizations.
*
* <p>A {@link SaveAuthorizedClientReactiveOAuth2AuthorizationSuccessHandler}
* is used by default.</p>
* The default saves {@link OAuth2AuthorizedClient}s in the {@link ReactiveOAuth2AuthorizedClientService}.
*
* @param authorizationSuccessHandler the handler that handles successful authorizations.
* @see SaveAuthorizedClientReactiveOAuth2AuthorizationSuccessHandler
* @since 5.3
*/
public void setAuthorizationSuccessHandler(ReactiveOAuth2AuthorizationSuccessHandler authorizationSuccessHandler) {

View File

@ -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");
* 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.core.AbstractOAuth2Token;
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.util.Assert;
@ -79,8 +80,13 @@ public final class ClientCredentialsOAuth2AuthorizedClientProvider implements OA
OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest =
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());
}

View File

@ -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");
* 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.core.AbstractOAuth2Token;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
import org.springframework.util.Assert;
import reactor.core.publisher.Mono;
@ -77,6 +78,8 @@ public final class ClientCredentialsReactiveOAuth2AuthorizedClientProvider imple
return Mono.just(new OAuth2ClientCredentialsGrantRequest(clientRegistration))
.flatMap(this.accessTokenResponseClient::getTokenResponse)
.onErrorMap(OAuth2AuthorizationException.class,
e -> new ClientAuthorizationException(e.getError(), clientRegistration.getRegistrationId(), e))
.map(tokenResponse -> new OAuth2AuthorizedClient(
clientRegistration, context.getPrincipal().getName(), tokenResponse.getAccessToken()));
}

View File

@ -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");
* 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.core.AbstractOAuth2Token;
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.util.Assert;
import org.springframework.util.StringUtils;
@ -96,8 +97,13 @@ public final class PasswordOAuth2AuthorizedClientProvider implements OAuth2Autho
OAuth2PasswordGrantRequest passwordGrantRequest =
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(),
tokenResponse.getAccessToken(), tokenResponse.getRefreshToken());

View File

@ -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");
* 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.core.AbstractOAuth2Token;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Mono;
@ -97,6 +98,8 @@ public final class PasswordReactiveOAuth2AuthorizedClientProvider implements Rea
return Mono.just(passwordGrantRequest)
.flatMap(this.accessTokenResponseClient::getTokenResponse)
.onErrorMap(OAuth2AuthorizationException.class,
e -> new ClientAuthorizationException(e.getError(), clientRegistration.getRegistrationId(), e))
.map(tokenResponse -> new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(),
tokenResponse.getAccessToken(), tokenResponse.getRefreshToken()));
}

View File

@ -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");
* 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.core.AbstractOAuth2Token;
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.util.Assert;
@ -86,8 +87,13 @@ public final class RefreshTokenOAuth2AuthorizedClientProvider implements OAuth2A
OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest(
authorizedClient.getClientRegistration(), authorizedClient.getAccessToken(),
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(),
context.getPrincipal().getName(), tokenResponse.getAccessToken(), tokenResponse.getRefreshToken());

View File

@ -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");
* 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.core.AbstractOAuth2Token;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
import org.springframework.util.Assert;
import reactor.core.publisher.Mono;
@ -88,6 +89,8 @@ public final class RefreshTokenReactiveOAuth2AuthorizedClientProvider implements
return Mono.just(refreshTokenGrantRequest)
.flatMap(this.accessTokenResponseClient::getTokenResponse)
.onErrorMap(OAuth2AuthorizationException.class,
e -> new ClientAuthorizationException(e.getError(), clientRegistration.getRegistrationId(), e))
.map(tokenResponse -> new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(),
tokenResponse.getAccessToken(), tokenResponse.getRefreshToken()));
}

View File

@ -13,19 +13,15 @@
* See the License for the specific language governing permissions and
* 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.oauth2.client.ClientAuthorizationException;
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.client.web.OAuth2AuthorizedClientRepository;
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
import org.springframework.util.Assert;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
@ -34,8 +30,8 @@ import java.util.Set;
/**
* An {@link OAuth2AuthorizationFailureHandler} that removes an {@link OAuth2AuthorizedClient}
* from an {@link OAuth2AuthorizedClientRepository} or {@link OAuth2AuthorizedClientService}
* for a specific set of OAuth 2.0 error codes.
* when the {@link OAuth2Error#getErrorCode()} matches
* one of the configured {@link OAuth2ErrorCodes OAuth 2.0 error codes}.
*
* @author Joe Grandja
* @since 5.3
@ -74,73 +70,58 @@ public class RemoveAuthorizedClientOAuth2AuthorizationFailureHandler implements
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}
* if the error code is one of the {@link #removeAuthorizedClientErrorCodes}.
*/
private final OAuth2AuthorizedClientRemover delegate;
/**
* Removes an {@link OAuth2AuthorizedClient} from an
* {@link OAuth2AuthorizedClientRepository} or {@link OAuth2AuthorizedClientService}.
*/
@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);
}
/**
* 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 #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
* @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(OAuth2AuthorizedClientService authorizedClientService) {
this(authorizedClientService, DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES);
public RemoveAuthorizedClientOAuth2AuthorizationFailureHandler(OAuth2AuthorizedClientRemover authorizedClientRemover) {
this(authorizedClientRemover, DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES);
}
/**
* 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}.
* @param removeAuthorizedClientErrorCodes the OAuth 2.0 error codes which will trigger removal of an authorized client.
* @see OAuth2ErrorCodes
*/
public RemoveAuthorizedClientOAuth2AuthorizationFailureHandler(
OAuth2AuthorizedClientService authorizedClientService,
OAuth2AuthorizedClientRemover authorizedClientRemover,
Set<String> removeAuthorizedClientErrorCodes) {
Assert.notNull(authorizedClientService, "authorizedClientService cannot be null");
Assert.notNull(authorizedClientRemover, "authorizedClientRemover 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());
this.delegate = authorizedClientRemover;
}
@Override
@ -149,6 +130,7 @@ public class RemoveAuthorizedClientOAuth2AuthorizationFailureHandler implements
if (authorizationException instanceof ClientAuthorizationException &&
hasRemovalErrorCode(authorizationException)) {
ClientAuthorizationException clientAuthorizationException = (ClientAuthorizationException) authorizationException;
this.delegate.removeAuthorizedClient(
clientAuthorizationException.getClientRegistrationId(), principal, attributes);

View File

@ -13,17 +13,14 @@
* See the License for the specific language governing permissions and
* 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.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.core.OAuth2AuthorizationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Arrays;
@ -33,10 +30,9 @@ import java.util.Map;
import java.util.Set;
/**
* An authorization failure handler that removes authorized clients from a
* {@link ServerOAuth2AuthorizedClientRepository}
* or a {@link ReactiveOAuth2AuthorizedClientService}.
* for specific OAuth 2.0 error codes.
* A {@link ReactiveOAuth2AuthorizationFailureHandler} that removes an {@link OAuth2AuthorizedClient}
* when the {@link OAuth2Error#getErrorCode()} matches
* one of the configured {@link OAuth2ErrorCodes OAuth 2.0 error codes}.
*
* @author Phil Clay
* @since 5.3
@ -64,10 +60,8 @@ public class RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler imp
OAuth2ErrorCodes.INVALID_GRANT)));
/**
* A delegate that removes clients from either a
* {@link ServerOAuth2AuthorizedClientRepository}
* or a
* {@link ReactiveOAuth2AuthorizedClientService}
* A delegate that removes an {@link OAuth2AuthorizedClient} from a
* {@link ServerOAuth2AuthorizedClientRepository} or {@link ReactiveOAuth2AuthorizedClientService}
* if the error code is one of the {@link #removeAuthorizedClientErrorCodes}.
*/
private final OAuth2AuthorizedClientRemover delegate;
@ -78,81 +72,64 @@ public class RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler imp
*/
private final Set<String> removeAuthorizedClientErrorCodes;
/**
* Removes an {@link OAuth2AuthorizedClient} from a
* {@link ServerOAuth2AuthorizedClientRepository} or {@link ReactiveOAuth2AuthorizedClientService}.
*/
@FunctionalInterface
private interface OAuth2AuthorizedClientRemover {
Mono<Void> removeAuthorizedClient(
String clientRegistrationId,
Authentication principal,
Map<String, Object> attributes);
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 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
* if the error code is one of the {@link #DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES}.
* Constructs a {@code RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} using the provided parameters.
*
* @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) {
this(authorizedClientRepository, DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES);
public RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler(OAuth2AuthorizedClientRemover authorizedClientRemover) {
this(authorizedClientRemover, DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES);
}
/**
* @param authorizedClientRepository The repository 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.
* Constructs a {@code RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} using the provided parameters.
*
* @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
*/
public RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler(
ServerOAuth2AuthorizedClientRepository authorizedClientRepository,
OAuth2AuthorizedClientRemover authorizedClientRemover,
Set<String> removeAuthorizedClientErrorCodes) {
Assert.notNull(authorizedClientRepository, "authorizedClientRepository cannot be null");
Assert.notNull(authorizedClientRemover, "authorizedClientRemover 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,
(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());
this.delegate = authorizedClientRemover;
}
@Override
public Mono<Void> onAuthorizationFailure(
OAuth2AuthorizationException authorizationException,
Authentication principal,
Map<String, Object> attributes) {
public Mono<Void> onAuthorizationFailure(OAuth2AuthorizationException authorizationException,
Authentication principal, Map<String, Object> attributes) {
if (authorizationException instanceof ClientAuthorizationException
&& hasRemovalErrorCode(authorizationException)) {
ClientAuthorizationException clientAuthorizationException = (ClientAuthorizationException) authorizationException;
return this.delegate.removeAuthorizedClient(
clientAuthorizationException.getClientRegistrationId(),
principal,
attributes);
clientAuthorizationException.getClientRegistrationId(), principal, attributes);
} else {
return Mono.empty();
}

View File

@ -17,10 +17,8 @@ package org.springframework.security.oauth2.client.endpoint;
import org.springframework.http.HttpHeaders;
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.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.util.Assert;
@ -167,38 +165,9 @@ abstract class AbstractWebClientReactiveOAuth2AccessTokenResponseClient<T extend
*/
private Mono<OAuth2AccessTokenResponse> readTokenResponse(T grantRequest, ClientResponse response) {
return response.body(oauth2AccessTokenResponse())
.onErrorMap(OAuth2AuthorizationException.class, e -> createClientAuthorizationException(
response,
clientRegistration(grantRequest).getRegistrationId(),
e))
.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
* from the grant request.

View File

@ -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");
* 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.converter.FormHttpMessageConverter;
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.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
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.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestClientResponseException;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;
@ -75,22 +74,9 @@ public final class DefaultAuthorizationCodeTokenResponseClient implements OAuth2
try {
response = this.restOperations.exchange(request, OAuth2AccessTokenResponse.class);
} catch (RestClientException ex) {
int statusCode = 500;
if (ex instanceof RestClientResponseException) {
statusCode = ((RestClientResponseException) ex).getRawStatusCode();
}
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);
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);
throw new OAuth2AuthorizationException(oauth2Error, ex);
}
OAuth2AccessTokenResponse tokenResponse = response.getBody();

View File

@ -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");
* 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.converter.FormHttpMessageConverter;
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.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
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.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestClientResponseException;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;
@ -75,22 +74,9 @@ public final class DefaultClientCredentialsTokenResponseClient implements OAuth2
try {
response = this.restOperations.exchange(request, OAuth2AccessTokenResponse.class);
} catch (RestClientException ex) {
int statusCode = 500;
if (ex instanceof RestClientResponseException) {
statusCode = ((RestClientResponseException) ex).getRawStatusCode();
}
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);
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);
throw new OAuth2AuthorizationException(oauth2Error, ex);
}
OAuth2AccessTokenResponse tokenResponse = response.getBody();

View File

@ -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");
* 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.converter.FormHttpMessageConverter;
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.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
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.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestClientResponseException;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;
@ -75,22 +74,9 @@ public final class DefaultPasswordTokenResponseClient implements OAuth2AccessTok
try {
response = this.restOperations.exchange(request, OAuth2AccessTokenResponse.class);
} catch (RestClientException ex) {
int statusCode = 500;
if (ex instanceof RestClientResponseException) {
statusCode = ((RestClientResponseException) ex).getRawStatusCode();
}
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);
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);
throw new OAuth2AuthorizationException(oauth2Error, ex);
}
OAuth2AccessTokenResponse tokenResponse = response.getBody();

View File

@ -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");
* 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.converter.FormHttpMessageConverter;
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.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
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.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestClientResponseException;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;
@ -74,22 +73,9 @@ public final class DefaultRefreshTokenTokenResponseClient implements OAuth2Acces
try {
response = this.restOperations.exchange(request, OAuth2AccessTokenResponse.class);
} catch (RestClientException ex) {
int statusCode = 500;
if (ex instanceof RestClientResponseException) {
statusCode = ((RestClientResponseException) ex).getRawStatusCode();
}
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);
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);
throw new OAuth2AuthorizationException(oauth2Error, ex);
}
OAuth2AccessTokenResponse tokenResponse = response.getBody();

View File

@ -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");
* 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.id.ClientID;
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.core.ClientAuthenticationMethod;
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.OAuth2ErrorCodes;
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
@ -100,19 +100,9 @@ public class NimbusAuthorizationCodeTokenResponseClient implements OAuth2AccessT
httpRequest.setReadTimeout(30000);
tokenResponse = com.nimbusds.oauth2.sdk.TokenResponse.parse(httpRequest.send());
} catch (ParseException | IOException ex) {
int statusCode = 500;
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,
clientRegistration.getRegistrationId(),
message,
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);
throw new OAuth2AuthorizationException(oauth2Error, ex);
}
if (!tokenResponse.indicatesSuccess()) {
@ -127,7 +117,7 @@ public class NimbusAuthorizationCodeTokenResponseClient implements OAuth2AccessT
errorObject.getDescription(),
errorObject.getURI() != null ? errorObject.getURI().toString() : null);
}
throw new ClientAuthorizationException(oauth2Error, clientRegistration.getRegistrationId());
throw new OAuth2AuthorizationException(oauth2Error);
}
AccessTokenResponse accessTokenResponse = (AccessTokenResponse) tokenResponse;

View File

@ -25,6 +25,7 @@ import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
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.ClientRegistrationRepository;
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
@ -102,8 +103,15 @@ public final class DefaultOAuth2AuthorizedClientManager implements OAuth2Authori
this.clientRegistrationRepository = clientRegistrationRepository;
this.authorizedClientRepository = authorizedClientRepository;
this.contextAttributesMapper = new DefaultContextAttributesMapper();
this.authorizationSuccessHandler = new SaveAuthorizedClientOAuth2AuthorizationSuccessHandler(authorizedClientRepository);
this.authorizationFailureHandler = new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler(authorizedClientRepository);
this.authorizationSuccessHandler = (authorizedClient, principal, attributes) ->
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
@ -221,10 +229,9 @@ public final class DefaultOAuth2AuthorizedClientManager implements OAuth2Authori
* Sets the {@link OAuth2AuthorizationSuccessHandler} that handles successful authorizations.
*
* <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
* @see SaveAuthorizedClientOAuth2AuthorizationSuccessHandler
* @since 5.3
*/
public void setAuthorizationSuccessHandler(OAuth2AuthorizationSuccessHandler authorizationSuccessHandler) {

View File

@ -23,6 +23,7 @@ import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizationFai
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizationSuccessHandler;
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientManager;
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.ReactiveClientRegistrationRepository;
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");
this.clientRegistrationRepository = clientRegistrationRepository;
this.authorizedClientRepository = authorizedClientRepository;
this.authorizationSuccessHandler = new SaveAuthorizedClientReactiveOAuth2AuthorizationSuccessHandler(authorizedClientRepository);
this.authorizationFailureHandler = new RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler(authorizedClientRepository);
this.authorizationSuccessHandler = (authorizedClient, principal, attributes) ->
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
@ -230,11 +236,9 @@ public final class DefaultReactiveOAuth2AuthorizedClientManager implements React
/**
* Sets the handler that handles successful authorizations.
*
* <p>A {@link SaveAuthorizedClientReactiveOAuth2AuthorizationSuccessHandler}
* is used by default.</p>
* The default saves {@link OAuth2AuthorizedClient}s in the {@link ServerOAuth2AuthorizedClientRepository}.
*
* @param authorizationSuccessHandler the handler that handles successful authorizations.
* @see SaveAuthorizedClientReactiveOAuth2AuthorizationSuccessHandler
* @since 5.3
*/
public void setAuthorizationSuccessHandler(ReactiveOAuth2AuthorizationSuccessHandler authorizationSuccessHandler) {

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -34,14 +34,13 @@ import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClient
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProvider;
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProviderBuilder;
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.endpoint.OAuth2ClientCredentialsGrantRequest;
import org.springframework.security.oauth2.client.endpoint.ReactiveOAuth2AccessTokenResponseClient;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
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.UnAuthenticatedServerOAuth2AuthorizedClientRepository;
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
@ -191,7 +190,10 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements
ServerOAuth2AuthorizedClientRepository authorizedClientRepository) {
ReactiveOAuth2AuthorizationFailureHandler authorizationFailureHandler =
new RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler(authorizedClientRepository);
new RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler(
(clientRegistrationId, principal, attributes) ->
authorizedClientRepository.removeAuthorizedClient(clientRegistrationId, principal,
(ServerWebExchange) attributes.get(ServerWebExchange.class.getName())));
this.authorizedClientManager = createDefaultAuthorizedClientManager(
clientRegistrationRepository,
@ -518,7 +520,9 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements
ReactiveOAuth2AuthorizationFailureHandler authorizationFailureHandler) {
this.clientRegistrationRepository = clientRegistrationRepository;
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;
}

View File

@ -31,6 +31,7 @@ import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder;
import org.springframework.security.oauth2.client.RefreshTokenOAuth2AuthorizedClientProvider;
import org.springframework.security.oauth2.client.RemoveAuthorizedClientOAuth2AuthorizationFailureHandler;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
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.web.DefaultOAuth2AuthorizedClientManager;
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.OAuth2Error;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
@ -212,8 +212,11 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement
OAuth2AuthorizedClientRepository authorizedClientRepository) {
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(
clientRegistrationRepository, authorizedClientRepository, authorizationFailureHandler);
this.defaultAuthorizedClientManager = true;

View File

@ -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.ClientRegistrationRepository;
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.OAuth2ErrorCodes;
import org.springframework.security.oauth2.core.TestOAuth2AccessTokens;
import org.springframework.security.oauth2.core.TestOAuth2RefreshTokens;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import java.util.Map;
import java.util.function.Function;
import static org.assertj.core.api.Assertions.assertThat;
@ -70,8 +69,15 @@ public class AuthorizedClientServiceOAuth2AuthorizedClientManagerTests {
this.authorizedClientService = mock(OAuth2AuthorizedClientService.class);
this.authorizedClientProvider = mock(OAuth2AuthorizedClientProvider.class);
this.contextAttributesMapper = mock(Function.class);
this.authorizationSuccessHandler = spy(new SaveAuthorizedClientOAuth2AuthorizationSuccessHandler(this.authorizedClientService));
this.authorizationFailureHandler = spy(new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler(this.authorizedClientService));
this.authorizationSuccessHandler = spy(new OAuth2AuthorizationSuccessHandler() {
@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.clientRegistrationRepository, this.authorizedClientService);
this.authorizedClientManager.setAuthorizedClientProvider(this.authorizedClientProvider);

View File

@ -24,10 +24,10 @@ import org.junit.Test;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
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.TestClientRegistrations;
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.OAuth2AuthorizationExchange;
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.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
@ -178,7 +181,7 @@ public class WebClientReactiveAuthorizationCodeTokenResponseClientTests {
this.server.enqueue(jsonResponse(accessTokenErrorResponse).setResponseCode(HttpStatus.INTERNAL_SERVER_ERROR.value()));
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");
}
@ -189,7 +192,7 @@ public class WebClientReactiveAuthorizationCodeTokenResponseClientTests {
this.server.enqueue(jsonResponse(accessTokenErrorResponse).setResponseCode(HttpStatus.INTERNAL_SERVER_ERROR.value()));
assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(authorizationCodeGrantRequest()).block())
.isInstanceOf(ClientAuthorizationException.class)
.isInstanceOf(OAuth2AuthorizationException.class)
.hasMessageContaining("server_error");
}
@ -204,7 +207,7 @@ public class WebClientReactiveAuthorizationCodeTokenResponseClientTests {
this.server.enqueue(jsonResponse(accessTokenSuccessResponse));
assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(authorizationCodeGrantRequest()).block())
.isInstanceOf(ClientAuthorizationException.class)
.isInstanceOf(OAuth2AuthorizationException.class)
.hasMessageContaining("invalid_token_response");
}

View File

@ -24,17 +24,21 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.http.HttpHeaders;
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.TestClientRegistrations;
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.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import static org.assertj.core.api.Assertions.assertThat;
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
@ -157,10 +161,9 @@ public class WebClientReactiveClientCredentialsTokenResponseClientTests {
OAuth2ClientCredentialsGrantRequest request = new OAuth2ClientCredentialsGrantRequest(registration);
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("Empty OAuth 2.0 Access Token Response")
.hasMessageContaining("HTTP Status Code: 301");
.hasMessageContaining("Empty OAuth 2.0 Access Token Response");
}

View File

@ -24,11 +24,11 @@ import org.junit.Test;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
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.TestClientRegistrations;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
import java.time.Instant;
@ -148,10 +148,9 @@ public class WebClientReactivePasswordTokenResponseClientTests {
this.clientRegistrationBuilder.build(), this.username, this.password);
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("An error occurred parsing the Access Token response")
.hasMessageContaining("HTTP Status Code: 200")
.hasCauseInstanceOf(Throwable.class);
}
@ -188,10 +187,8 @@ public class WebClientReactivePasswordTokenResponseClientTests {
this.clientRegistrationBuilder.build(), this.username, this.password);
assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(passwordGrantRequest).block())
.isInstanceOfSatisfying(ClientAuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("unauthorized_client"))
.hasMessageContaining("[unauthorized_client]")
.hasMessageContaining("Error retrieving OAuth 2.0 Access Token")
.hasMessageContaining("HTTP Status Code: 400");
.isInstanceOfSatisfying(OAuth2AuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("unauthorized_client"))
.hasMessageContaining("[unauthorized_client]");
}
@Test
@ -202,10 +199,9 @@ public class WebClientReactivePasswordTokenResponseClientTests {
this.clientRegistrationBuilder.build(), this.username, this.password);
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("Empty OAuth 2.0 Access Token Response")
.hasMessageContaining("HTTP Status Code: 500");
.hasMessageContaining("Empty OAuth 2.0 Access Token Response");
}
private MockResponse jsonResponse(String json) {

View File

@ -24,11 +24,11 @@ import org.junit.Test;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
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.TestClientRegistrations;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
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.TestOAuth2AccessTokens;
import org.springframework.security.oauth2.core.TestOAuth2RefreshTokens;
@ -153,7 +153,7 @@ public class WebClientReactiveRefreshTokenTokenResponseClientTests {
this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken);
assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest).block())
.isInstanceOf(ClientAuthorizationException.class)
.isInstanceOf(OAuth2AuthorizationException.class)
.hasMessageContaining("[invalid_token_response]")
.hasMessageContaining("An error occurred parsing the Access Token response")
.hasCauseInstanceOf(Throwable.class);
@ -192,9 +192,8 @@ public class WebClientReactiveRefreshTokenTokenResponseClientTests {
this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken);
assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest).block())
.isInstanceOfSatisfying(ClientAuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("unauthorized_client"))
.hasMessageContaining("[unauthorized_client]")
.hasMessageContaining("HTTP Status Code: 400");
.isInstanceOfSatisfying(OAuth2AuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("unauthorized_client"))
.hasMessageContaining("[unauthorized_client]");
}
@Test
@ -205,10 +204,9 @@ public class WebClientReactiveRefreshTokenTokenResponseClientTests {
this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken);
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("Empty OAuth 2.0 Access Token Response")
.hasMessageContaining("HTTP Status Code: 500");
.hasMessageContaining("Empty OAuth 2.0 Access Token Response");
}
private MockResponse jsonResponse(String json) {

View File

@ -29,6 +29,7 @@ import org.springframework.security.oauth2.client.OAuth2AuthorizationSuccessHand
import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
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.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.registration.TestClientRegistrations;
@ -84,8 +85,19 @@ public class DefaultOAuth2AuthorizedClientManagerTests {
this.authorizedClientRepository = mock(OAuth2AuthorizedClientRepository.class);
this.authorizedClientProvider = mock(OAuth2AuthorizedClientProvider.class);
this.contextAttributesMapper = mock(Function.class);
this.authorizationSuccessHandler = spy(new SaveAuthorizedClientOAuth2AuthorizationSuccessHandler(this.authorizedClientRepository));
this.authorizationFailureHandler = spy(new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler(this.authorizedClientRepository));
this.authorizationSuccessHandler = spy(new OAuth2AuthorizationSuccessHandler() {
@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.clientRegistrationRepository, this.authorizedClientRepository);
this.authorizedClientManager.setAuthorizedClientProvider(this.authorizedClientProvider);