Add InMemoryReactiveClientRegistrationRepository
Issue: gh-4807
This commit is contained in:
parent
ca9cd20832
commit
a02b0c17f8
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* 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.registration;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ConcurrentReferenceHashMap;
|
||||||
|
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Reactive {@link ClientRegistrationRepository} that stores {@link ClientRegistration}(s) in-memory.
|
||||||
|
*
|
||||||
|
* @author Rob Winch
|
||||||
|
* @since 5.1
|
||||||
|
* @see ClientRegistrationRepository
|
||||||
|
* @see ClientRegistration
|
||||||
|
*/
|
||||||
|
public final class InMemoryReactiveClientRegistrationRepository
|
||||||
|
implements ReactiveClientRegistrationRepository, Iterable<ClientRegistration> {
|
||||||
|
|
||||||
|
private final Map<String, ClientRegistration> clientIdToClientRegistration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an {@code InMemoryReactiveClientRegistrationRepository} using the provided parameters.
|
||||||
|
*
|
||||||
|
* @param registrations the client registration(s)
|
||||||
|
*/
|
||||||
|
public InMemoryReactiveClientRegistrationRepository(ClientRegistration... registrations) {
|
||||||
|
Assert.notEmpty(registrations, "registrations cannot be empty");
|
||||||
|
this.clientIdToClientRegistration = new ConcurrentReferenceHashMap<>();
|
||||||
|
for (ClientRegistration registration : registrations) {
|
||||||
|
Assert.notNull(registration, "registrations cannot contain null values");
|
||||||
|
this.clientIdToClientRegistration.put(registration.getRegistrationId(), registration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an {@code InMemoryReactiveClientRegistrationRepository} using the provided parameters.
|
||||||
|
*
|
||||||
|
* @param registrations the client registration(s)
|
||||||
|
*/
|
||||||
|
public InMemoryReactiveClientRegistrationRepository(List<ClientRegistration> registrations) {
|
||||||
|
Assert.notEmpty(registrations, "registrations cannot be null or empty");
|
||||||
|
this.clientIdToClientRegistration = registrations.stream()
|
||||||
|
.collect(Collectors.toConcurrentMap(ClientRegistration::getRegistrationId, Function.identity()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<ClientRegistration> findByRegistrationId(String registrationId) {
|
||||||
|
return Mono.justOrEmpty(this.clientIdToClientRegistration.get(registrationId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an {@code Iterator} of {@link ClientRegistration}.
|
||||||
|
*
|
||||||
|
* @return an {@code Iterator<ClientRegistration>}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Iterator<ClientRegistration> iterator() {
|
||||||
|
return this.clientIdToClientRegistration.values().iterator();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* 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.registration;
|
||||||
|
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A reactive repository for OAuth 2.0 / OpenID Connect 1.0 {@link ClientRegistration}(s).
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* <b>NOTE:</b> Client registration information is ultimately stored and owned
|
||||||
|
* by the associated Authorization Server.
|
||||||
|
* Therefore, this repository provides the capability to store a sub-set copy
|
||||||
|
* of the <i>primary</i> client registration information
|
||||||
|
* externally from the Authorization Server.
|
||||||
|
*
|
||||||
|
* @author Rob Winch
|
||||||
|
* @since 5.1
|
||||||
|
* @see ClientRegistration
|
||||||
|
*/
|
||||||
|
public interface ReactiveClientRegistrationRepository {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the client registration identified by the provided {@code registrationId}, or {@code null} if not found.
|
||||||
|
*
|
||||||
|
* @param registrationId the registration identifier
|
||||||
|
* @return the {@link ClientRegistration} if found, otherwise {@code null}
|
||||||
|
*/
|
||||||
|
Mono<ClientRegistration> findByRegistrationId(String registrationId);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* 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.registration;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||||
|
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
|
||||||
|
|
||||||
|
import reactor.test.StepVerifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Rob Winch
|
||||||
|
* @since 5.1
|
||||||
|
*/
|
||||||
|
public class InMemoryReactiveClientRegistrationRepositoryTests {
|
||||||
|
|
||||||
|
private ClientRegistration github = ClientRegistration.withRegistrationId("github")
|
||||||
|
.redirectUriTemplate("{baseUrl}/{action}/oauth2/code/{registrationId}")
|
||||||
|
.clientAuthenticationMethod(ClientAuthenticationMethod.BASIC)
|
||||||
|
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
|
||||||
|
.scope("read:user")
|
||||||
|
.authorizationUri("https://github.com/login/oauth/authorize")
|
||||||
|
.tokenUri("https://github.com/login/oauth/access_token")
|
||||||
|
.userInfoUri("https://api.github.com/user")
|
||||||
|
.userNameAttributeName("id")
|
||||||
|
.clientName("GitHub")
|
||||||
|
.clientId("clientId")
|
||||||
|
.clientSecret("clientSecret")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
private InMemoryReactiveClientRegistrationRepository repository;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
this.repository = new InMemoryReactiveClientRegistrationRepository(this.github);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void constructorWhenZeroVarArgsThenIllegalArgumentException() {
|
||||||
|
assertThatThrownBy(() -> new InMemoryReactiveClientRegistrationRepository())
|
||||||
|
.isInstanceOf(IllegalArgumentException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void constructorWhenClientRegistrationArrayThenIllegalArgumentException() {
|
||||||
|
ClientRegistration[] registrations = null;
|
||||||
|
assertThatThrownBy(() -> new InMemoryReactiveClientRegistrationRepository(registrations))
|
||||||
|
.isInstanceOf(IllegalArgumentException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void constructorWhenClientRegistrationListThenIllegalArgumentException() {
|
||||||
|
List<ClientRegistration> registrations = null;
|
||||||
|
assertThatThrownBy(() -> new InMemoryReactiveClientRegistrationRepository(registrations))
|
||||||
|
.isInstanceOf(IllegalArgumentException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void constructorWhenClientRegistrationIsNullThenIllegalArgumentException() {
|
||||||
|
ClientRegistration registration = null;
|
||||||
|
assertThatThrownBy(() -> new InMemoryReactiveClientRegistrationRepository(registration))
|
||||||
|
.isInstanceOf(IllegalArgumentException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void findByRegistrationIdWhenValidIdThenFound() {
|
||||||
|
StepVerifier.create(this.repository.findByRegistrationId(this.github.getRegistrationId()))
|
||||||
|
.expectNext(this.github)
|
||||||
|
.verifyComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void findByRegistrationIdWhenNotValidIdThenEmpty() {
|
||||||
|
StepVerifier.create(this.repository.findByRegistrationId(this.github.getRegistrationId() + "invalid"))
|
||||||
|
.verifyComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void iteratorWhenContainsGithubThenContains() {
|
||||||
|
assertThat(this.repository.iterator())
|
||||||
|
.containsOnly(this.github);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue