Add auto-config for spring-security-oauth2-resource-server

Closes gh-13787
This commit is contained in:
Madhura Bhave 2018-08-06 16:29:39 -07:00
parent 6a2cb883a5
commit d6b6a5f81f
16 changed files with 629 additions and 3 deletions

View File

@ -553,6 +553,11 @@
<artifactId>spring-security-oauth2-client</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-core</artifactId>

View File

@ -0,0 +1,69 @@
/*
* Copyright 2012-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.boot.autoconfigure.security.oauth2.resource;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* OAuth 2.0 resource server properties.
*
* @author Madhura Bhave
*/
@ConfigurationProperties(prefix = "spring.security.oauth2.resource")
public class OAuth2ResourceServerProperties {
private Jwt jwt = new Jwt();
public Jwt getJwt() {
return this.jwt;
}
public void setJwt(Jwt jwt) {
this.jwt = jwt;
}
public static class Jwt {
private Jwk jwk = new Jwk();
public Jwk getJwk() {
return this.jwk;
}
public void setJwk(Jwk jwk) {
this.jwk = jwk;
}
}
public static class Jwk {
/**
* The URI to get verification keys to verify the JWT token.
*/
private String setUri;
public String getSetUri() {
return this.setUri;
}
public void setSetUri(String setUri) {
this.setUri = setUri;
}
}
}

View File

@ -0,0 +1,20 @@
/*
* Copyright 2012-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.
*/
/**
* Support for Spring Security's OAuth 2 resource server.
*/
package org.springframework.boot.autoconfigure.security.oauth2.resource;

View File

@ -0,0 +1,42 @@
/*
* Copyright 2012-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.boot.autoconfigure.security.oauth2.resource.servlet;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerProperties;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
/**
* {@link EnableAutoConfiguration Auto-configuration} for OAuth resource server support.
*
* @author Madhura Bhave
* @since 2.1.0
*/
@Configuration
@AutoConfigureBefore(SecurityAutoConfiguration.class)
@EnableConfigurationProperties(OAuth2ResourceServerProperties.class)
@ConditionalOnClass(JwtAuthenticationToken.class)
@Import({ OAuth2ResourceServerJwkConfiguration.class,
OAuth2ResourceServerWebSecurityConfiguration.class })
public class OAuth2ResourceServerAutoConfiguration {
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 2012-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.boot.autoconfigure.security.oauth2.resource.servlet;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoderJwkSupport;
/**
* Configures a {@link JwtDecoder} when a JWK Set URI is available.
*
* @author Madhura Bhave
*/
@Configuration
class OAuth2ResourceServerJwkConfiguration {
private final OAuth2ResourceServerProperties properties;
public OAuth2ResourceServerJwkConfiguration(
OAuth2ResourceServerProperties properties) {
this.properties = properties;
}
@Bean
@ConditionalOnProperty(name = "spring.security.oauth2.resource.jwt.jwk.set-uri")
@ConditionalOnMissingBean
public JwtDecoder jwtDecoder() {
return new NimbusJwtDecoderJwkSupport(
this.properties.getJwt().getJwk().getSetUri());
}
}

View File

@ -0,0 +1,47 @@
/*
* Copyright 2012-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.boot.autoconfigure.security.oauth2.resource.servlet;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.jwt.JwtDecoder;
/**
* {@link WebSecurityConfigurerAdapter} for OAuth2 resource server support.
*
* @author Madhura Bhave
*/
@Configuration
@ConditionalOnMissingBean(WebSecurityConfigurerAdapter.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
class OAuth2ResourceServerWebSecurityConfiguration {
@Configuration
@ConditionalOnBean(JwtDecoder.class)
static class OAuth2WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().oauth2()
.resourceServer().jwt();
}
}
}

View File

@ -0,0 +1,20 @@
/*
* Copyright 2012-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.
*/
/**
* Auto-configuration for Spring Security's OAuth 2 resource server.
*/
package org.springframework.boot.autoconfigure.security.oauth2.resource.servlet;

View File

@ -105,6 +105,7 @@ org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutorAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\

View File

@ -0,0 +1,118 @@
/*
* Copyright 2012-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.boot.autoconfigure.security.oauth2.resource.servlet;
import java.util.List;
import javax.servlet.Filter;
import org.junit.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoderJwkSupport;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link OAuth2ResourceServerAutoConfiguration}.
*
* @author Madhura Bhave
*/
public class OAuth2ResourceServerAutoConfigurationTests {
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(OAuth2ResourceServerAutoConfiguration.class))
.withUserConfiguration(TestConfig.class);
@Test
public void autoConfigurationShouldConfigureResourceServer() {
this.contextRunner.withPropertyValues(
"spring.security.oauth2.resource.jwt.jwk.set-uri=http://jwk-set-uri.com")
.run((context) -> {
assertThat(context.getBean(JwtDecoder.class))
.isInstanceOf(NimbusJwtDecoderJwkSupport.class);
assertThat(getBearerTokenFilter(context)).isNotNull();
});
}
@Test
public void autoConfigurationWhenJwkSetUriNullShouldNotFail() {
this.contextRunner
.run((context) -> assertThat(getBearerTokenFilter(context)).isNull());
}
@Test
public void jwtDecoderBeanIsConditionalOnMissingBean() {
this.contextRunner.withPropertyValues(
"spring.security.oauth2.resource.jwt.jwk.set-uri=http://jwk-set-uri.com")
.withUserConfiguration(JwtDecoderConfig.class)
.run((context) -> assertThat(getBearerTokenFilter(context)).isNotNull());
}
@Test
public void autoConfigurationShouldBeConditionalOnJwtAuthenticationTokenClass() {
this.contextRunner.withPropertyValues(
"spring.security.oauth2.resource.jwt.jwk.set-uri=http://jwk-set-uri.com")
.withUserConfiguration(JwtDecoderConfig.class)
.withClassLoader(new FilteredClassLoader(JwtAuthenticationToken.class))
.run((context) -> assertThat(getBearerTokenFilter(context)).isNull());
}
@SuppressWarnings("unchecked")
private Filter getBearerTokenFilter(AssertableWebApplicationContext context) {
FilterChainProxy filterChain = (FilterChainProxy) context
.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN);
List<SecurityFilterChain> filterChains = filterChain.getFilterChains();
List<Filter> filters = (List<Filter>) ReflectionTestUtils
.getField(filterChains.get(0), "filters");
return filters.stream()
.filter((f) -> f instanceof BearerTokenAuthenticationFilter).findFirst()
.orElse(null);
}
@Configuration
@EnableWebSecurity
static class TestConfig {
}
@Configuration
@EnableWebSecurity
static class JwtDecoderConfig {
@Bean
public JwtDecoder decoder() {
return mock(JwtDecoder.class);
}
}
}

View File

@ -529,6 +529,9 @@ content into your application. Rather, pick only the properties that you need.
spring.security.oauth2.client.provider.*= # OAuth provider details.
spring.security.oauth2.client.registration.*= # OAuth client registrations.
# SECURITY OAUTH2 RESOURCE SERVER ({sc-spring-boot-autoconfigure}/security/oauth2/resource/OAuth2ResourceServerProperties.{sc-ext}[OAuth2ResourceServerProperties])
spring.security.oauth2.resource.jwt.jwk.set-uri.*= # JWK Set URI
# ----------------------------------------
# DATA PROPERTIES
# ----------------------------------------

View File

@ -3276,12 +3276,26 @@ Provider can be configured with the `issuer-uri`:
[[boot-features-security-oauth2-server]]
==== Server
==== Resource Server
If you have `spring-security-oauth2-resource-server` on your classpath, you can take advantage of
some auto-configuration to make it easy to set up an OAuth2 Resource Server. This configuration
makes use of the properties under `OAuth2ResourceServerProperties`.
For the OAuth2 Resource Server auto-configuration to kick in, you can
provide a bean of type `JwtDecoder` yourself or configure a JWK Set URI as follows:
[source,properties,indent=0]
----
spring.security.oauth2.resource.jwt.jwk.set-uri=https://example.com/oauth2/default/v1/keys
----
==== Authorization Server
Currently, Spring Security does not provide support for implementing an OAuth 2.0
Authorization Server or Resource Server. However, this functionality is available from
Authorization Server. However, this functionality is available from
the https://projects.spring.io/spring-security-oauth/[Spring Security OAuth] project,
which will eventually be superseded by Spring Security completely. Until then, you can
use the `spring-security-oauth2-autoconfigure` module to easily set up an OAuth 2.0 server;
use the `spring-security-oauth2-autoconfigure` module to easily set up an OAuth 2.0 authorization server;
see its https://docs.spring.io/spring-security-oauth2-boot[documentation] for instructions.

View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<!-- Your own application should inherit from spring-boot-starter-parent -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-samples</artifactId>
<version>${revision}</version>
</parent>
<artifactId>spring-boot-sample-oauth2-resource-server</artifactId>
<name>Spring Boot Sample OAuth2 Resource Server</name>
<description>Spring Boot Sample Resource Server</description>
<properties>
<main.basedir>${basedir}/../..</main.basedir>
</properties>
<dependencies>
<!-- Compile -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
<!-- Test -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
<version>3.9.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,31 @@
/*
* Copyright 2012-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 sample.oauth2.resource;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ExampleController {
@GetMapping("/")
public String index(@AuthenticationPrincipal Jwt jwt) {
return String.format("Hello, %s!", jwt.getSubject());
}
}

View File

@ -0,0 +1,28 @@
/*
* Copyright 2012-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 sample.oauth2.resource;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SampleOauth2ResourceServerApplication {
public static void main(String[] args) {
SpringApplication.run(SampleOauth2ResourceServerApplication.class);
}
}

View File

@ -0,0 +1,8 @@
spring:
security:
oauth2:
resource:
jwt:
jwk:
# To run the application, replace this with a valid JWK Set URI
set-uri: https://example.com/oauth2/default/v1/keys

View File

@ -0,0 +1,111 @@
/*
* Copyright 2012-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 sample.oauth2.resource;
import java.io.IOException;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SampleOauth2ResourceServerApplicationTests {
private static MockWebServer server = new MockWebServer();
private static final String VALID_TOKEN = "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0Iiwic2NvcGUiOiJtZXNzYWdlOnJlYWQi"
+ "LCJleHAiOjQ2ODM4MDUxNDF9.h-j6FKRFdnTdmAueTZCdep45e6DPwqM68ZQ8doIJ1exi9YxAlbWzOwId6Bd0L5YmCmp63gGQgsBUBLzwnZQ8kLUgU"
+ "OBEC3UzSWGRqMskCY9_k9pX0iomX6IfF3N0PaYs0WPC4hO1s8wfZQ-6hKQ4KigFi13G9LMLdH58PRMK0pKEvs3gCbHJuEPw-K5ORlpdnleUTQIwIN"
+ "afU57cmK3KocTeknPAM_L716sCuSYGvDl6xUTXO7oPdrXhS_EhxLP6KxrpI1uD4Ea_5OWTh7S0Wx5LLDfU6wBG1DowN20d374zepOIEkR-Jnmr_Ql"
+ "R44vmRqS5ncrF-1R0EGcPX49U6A";
@Autowired
private TestRestTemplate restTemplate;
@BeforeClass
public static void setup() throws Exception {
server.start();
String url = server.url("/.well-known/jwks.json").toString();
server.enqueue(mockResponse());
System.setProperty("spring.security.oauth2.resource.jwt.jwk.set-uri", url);
}
@AfterClass
public static void shutdown() throws IOException {
server.shutdown();
System.clearProperty("spring.security.oauth2.resource.jwt.jwk.set-uri");
}
@Test
public void withValidBearerTokenShouldAllowAccess() {
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(VALID_TOKEN);
HttpEntity<?> request = new HttpEntity<Void>(headers);
ResponseEntity<String> entity = this.restTemplate.exchange("/", HttpMethod.GET,
request, String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
}
@Test
public void withNoBearerTokenShouldNotAllowAccess() {
HttpHeaders headers = new HttpHeaders();
HttpEntity<?> request = new HttpEntity<Void>(headers);
ResponseEntity<String> entity = this.restTemplate.exchange("/", HttpMethod.GET,
request, String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
}
private static MockResponse mockResponse() {
String body = "{\"keys\":[{\"p\":\"2p-ViY7DE9ZrdWQb544m0Jp7Cv03YCSljqfim9pD4ALhObX0OrAznOiowTjwBky9JGffMw"
+ "DBVSfJSD9TSU7aH2sbbfi0bZLMdekKAuimudXwUqPDxrrg0BCyvCYgLmKjbVT3zcdylWSog93CNTxGDPzauu-oc0XPNKCXnaDpNvE\""
+ ",\"kty\":\"RSA\",\"q\":\"sP_QYavrpBvSJ86uoKVGj2AGl78CSsAtpf1ybSY5TwUlorXSdqapRbY69Y271b0aMLzlleUn9ZTBO"
+ "1dlKV2_dw_lPADHVia8z3pxL-8sUhIXLsgj4acchMk4c9YX-sFh07xENnyZ-_TXm3llPLuL67HUfBC2eKe800TmCYVWc9U\",\"d\""
+ ":\"bn1nFxCQT4KLTHqo8mo9HvHD0cRNRNdWcKNnnEQkCF6tKbt-ILRyQGP8O40axLd7CoNVG9c9p_-g4-2kwCtLJNv_STLtwfpCY7"
+ "VN5o6-ZIpfTjiW6duoPrLWq64Hm_4LOBQTiZfUPcLhsuJRHbWqakj-kV_YbUyC2Ocf_dd8IAQcSrAU2SCcDebhDCWwRUFvaa9V5eq0"
+ "851S9goaA-AJz-JXyePH6ZFr8JxmWkWxYZ5kdcMD-sm9ZbxE0CaEk32l4fE4hR-L8x2dDtjWA-ahKCZ091z-gV3HWtR2JOjvxoNRjxUo"
+ "3UxaGiFJHWNIl0EYUJZu1Cb-5wIlEI7wPx5mwQ\",\"e\":\"AQAB\",\"use\":\"sig\",\"kid\":\"one\",\"qi\":\"qS0OK4"
+ "8M2CIAA6_4Wdw4EbCaAfcTLf5Oy9t5BOF_PFUKqoSpZ6JsT5H0a_4zkjt-oI969v78OTlvBKbmEyKO-KeytzHBAA5CsLmVcz0THrMSg6o"
+ "XZqu66MPnvWoZN9FEN5TklPOvBFm8Bg1QZ3k-YMVaM--DLvhaYR95_mqaz50\",\"dp\":\"Too2NozLGD1XrXyhabZvy1E0EuaVFj0UHQ"
+ "PDLSpkZ_2g3BK6Art6T0xmE8RYtmqrKIEIdlI3IliAvyvAx_1D7zWTTRaj-xlZyqJFrnXWL7zj8UxT8PkB-r2E-ILZ3NAi1gxIWezlBTZ8"
+ "M6NfObDFmbTc_3tJkN_raISo8z_ziIE\",\"dq\":\"U0yhSkY5yOsa9YcMoigGVBWSJLpNHtbg5NypjHrPv8OhWbkOSq7WvSstBkF"
+ "k5AtyFvvfZLMLIkWWxxGzV0t6f1MoxBtttLrYYyCxwihiiGFhLbAdSuZ1wnxcqA9bC7UVECvrQmVTpsMs8UupfHKbQBpZ8OWAqrn"
+ "uYNNtG4_4Bt0\",\"n\":\"lygtuZj0lJjqOqIWocF8Bb583QDdq-aaFg8PesOp2-EDda6GqCpL-_NZVOflNGX7XIgjsWHcPsQHs"
+ "V9gWuOzSJ0iEuWvtQ6eGBP5M6m7pccLNZfwUse8Cb4Ngx3XiTlyuqM7pv0LPyppZusfEHVEdeelou7Dy9k0OQ_nJTI3b2E1WBoHC5"
+ "8CJ453lo4gcBm1efURN3LIVc1V9NQY_ESBKVdwqYyoJPEanURLVGRd6cQKn6YrCbbIRHjqAyqOE-z3KmgDJnPriljfR5XhSGyM9eq"
+ "D9Xpy6zu_MAeMJJfSArp857zLPk-Wf5VP9STAcjyfdBIybMKnwBYr2qHMT675hQ\"}]}";
return new MockResponse()
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.setResponseCode(200).setBody(body);
}
}