3 changed files with 230 additions and 0 deletions
@ -0,0 +1,82 @@
@@ -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 @@
@@ -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 @@
@@ -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