Add UnauthenticatedServerOAuth2AuthorizedClientRepository
Fixes: gh-5817
This commit is contained in:
parent
96d85ad2b5
commit
11ea92ef1c
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://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.server;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Provides support for an unauthenticated user. This is useful when running as a process with no
|
||||
* user associated to it. The implementation ensures that {@link ServerWebExchange} is null and that the
|
||||
* {@link Authentication} is either null or anonymous to prevent using it incorrectly.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.1
|
||||
*/
|
||||
public class UnauthenticatedServerOAuth2AuthorizedClientRepository implements ServerOAuth2AuthorizedClientRepository {
|
||||
private final AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
|
||||
|
||||
private Map<String, OAuth2AuthorizedClient> clientRegistrationIdToAuthorizedClient = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public <T extends OAuth2AuthorizedClient> Mono<T> loadAuthorizedClient(String clientRegistrationId,
|
||||
Authentication authentication, ServerWebExchange serverWebExchange) {
|
||||
Assert.notNull(clientRegistrationId, "clientRegistrationId cannot be null");
|
||||
Assert.isNull(serverWebExchange, "serverWebExchange must be null");
|
||||
Assert.isTrue(isUnauthenticated(authentication), "The user " + authentication + " should not be authenticated");
|
||||
|
||||
return Mono.fromSupplier(() -> (T) this.clientRegistrationIdToAuthorizedClient.get(clientRegistrationId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> saveAuthorizedClient(
|
||||
OAuth2AuthorizedClient authorizedClient,
|
||||
Authentication authentication, ServerWebExchange serverWebExchange) {
|
||||
Assert.notNull(authorizedClient, "authorizedClient cannot be null");
|
||||
Assert.isNull(serverWebExchange, "serverWebExchange must be null");
|
||||
Assert.isTrue(isUnauthenticated(authentication), "The user " + authentication + " should not be authenticated");
|
||||
return Mono.fromRunnable(() -> {
|
||||
String clientRegistrationId = authorizedClient.getClientRegistration().getRegistrationId();
|
||||
this.clientRegistrationIdToAuthorizedClient.put(clientRegistrationId, authorizedClient);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> removeAuthorizedClient(String clientRegistrationId, Authentication authentication,
|
||||
ServerWebExchange serverWebExchange) {
|
||||
Assert.notNull(clientRegistrationId, "clientRegistrationId cannot be null");
|
||||
Assert.isNull(serverWebExchange, "serverWebExchange " + serverWebExchange + "must be null");
|
||||
Assert.isTrue(isUnauthenticated(authentication), "The user " + authentication + " should not be authenticated");
|
||||
return Mono.fromRunnable(() -> {
|
||||
this.clientRegistrationIdToAuthorizedClient.remove(clientRegistrationId);
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isUnauthenticated(Authentication authentication) {
|
||||
return authentication == null || this.trustResolver.isAnonymous(authentication);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://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.server;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.mock.web.server.MockServerWebExchange;
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
||||
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.TestOAuth2AccessTokens;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class UnauthenticatedServerOAuth2AuthorizedClientRepositoryTests {
|
||||
private UnauthenticatedServerOAuth2AuthorizedClientRepository repository =
|
||||
new UnauthenticatedServerOAuth2AuthorizedClientRepository();
|
||||
|
||||
private ClientRegistration clientRegistration = TestClientRegistrations.clientCredentials().build();
|
||||
|
||||
private String clientRegistrationId = this.clientRegistration.getRegistrationId();
|
||||
|
||||
private ServerWebExchange exchange;
|
||||
|
||||
private Authentication anonymous = new AnonymousAuthenticationToken("key", "anonymous", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
|
||||
|
||||
private Authentication authentication;
|
||||
|
||||
private OAuth2AuthorizedClient authorizedClient;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
OAuth2AccessToken token = TestOAuth2AccessTokens.noScopes();
|
||||
this.authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, "anonymousUser", token);
|
||||
}
|
||||
|
||||
// loadAuthorizedClient
|
||||
|
||||
@Test
|
||||
public void loadAuthorizedClientWhenClientRegistrationIdNullThenIllegalArgumentException() {
|
||||
this.clientRegistrationId = null;
|
||||
assertThatThrownBy(() -> this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block())
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadAuthorizedClientWhenAuthenticationNotNullThenIllegalArgumentException() {
|
||||
this.authentication = new TestingAuthenticationToken("a", "b", "ROLE_USER");
|
||||
assertThatThrownBy(() -> this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block())
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadAuthorizedClientWhenServerWebExchangeNotNullThenIllegalArgumentException() {
|
||||
this.exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/").build());
|
||||
assertThatThrownBy(() -> this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block())
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadAuthorizedClientWhenNotFoundThenEmpty() {
|
||||
assertThat(this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadAuthorizedClientWhenFoundThenFound() {
|
||||
this.repository.saveAuthorizedClient(this.authorizedClient, this.authentication, this.exchange).block();
|
||||
|
||||
assertThat(this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()).isEqualTo(this.authorizedClient);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadAuthorizedClientWhenMultipleThenFound() {
|
||||
ClientRegistration otherClientRegistration = TestClientRegistrations.clientRegistration()
|
||||
.registrationId("other-client-registration")
|
||||
.build();
|
||||
OAuth2AuthorizedClient otherAuthorizedClient = new OAuth2AuthorizedClient(otherClientRegistration, "anonymousUser", this.authorizedClient.getAccessToken());
|
||||
|
||||
this.repository.saveAuthorizedClient(this.authorizedClient, this.authentication, this.exchange).block();
|
||||
this.repository.saveAuthorizedClient(otherAuthorizedClient, this.authentication, this.exchange).block();
|
||||
|
||||
assertThat(this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()).isEqualTo(this.authorizedClient);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadAuthorizedClientWhenAnonymousThenFound() {
|
||||
this.authentication = this.anonymous;
|
||||
this.repository.saveAuthorizedClient(this.authorizedClient, this.authentication, this.exchange).block();
|
||||
|
||||
assertThat(this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()).isEqualTo(this.authorizedClient);
|
||||
}
|
||||
|
||||
// saveAuthorizedClient
|
||||
|
||||
@Test
|
||||
public void saveAuthorizedClientWhenAuthorizedClientNullThenIllegalArgumentException() {
|
||||
this.authorizedClient = null;
|
||||
assertThatThrownBy(() -> this.repository.saveAuthorizedClient(this.authorizedClient, this.authentication, this.exchange).block())
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveAuthorizedClientWhenAuthenticationNotNullThenIllegalArgumentException() {
|
||||
this.authentication = new TestingAuthenticationToken("a", "b", "ROLE_USER");
|
||||
assertThatThrownBy(() -> this.repository.saveAuthorizedClient(this.authorizedClient, this.authentication, this.exchange).block())
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveAuthorizedClientWhenServerWebExchangeNotNullThenIllegalArgumentException() {
|
||||
this.exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/").build());
|
||||
assertThatThrownBy(() -> this.repository.saveAuthorizedClient(this.authorizedClient, this.authentication, this.exchange).block())
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
// removeAuthorizedClient
|
||||
|
||||
@Test
|
||||
public void removeAuthorizedClientWhenClientRegistrationIdNullThenIllegalArgumentException() {
|
||||
this.clientRegistrationId = null;
|
||||
assertThatThrownBy(() -> this.repository.removeAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block())
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeAuthorizedClientWhenAuthenticationNotNullThenIllegalArgumentException() {
|
||||
this.authentication = new TestingAuthenticationToken("a", "b", "ROLE_USER");
|
||||
assertThatThrownBy(() -> this.repository.removeAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block())
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeAuthorizedClientWhenServerWebExchangeNotNullThenIllegalArgumentException() {
|
||||
this.exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/").build());
|
||||
assertThatThrownBy(() -> this.repository.removeAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block())
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeAuthorizedClientWhenFoundThenFound() {
|
||||
this.repository.saveAuthorizedClient(this.authorizedClient, this.authentication, this.exchange).block();
|
||||
this.repository.removeAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block();
|
||||
|
||||
assertThat(this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()).isNull();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue