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.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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
|
|
|
@ -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);
|
|
@ -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();
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue