From 2dffa2bada158feb6e9df2712589ece68ae8e025 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Wacongne?=
Date: Wed, 13 Mar 2019 12:30:34 +0100
Subject: [PATCH 1/9] gh-6557 @WithMockJwt
---
...ecurity-oauth2-resource-server-test.gradle | 7 +
.../support/oauth2/StringObjectMapHelper.java | 53 ++++
.../support/oauth2/StringParsingHelper.java | 61 ++++
.../context/support/oauth2/WithMockJwt.java | 167 +++++++++++
.../WithMockJwtSecurityContextFactory.java | 74 +++++
.../properties/BooleanPropertyParser.java | 35 +++
.../properties/DoublePropertyParser.java | 35 +++
.../properties/InstantPropertyParser.java | 37 +++
.../properties/IntegerPropertyParser.java | 35 +++
.../oauth2/properties/LongPropertyParser.java | 35 +++
.../oauth2/properties/NoOpPropertyParser.java | 35 +++
.../support/oauth2/properties/Property.java | 83 ++++++
.../oauth2/properties/PropertyParser.java | 37 +++
.../properties/PropertyParsersHelper.java | 261 ++++++++++++++++++
.../properties/StringListPropertyParser.java | 38 +++
.../properties/StringSetPropertyParser.java | 37 +++
.../oauth2/properties/UrlPropertyParser.java | 43 +++
.../main/resources/META-INF/spring.factories | 3 +
...ithMockJwtSecurityContextFactoryTests.java | 131 +++++++++
.../support/oauth2/WithMockJwtTests.java | 96 +++++++
.../properties/PropertyParsersHelperTest.java | 149 ++++++++++
oauth2-test/template.mf | 19 ++
.../OAuth2IntrospectionClaimNames.java | 2 +-
...y-samples-boot-oauth2resourceserver.gradle | 1 +
.../OAuth2ResourceServerControllerTest.java | 60 ++++
25 files changed, 1533 insertions(+), 1 deletion(-)
create mode 100644 oauth2-test/spring-security-oauth2-resource-server-test.gradle
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/StringObjectMapHelper.java
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/StringParsingHelper.java
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwt.java
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactory.java
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/BooleanPropertyParser.java
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/DoublePropertyParser.java
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/InstantPropertyParser.java
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/IntegerPropertyParser.java
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/LongPropertyParser.java
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/NoOpPropertyParser.java
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/Property.java
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/PropertyParser.java
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/PropertyParsersHelper.java
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/StringListPropertyParser.java
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/StringSetPropertyParser.java
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/UrlPropertyParser.java
create mode 100644 oauth2-test/src/main/resources/META-INF/spring.factories
create mode 100644 oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactoryTests.java
create mode 100644 oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtTests.java
create mode 100644 oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/properties/PropertyParsersHelperTest.java
create mode 100644 oauth2-test/template.mf
create mode 100644 samples/boot/oauth2resourceserver/src/test/java/sample/OAuth2ResourceServerControllerTest.java
diff --git a/oauth2-test/spring-security-oauth2-resource-server-test.gradle b/oauth2-test/spring-security-oauth2-resource-server-test.gradle
new file mode 100644
index 00000000000..1395227adff
--- /dev/null
+++ b/oauth2-test/spring-security-oauth2-resource-server-test.gradle
@@ -0,0 +1,7 @@
+apply plugin: 'io.spring.convention.spring-module'
+
+dependencies {
+ compile project(':spring-security-test')
+ compile project(':spring-security-oauth2-resource-server')
+ compile project(':spring-security-oauth2-jose')
+}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/StringObjectMapHelper.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/StringObjectMapHelper.java
new file mode 100644
index 00000000000..5111a20cc65
--- /dev/null
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/StringObjectMapHelper.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ * 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.test.context.support.oauth2;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ */
+class StringObjectMapHelper {
+
+ public static final Map putIfNotEmpty(String key, String value,
+ Map map) {
+ if (value != null && !value.isEmpty()) {
+ map.put(key, value);
+ }
+ return map;
+ }
+
+ public static final Map putIfNotEmpty(String key, List value,
+ Map map) {
+ if (value != null && !value.isEmpty()) {
+ map.put(key, value);
+ }
+ return map;
+ }
+
+ public static final Map putIfNotEmpty(String key, T value,
+ Map map) {
+ if (value != null) {
+ map.put(key, value);
+ }
+ return map;
+ }
+
+}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/StringParsingHelper.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/StringParsingHelper.java
new file mode 100644
index 00000000000..e21e3f37ae7
--- /dev/null
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/StringParsingHelper.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ * 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.test.context.support.oauth2;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.time.Instant;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+
+/**
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ */
+class StringParsingHelper {
+
+ public static String nullIfEmpty(String str) {
+ return str == null || str.isEmpty() ? null : str;
+ }
+
+ public static Instant intant(String str) {
+ return str == null || str.isEmpty() ? null : Instant.parse(str);
+ }
+
+ public static URL url(String str) throws MalformedURLException {
+ return str == null || str.isEmpty() ? null : new URL(str);
+ }
+
+ public static List stringList(String[] stringArr) {
+ return Stream.of(stringArr).collect(Collectors.toList());
+ }
+
+ public static Set stringSet(String[] stringArr) {
+ return Stream.of(stringArr).collect(Collectors.toSet());
+ }
+
+ public static Set grantedAuthorities(String[] stringArr) {
+ return Stream.of(stringArr).map(SimpleGrantedAuthority::new)
+ .collect(Collectors.toSet());
+ }
+
+}
\ No newline at end of file
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwt.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwt.java
new file mode 100644
index 00000000000..e589a274efd
--- /dev/null
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwt.java
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ * 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.test.context.support.oauth2;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.core.annotation.AliasFor;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.oauth2.jwt.Jwt;
+import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
+import org.springframework.security.test.context.support.TestExecutionEvent;
+import org.springframework.security.test.context.support.WithSecurityContext;
+import org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener;
+import org.springframework.security.test.context.support.oauth2.properties.Property;
+import org.springframework.security.test.context.support.oauth2.properties.PropertyParser;
+import org.springframework.security.test.context.support.oauth2.properties.PropertyParsersHelper;
+import org.springframework.test.context.TestContext;
+import org.springframework.test.web.servlet.MockMvc;
+
+/**
+ *
+ * A lot like
+ * {@link org.springframework.security.test.context.support.WithMockUser @WithMockUser}:
+ * when used with {@link WithSecurityContextTestExecutionListener} this annotation can be
+ * added to a test method to emulate running with a mocked authentication created out of a
+ * {@link Jwt JWT}.
+ *
+ *
+ * Main steps are:
+ *
+ *
+ *
A {@link Jwt JWT} is created as per this annotation {@code name} (forces
+ * {@code subject} claim), {@code headers} and {@code claims}
+ *
A {@link JwtAuthenticationToken JwtAuthenticationToken} is then created and fed
+ * with this new JWT token
+ *
An empty {@link SecurityContext} is instantiated and populated with this
+ * {@code JwtAuthenticationToken}
+ *
+ *
+ * As a result, the {@link Authentication} {@link MockMvc} gets from security context will
+ * have the following properties:
+ *
+ *
+ *
{@link Authentication#getPrincipal() getPrincipal()} returns a {@link Jwt}
+ *
{@link Authentication#getName() getName()} returns the JWT {@code subject} claim
+ * (set from this annotation {@code name} value)
+ *
{@link Authentication#getAuthorities() authorities} will be a collection of
+ * {@link SimpleGrantedAuthority} as defined by this annotation {@code authorities}
+ *
+ *
+ * Sample Usage:
+ *
+ *
+ * @WithMockJwt
+ * @Test
+ * public void testSomethingWithDefaultJwtAuthentication() {
+ * //no authority
+ * //single {@link DEFAULT_HEADER_NAME} header (can't be empty)
+ * //"sub" claim (subject) with {@link DEFAULT_AUTH_NAME} as value
+ * ...
+ * }
+ *
+ * @WithMockJwt(
+ * authorities = {"ROLE_USER", "ROLE_ADMIN"},
+ * name = "user",
+ * headers = { @Property(name = "foo", value = "bar") },
+ * claims = { @Property(name = "machin", value = "chose") })
+ * @Test
+ * public void testSomethingWithCustomJwtAuthentication() {
+ * //two authorities
+ * //single "foo" header with "bar" as value
+ * //"machin" claim with "chose" as value
+ * //"sub" claim (subject) with "user" as value
+ * ...
+ * }
+ *
+ *
+ * @see Property
+ * @see PropertyParser
+ * @see PropertyParsersHelper#DEFAULT_PARSERS
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ */
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@Documented
+@WithSecurityContext(factory = WithMockJwtSecurityContextFactory.class)
+public @interface WithMockJwt {
+ public static final String DEFAULT_AUTH_NAME = "user";
+ public static final String DEFAULT_HEADER_NAME = "alg";
+ public static final String DEFAULT_HEADER_VALUE = "test-algorythm";
+
+ /**
+ * Alias for authorities
+ * @return Authorities the client is to be granted
+ */
+ @AliasFor("authorities")
+ String[] value() default {};
+
+ /**
+ * Alias for value
+ * @return Authorities the client is to be granted
+ */
+ @AliasFor("value")
+ String[] authorities() default {};
+
+ /**
+ * To be used both as authentication {@code Principal} name and token {@code username}
+ * attribute.
+ * @return Resource owner name
+ */
+ String name() default DEFAULT_AUTH_NAME;
+
+ /**
+ * @return JWT claims
+ */
+ Property[] claims() default {};
+
+ /**
+ * Of little use at unit test time...
+ * @return JWT headers
+ */
+ Property[] headers() default {
+ @Property(name = DEFAULT_HEADER_NAME, value = DEFAULT_HEADER_VALUE) };
+
+ /**
+ * {@link PropertyParsersHelper#DEFAULT_PARSERS Defaulted parsers} are provided for
+ * most common value types.
+ *
+ * @return parsers to add to default ones (or override)
+ *
+ * @see PropertyParsersHelper#DEFAULT_PARSERS
+ */
+ String[] additionalParsers() default {};
+
+ /**
+ * Determines when the {@link SecurityContext} is setup. The default is before
+ * {@link TestExecutionEvent#TEST_METHOD} which occurs during
+ * {@link org.springframework.test.context.TestExecutionListener#beforeTestMethod(TestContext)}
+ * @return the {@link TestExecutionEvent} to initialize before
+ */
+ @AliasFor(annotation = WithSecurityContext.class)
+ TestExecutionEvent setupBefore() default TestExecutionEvent.TEST_METHOD;
+}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactory.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactory.java
new file mode 100644
index 00000000000..f6d5dd07ebb
--- /dev/null
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactory.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ * 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.test.context.support.oauth2;
+
+import static org.springframework.security.test.context.support.oauth2.StringObjectMapHelper.putIfNotEmpty;
+import static org.springframework.security.test.context.support.oauth2.StringParsingHelper.grantedAuthorities;
+
+import java.time.Instant;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.oauth2.jwt.Jwt;
+import org.springframework.security.oauth2.jwt.JwtClaimNames;
+import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
+import org.springframework.security.test.context.support.WithSecurityContextFactory;
+import org.springframework.security.test.context.support.oauth2.properties.PropertyParsersHelper;
+
+/**
+ * Create a {@link org.springframework.security.core.context.SecurityContext
+ * SecurityContext} populated with a
+ * {@link org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken
+ * JwtAuthenticationToken} containing a {@link org.springframework.security.oauth2.jwt.Jwt
+ * JWT} as described by
+ * {@link org.springframework.security.test.context.support.oauth2.WithMockJwt @WithMockJwt}
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ */
+public final class WithMockJwtSecurityContextFactory
+ implements WithSecurityContextFactory {
+ public static final String DEFAULT_TOKEN_VALUE = "test.jwt.value";
+
+ @Override
+ public SecurityContext createSecurityContext(final WithMockJwt annotation) {
+ final PropertyParsersHelper propertyParsers = PropertyParsersHelper
+ .withDefaultParsers(annotation.additionalParsers());
+
+ final Map headers = propertyParsers.parse(annotation.headers());
+
+ Map claims = propertyParsers.parse(annotation.claims());
+ if (claims.containsKey(JwtClaimNames.SUB)) {
+ throw new RuntimeException(JwtClaimNames.SUB
+ + " claim is not configurable (forced to @WithMockJwt.name)");
+ }
+ else {
+ claims = new HashMap<>(claims);
+ putIfNotEmpty(JwtClaimNames.SUB, annotation.name(), claims);
+ }
+
+ final SecurityContext context = SecurityContextHolder.createEmptyContext();
+ context.setAuthentication(new JwtAuthenticationToken(
+ new Jwt(DEFAULT_TOKEN_VALUE, (Instant) claims.get(JwtClaimNames.IAT),
+ (Instant) claims.get(JwtClaimNames.EXP), headers, claims),
+ grantedAuthorities(annotation.authorities())));
+
+ return context;
+ }
+}
\ No newline at end of file
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/BooleanPropertyParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/BooleanPropertyParser.java
new file mode 100644
index 00000000000..023f88b4406
--- /dev/null
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/BooleanPropertyParser.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ * 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.test.context.support.oauth2.properties;
+
+/**
+ * Turns an annotation String value into a Boolean
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ */
+public class BooleanPropertyParser implements PropertyParser {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Boolean parse(String value) {
+ return Boolean.valueOf(value);
+ }
+
+}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/DoublePropertyParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/DoublePropertyParser.java
new file mode 100644
index 00000000000..0d2a4d2cfdf
--- /dev/null
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/DoublePropertyParser.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ * 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.test.context.support.oauth2.properties;
+
+/**
+ * Turns an annotation String value into a Double
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ */
+public class DoublePropertyParser implements PropertyParser {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Double parse(String value) {
+ return Double.valueOf(value);
+ }
+
+}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/InstantPropertyParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/InstantPropertyParser.java
new file mode 100644
index 00000000000..2317227ffe2
--- /dev/null
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/InstantPropertyParser.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ * 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.test.context.support.oauth2.properties;
+
+import java.time.Instant;
+
+/**
+ * Turns an annotation String value into an {@link java.time.Instant Instant}
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ */
+public class InstantPropertyParser implements PropertyParser {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Instant parse(String value) {
+ return Instant.parse(value);
+ }
+
+}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/IntegerPropertyParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/IntegerPropertyParser.java
new file mode 100644
index 00000000000..767fa2184df
--- /dev/null
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/IntegerPropertyParser.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ * 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.test.context.support.oauth2.properties;
+
+/**
+ * Turns an annotation String value into an Integer
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ */
+public class IntegerPropertyParser implements PropertyParser {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Integer parse(String value) {
+ return Integer.valueOf(value);
+ }
+
+}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/LongPropertyParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/LongPropertyParser.java
new file mode 100644
index 00000000000..2771cf72e86
--- /dev/null
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/LongPropertyParser.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ * 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.test.context.support.oauth2.properties;
+
+/**
+ * Turns an annotation String value into a Long
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ */
+public class LongPropertyParser implements PropertyParser {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Long parse(String value) {
+ return Long.valueOf(value);
+ }
+
+}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/NoOpPropertyParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/NoOpPropertyParser.java
new file mode 100644
index 00000000000..261ada9b3d6
--- /dev/null
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/NoOpPropertyParser.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ * 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.test.context.support.oauth2.properties;
+
+/**
+ * Leaves an annotation String value untouched
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ */
+public class NoOpPropertyParser implements PropertyParser {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String parse(String value) {
+ return value;
+ }
+
+}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/Property.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/Property.java
new file mode 100644
index 00000000000..4b22cdd5c1a
--- /dev/null
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/Property.java
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ * 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.test.context.support.oauth2.properties;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ *
+ * Annotation to create an entry in a {@link java.util.Map Map<String, Object>} such
+ * as {@link org.springframework.security.oauth2.jwt.Jwt JWT} headers or claims.
+ *
+ *
+ * See
+ * {@link org.springframework.security.test.context.support.oauth2.properties.PropertyParser
+ * PropertyParser} and its already provided implementations
+ *
an {@code audience} claim with a value being a {@code List} with two
+ * entries
+ *
an {@code issuer} claim with a value being a {@code java.net.URL} instance
+ *
a {@code machin} claim with {@code chose} String as value (default parser is
+ * {@link org.springframework.security.test.context.support.oauth2.properties.NoOpPropertyParser
+ * NoOpPropertyParser})
+ *
a {@code truc} claim whith an instance of what {@code your.fancy.ParserImpl} is
+ * designed to build from {@code bidule} string as value
+ *
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ */
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Property {
+
+ /**
+ * @return the key in the {@link java.util.Map Map<String, Object>}
+ */
+ String name();
+
+ /**
+ * @return a value to be transformed using "parser" before being put as value in
+ * {@link java.util.Map Map<String, Object>}
+ */
+ String value();
+
+ /**
+ * @return a
+ * {@link org.springframework.security.test.context.support.oauth2.properties.PropertyParser
+ * PropertyParser} implementation class name
+ */
+ String parser() default "org.springframework.security.test.context.support.oauth2.properties.NoOpPropertyParser";
+
+}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/PropertyParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/PropertyParser.java
new file mode 100644
index 00000000000..272705200da
--- /dev/null
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/PropertyParser.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ * 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.test.context.support.oauth2.properties;
+
+/**
+ * De-serializes an annotation String value into an Object of type T
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ * @param what
+ * {@link org.springframework.security.test.context.support.oauth2.properties.Property#value() @Property.value}
+ * should be turned into
+ *
+ */
+public interface PropertyParser {
+
+ /**
+ * @param value String to de-serialize
+ * @return an Object
+ */
+ T parse(String value);
+
+}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/PropertyParsersHelper.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/PropertyParsersHelper.java
new file mode 100644
index 00000000000..297bbb2ce06
--- /dev/null
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/properties/PropertyParsersHelper.java
@@ -0,0 +1,261 @@
+/*
+ * 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.
+ * 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.test.context.support.oauth2.properties;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.BinaryOperator;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * Helps turn a
+ * {@link org.springframework.security.test.context.support.oauth2.properties.Property @Property}
+ * array into a {@link java.util.Map Map<String, Object>}
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ */
+public class PropertyParsersHelper {
+ /**
+ *
+ *
{@link org.springframework.security.test.context.support.oauth2.properties.NoOpPropertyParser
+ * NoOpPropertyParser} => keeps value as is.
* Annotation to create an entry in a {@link java.util.Map Map<String, Object>} such as
* {@link org.springframework.security.oauth2.jwt.Jwt JWT} headers or claims.
*
*
- * {@link #parser()} can be referenced either by fully qualified name or simple name.
+ * {@link #parserOverride()} can be referenced either by fully qualified name or simple name.
*
*
- * See {@link Parser} and its already provided implementations: {@link AttributeParsersHelper#DEFAULT_PARSERS}
+ * See {@link AttributeValueParser} and its already provided implementations:
+ * {@link AttributeParsersHelper#DEFAULT_PARSERS}
*
an {@code audience} claim with a value being a {@code List} with two entries
*
an {@code issuer} claim with a value being a {@code java.net.URL} instance
*
a {@code machin} claim with {@code chose} String as value (default parser is
- * {@link org.springframework.security.test.context.support.oauth2.attributes.NoOpStringParser NoOpStringParser})
each {@link org.springframework.security.test.context.support.oauth2.attributes.Attribute#value() value()} is
- * parsed according to {@link org.springframework.security.test.context.support.oauth2.attributes.Attribute#parser()
+ * parsed according to
+ * {@link org.springframework.security.test.context.support.oauth2.attributes.Attribute#parserOverride()
* parser()}
*
obtained values are associated with
* {@link org.springframework.security.test.context.support.oauth2.attributes.Attribute#name() name()}
@@ -153,26 +185,30 @@ public Map parse(final Attribute... properties) {
}
/**
- * Instantiates default {@link org.springframework.security.test.context.support.oauth2.attributes.Parser Parser}s
- * plus all provided ones (using default constructor)
+ * Instantiates default
+ * {@link org.springframework.security.test.context.support.oauth2.attributes.AttributeValueParser
+ * AttributeValueParser}s plus all provided ones (using default constructor)
*
- * @param additionalParserNames {@link org.springframework.security.test.context.support.oauth2.attributes.Parser
- * Parser} implementations class names to add to
+ * @param additionalParserNames
+ * {@link org.springframework.security.test.context.support.oauth2.attributes.AttributeValueParser
+ * AttributeValueParser} implementations class names to add to
* {@link org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelper#DEFAULT_PARSERS
* default ones}
- * @return helper instance with provided parsers plus default ones
+ * @return helper instance with provided attributeValueParsers plus default ones
*/
public static AttributeParsersHelper withDefaultParsers(final String... additionalParserNames) {
return new AttributeParsersHelper(DEFAULT_PARSERS, additionalParserNames);
}
/**
- * Instantiates all provided {@link org.springframework.security.test.context.support.oauth2.attributes.Parser
- * Parser}s using default constructor
+ * Instantiates all provided
+ * {@link org.springframework.security.test.context.support.oauth2.attributes.AttributeValueParser
+ * AttributeValueParser}s using default constructor
*
- * @param allParserNames {@link org.springframework.security.test.context.support.oauth2.attributes.Parser Parser}
- * implementations class names
- * @return helper instance with provided parsers only
+ * @param allParserNames
+ * {@link org.springframework.security.test.context.support.oauth2.attributes.AttributeValueParser
+ * AttributeValueParser} implementations class names
+ * @return helper instance with provided attributeValueParsers only
*/
public static AttributeParsersHelper withoutDefaultParsers(final String... allParserNames) {
return new AttributeParsersHelper(Collections.emptySet(), allParserNames);
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/Parser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeValueParser.java
similarity index 87%
rename from oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/Parser.java
rename to oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeValueParser.java
index 1f362031386..2a9941cf054 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/Parser.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeValueParser.java
@@ -17,16 +17,15 @@
* @author Jérôme Wacongne <ch4mp@c4-soft.com>
* @since 5.2.0
*
- * @param type before parsing (source)
* @param type after parsing (target)
*
*/
-public interface Parser {
+public interface AttributeValueParser {
/**
* @param value to de-serialize
* @return an Object
*/
- TO_TYPE parse(FROM_TYPE value);
+ TO_TYPE parse(String value);
}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/BooleanStringParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/BooleanParser.java
similarity index 94%
rename from oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/BooleanStringParser.java
rename to oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/BooleanParser.java
index 4eff10ef271..2db0fa31920 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/BooleanStringParser.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/BooleanParser.java
@@ -21,7 +21,7 @@
* @since 5.2.0
*
*/
-public class BooleanStringParser implements Parser {
+public class BooleanParser implements AttributeValueParser {
/**
* {@inheritDoc}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/DoubleStringParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/DoubleParser.java
similarity index 94%
rename from oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/DoubleStringParser.java
rename to oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/DoubleParser.java
index d12ccba842d..da7ead4db3c 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/DoubleStringParser.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/DoubleParser.java
@@ -21,7 +21,7 @@
* @since 5.2.0
*
*/
-public class DoubleStringParser implements Parser {
+public class DoubleParser implements AttributeValueParser {
/**
* {@inheritDoc}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/InstantStringParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/InstantParser.java
similarity index 94%
rename from oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/InstantStringParser.java
rename to oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/InstantParser.java
index cba7f6513f4..a2c3c6798ff 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/InstantStringParser.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/InstantParser.java
@@ -23,7 +23,7 @@
* @since 5.2.0
*
*/
-public class InstantStringParser implements Parser {
+public class InstantParser implements AttributeValueParser {
/**
* {@inheritDoc}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/IntegerStringParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/IntegerParser.java
similarity index 94%
rename from oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/IntegerStringParser.java
rename to oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/IntegerParser.java
index d8300d2f56e..f4bd76f8c00 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/IntegerStringParser.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/IntegerParser.java
@@ -21,7 +21,7 @@
* @since 5.2.0
*
*/
-public class IntegerStringParser implements Parser {
+public class IntegerParser implements AttributeValueParser {
/**
* {@inheritDoc}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/LongStringParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/LongParser.java
similarity index 94%
rename from oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/LongStringParser.java
rename to oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/LongParser.java
index 94a5b0f6412..405b614fe85 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/LongStringParser.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/LongParser.java
@@ -21,7 +21,7 @@
* @since 5.2.0
*
*/
-public class LongStringParser implements Parser {
+public class LongParser implements AttributeValueParser {
/**
* {@inheritDoc}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/NoOpStringParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/NoOpParser.java
similarity index 93%
rename from oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/NoOpStringParser.java
rename to oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/NoOpParser.java
index bbd27d5208f..6f6f27bb2a5 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/NoOpStringParser.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/NoOpParser.java
@@ -19,7 +19,7 @@
* @since 5.2.0
*
*/
-public class NoOpStringParser implements Parser {
+public class NoOpParser implements AttributeValueParser {
/**
* {@inheritDoc}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/StringListStringParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/StringListParser.java
similarity index 94%
rename from oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/StringListStringParser.java
rename to oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/StringListParser.java
index aeca5ad1ccd..c50d85e9ee3 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/StringListStringParser.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/StringListParser.java
@@ -22,7 +22,7 @@
* @since 5.2.0
*
*/
-public class StringListStringParser implements Parser> {
+public class StringListParser implements AttributeValueParser> {
/**
* {@inheritDoc}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/StringSetStringParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/StringSetParser.java
similarity index 94%
rename from oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/StringSetStringParser.java
rename to oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/StringSetParser.java
index 41d5136d0d3..7dcf89a92ab 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/StringSetStringParser.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/StringSetParser.java
@@ -22,7 +22,7 @@
* @since 5.2.0
*
*/
-public class StringSetStringParser implements Parser> {
+public class StringSetParser implements AttributeValueParser> {
/**
* {@inheritDoc}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/UrlStringParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/UrlParser.java
similarity index 95%
rename from oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/UrlStringParser.java
rename to oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/UrlParser.java
index 1e7a18cffbd..83a02ddcb04 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/UrlStringParser.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/UrlParser.java
@@ -24,7 +24,7 @@
* @since 5.2.0
*
*/
-public class UrlStringParser implements Parser {
+public class UrlParser implements AttributeValueParser {
/**
* {@inheritDoc}
diff --git a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactoryTests.java b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactoryTests.java
index 11105179a5e..0219ad81ba6 100644
--- a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactoryTests.java
+++ b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactoryTests.java
@@ -27,7 +27,8 @@
import org.springframework.security.oauth2.jwt.JwtClaimNames;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.security.test.context.support.oauth2.attributes.Attribute;
-import org.springframework.security.test.context.support.oauth2.attributes.Parser;
+import org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelper.TargetType;
+import org.springframework.security.test.context.support.oauth2.attributes.AttributeValueParser;
public class WithMockJwtSecurityContextFactoryTests {
@@ -62,13 +63,13 @@ private static class CustomAdvanced {
authorities = { "machin", "chose" },
headers = { @Attribute(name = "a", value = "1") },
claims = {
- @Attribute(name = JwtClaimNames.AUD, value = "test audience", parser = "StringListStringParser"),
- @Attribute(name = JwtClaimNames.AUD, value = "other audience", parser = "StringListStringParser"),
- @Attribute(name = JwtClaimNames.ISS, value = "https://test-issuer.org", parser = "UrlStringParser"),
+ @Attribute(name = JwtClaimNames.AUD, value = "test audience", parseTo = TargetType.STRING_LIST),
+ @Attribute(name = JwtClaimNames.AUD, value = "other audience", parseTo = TargetType.STRING_LIST),
+ @Attribute(name = JwtClaimNames.ISS, value = "https://test-issuer.org", parseTo = TargetType.URL),
@Attribute(
name = JwtClaimNames.IAT,
value = "2019-03-03T22:35:00.0Z",
- parser = "InstantStringParser"),
+ parseTo = TargetType.INSTANT),
@Attribute(name = JwtClaimNames.JTI, value = "test ID"),
@Attribute(name = "custom-claim", value = "foo") },
additionalParsers = {
@@ -242,7 +243,7 @@ public void custom() throws Exception {
}
- public static final class FooParser implements Parser {
+ public static final class FooParser implements AttributeValueParser {
@Override
public String parse(final String value) {
diff --git a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeParsersHelperTest.java b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeParsersHelperTest.java
index 691a398534e..f5e8a93f4ee 100644
--- a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeParsersHelperTest.java
+++ b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeParsersHelperTest.java
@@ -22,92 +22,18 @@
import org.junit.Test;
import org.springframework.core.annotation.AnnotationUtils;
-import org.springframework.security.test.context.support.oauth2.attributes.Attribute;
-import org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelper;
-import org.springframework.security.test.context.support.oauth2.attributes.BooleanStringParser;
-import org.springframework.security.test.context.support.oauth2.attributes.DoubleStringParser;
-import org.springframework.security.test.context.support.oauth2.attributes.IntegerStringParser;
-import org.springframework.security.test.context.support.oauth2.attributes.LongStringParser;
-import org.springframework.security.test.context.support.oauth2.attributes.NoOpStringParser;
-import org.springframework.security.test.context.support.oauth2.attributes.Parser;
-import org.springframework.security.test.context.support.oauth2.attributes.StringListStringParser;
-import org.springframework.security.test.context.support.oauth2.attributes.StringSetStringParser;
-import org.springframework.security.test.context.support.oauth2.attributes.UrlStringParser;
+import org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelper.TargetType;
public class AttributeParsersHelperTest {
- @Test
- public void helperWithDefaultParsers() {
- final AttributeParsersHelper actual = AttributeParsersHelper.withDefaultParsers(
- "org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelperTest$SomeTypeParser",
- "org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelperTest$OtherTypeParser");
-
- assertThat(actual.getParser(NoOpStringParser.class.getName())).isInstanceOf(NoOpStringParser.class);
- assertThat(actual.getParser("NoOpStringParser")).isInstanceOf(NoOpStringParser.class);
- assertThat(actual.getParser(BooleanStringParser.class.getName())).isInstanceOf(BooleanStringParser.class);
- assertThat(actual.getParser("BooleanStringParser")).isInstanceOf(BooleanStringParser.class);
- assertThat(actual.getParser(DoubleStringParser.class.getName())).isInstanceOf(DoubleStringParser.class);
- assertThat(actual.getParser("DoubleStringParser")).isInstanceOf(DoubleStringParser.class);
- assertThat(
- actual.getParser(
- org.springframework.security.test.context.support.oauth2.attributes.InstantStringParser.class
- .getName())).isInstanceOf(
- org.springframework.security.test.context.support.oauth2.attributes.InstantStringParser.class);
- assertThat(actual.getParser("InstantStringParser")).isInstanceOf(
- org.springframework.security.test.context.support.oauth2.attributes.InstantStringParser.class);
- assertThat(actual.getParser(IntegerStringParser.class.getName())).isInstanceOf(IntegerStringParser.class);
- assertThat(actual.getParser("IntegerStringParser")).isInstanceOf(IntegerStringParser.class);
- assertThat(actual.getParser(LongStringParser.class.getName())).isInstanceOf(LongStringParser.class);
- assertThat(actual.getParser("LongStringParser")).isInstanceOf(LongStringParser.class);
- assertThat(actual.getParser(StringListStringParser.class.getName())).isInstanceOf(StringListStringParser.class);
- assertThat(actual.getParser("StringListStringParser")).isInstanceOf(StringListStringParser.class);
- assertThat(actual.getParser(StringSetStringParser.class.getName())).isInstanceOf(StringSetStringParser.class);
- assertThat(actual.getParser("StringSetStringParser")).isInstanceOf(StringSetStringParser.class);
- assertThat(actual.getParser(UrlStringParser.class.getName())).isInstanceOf(UrlStringParser.class);
- assertThat(actual.getParser("UrlStringParser")).isInstanceOf(UrlStringParser.class);
- assertThat(actual.getParser(SomeTypeParser.class.getName())).isInstanceOf(SomeTypeParser.class);
- assertThat(actual.getParser("SomeTypeParser")).isInstanceOf(SomeTypeParser.class);
- assertThat(actual.getParser(OtherTypeParser.class.getName())).isInstanceOf(OtherTypeParser.class);
- assertThat(actual.getParser("OtherTypeParser")).isInstanceOf(OtherTypeParser.class);
- }
-
- @Test
- public void helperWithoutDefaultParsers() {
- final AttributeParsersHelper actual = AttributeParsersHelper.withoutDefaultParsers(
- "org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelperTest$SomeTypeParser",
- "org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelperTest$OtherTypeParser");
- assertThat(actual.getParser(NoOpStringParser.class.getName())).isNull();
- assertThat(actual.getParser("NoOpStringParser")).isNull();
- assertThat(actual.getParser(BooleanStringParser.class.getName())).isNull();
- assertThat(actual.getParser("BooleanStringParser")).isNull();
- assertThat(actual.getParser(DoubleStringParser.class.getName())).isNull();
- assertThat(actual.getParser("DoubleStringParser")).isNull();
- assertThat(actual.getParser(InstantStringParser.class.getName())).isNull();
- assertThat(actual.getParser("InstantStringParser")).isNull();
- assertThat(actual.getParser(IntegerStringParser.class.getName())).isNull();
- assertThat(actual.getParser("IntegerStringParser")).isNull();
- assertThat(actual.getParser(LongStringParser.class.getName())).isNull();
- assertThat(actual.getParser("LongStringParser")).isNull();
- assertThat(actual.getParser(StringListStringParser.class.getName())).isNull();
- assertThat(actual.getParser("StringListStringParser")).isNull();
- assertThat(actual.getParser(StringSetStringParser.class.getName())).isNull();
- assertThat(actual.getParser("StringSetStringParser")).isNull();
- assertThat(actual.getParser(UrlStringParser.class.getName())).isNull();
- assertThat(actual.getParser("UrlStringParser")).isNull();
- assertThat(actual.getParser(SomeTypeParser.class.getName())).isInstanceOf(SomeTypeParser.class);
- assertThat(actual.getParser("SomeTypeParser")).isInstanceOf(SomeTypeParser.class);
- assertThat(actual.getParser(OtherTypeParser.class.getName())).isInstanceOf(OtherTypeParser.class);
- assertThat(actual.getParser("OtherTypeParser")).isInstanceOf(OtherTypeParser.class);
- }
-
- @Attribute(name = "a", value = "bidule", parser = "SomeTypeParser")
+ @Attribute(name = "a", value = "bidule", parserOverride = "SomeTypeParser")
private static final class AProperty {
}
@Attribute(
name = "b",
value = "chose",
- parser = "org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelperTest$SomeTypeParser")
+ parserOverride = "org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelperTest$SomeTypeParser")
private static final class BProperty {
}
@@ -125,11 +51,11 @@ public void parsePropertiesWithDistinctNames() {
}
- @Attribute(name = "a", value = "bidule", parser = "StringListStringParser")
+ @Attribute(name = "a", value = "bidule", parseTo = TargetType.STRING_LIST)
private static final class CProperty {
}
- @Attribute(name = "a", value = "chose", parser = "StringListStringParser")
+ @Attribute(name = "a", value = "chose", parseTo = TargetType.STRING_LIST)
private static final class DProperty {
}
@@ -148,14 +74,14 @@ public void parsePropertiesWithSameNameAccumulatesValues() {
}
- @Attribute(name = "instant-millis", value = "12345678", parser = "InstantStringParser")
+ @Attribute(name = "instant-millis", value = "12345678", parserOverride = "InstantParser")
private static final class EProperty {
}
@Test
public void parsePropertiesUsesParseroverrides() {
final AttributeParsersHelper helper = AttributeParsersHelper.withDefaultParsers(
- "org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelperTest$InstantStringParser");
+ "org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelperTest$InstantParser");
final Attribute propertyAnnotation = AnnotationUtils.findAnnotation(EProperty.class, Attribute.class);
@@ -166,14 +92,14 @@ public void parsePropertiesUsesParseroverrides() {
}
- public static final class SomeTypeParser implements Parser {
+ public static final class SomeTypeParser implements AttributeValueParser {
@Override
public String parse(final String value) {
return value;
}
}
- public static final class OtherTypeParser implements Parser> {
+ public static final class OtherTypeParser implements AttributeValueParser> {
@Override
public Collection parse(final String value) {
return Collections.singletonList(value);
@@ -183,7 +109,7 @@ public Collection parse(final String value) {
/**
* custom Instant mapper designed to override default one
*/
- public static final class InstantStringParser implements Parser {
+ public static final class InstantParser implements AttributeValueParser {
@Override
public Instant parse(final String value) {
return Instant.ofEpochMilli(Long.valueOf(value));
From c0ce0adfd13eb25223a27d4844482e4474ffc24e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Wacongne?=
Date: Tue, 19 Mar 2019 15:57:44 +0100
Subject: [PATCH 4/9] missing comments
---
.../support/oauth2/AuthoritiesAndScopes.java | 19 +++++++++++++++++++
.../support/oauth2/AnnotationHelperTest.java | 18 ++++++++++++++++++
.../oauth2/AuthoritiesAndScopesTest.java | 18 ++++++++++++++++++
...ithMockJwtSecurityContextFactoryTests.java | 6 ++++++
.../support/oauth2/WithMockJwtTests.java | 6 ++++++
.../AttributeParsersHelperTest.java | 6 ++++++
6 files changed, 73 insertions(+)
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AuthoritiesAndScopes.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AuthoritiesAndScopes.java
index f8ffbeac431..9d90e862281 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AuthoritiesAndScopes.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AuthoritiesAndScopes.java
@@ -1,3 +1,15 @@
+/*
+ * 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. 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.test.context.support.oauth2;
import static org.springframework.security.test.context.support.oauth2.AnnotationHelper.putIfNotEmpty;
@@ -12,6 +24,13 @@
import org.springframework.security.core.authority.SimpleGrantedAuthority;
+/**
+ * Helps merging {@code authorities} and {@code scope}.
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ */
final class AuthoritiesAndScopes {
public final Set authorities;
public final Set scopes;
diff --git a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AnnotationHelperTest.java b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AnnotationHelperTest.java
index 1551ea8101d..2953e476156 100644
--- a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AnnotationHelperTest.java
+++ b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AnnotationHelperTest.java
@@ -1,3 +1,15 @@
+/*
+ * 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. 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.test.context.support.oauth2;
import static org.assertj.core.api.Assertions.assertThat;
@@ -12,6 +24,12 @@
import org.junit.Test;
+/**
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ */
public class AnnotationHelperTest {
@Test
diff --git a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AuthoritiesAndScopesTest.java b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AuthoritiesAndScopesTest.java
index f0f36c3c7b2..2d10ec9938c 100644
--- a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AuthoritiesAndScopesTest.java
+++ b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AuthoritiesAndScopesTest.java
@@ -1,3 +1,15 @@
+/*
+ * 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. 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.test.context.support.oauth2;
import static org.assertj.core.api.Assertions.assertThat;
@@ -10,6 +22,12 @@
import org.junit.Test;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
+/**
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ */
public class AuthoritiesAndScopesTest {
@Test
diff --git a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactoryTests.java b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactoryTests.java
index 0219ad81ba6..3ab510a11da 100644
--- a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactoryTests.java
+++ b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactoryTests.java
@@ -30,6 +30,12 @@
import org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelper.TargetType;
import org.springframework.security.test.context.support.oauth2.attributes.AttributeValueParser;
+/**
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ */
public class WithMockJwtSecurityContextFactoryTests {
private WithMockJwtSecurityContextFactory factory;
diff --git a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtTests.java b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtTests.java
index 6dc60b25226..d3893fd4668 100644
--- a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtTests.java
+++ b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtTests.java
@@ -21,6 +21,12 @@
import org.springframework.security.test.context.support.WithSecurityContext;
import org.springframework.security.test.context.support.oauth2.attributes.Attribute;
+/**
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ */
public class WithMockJwtTests {
@Test
diff --git a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeParsersHelperTest.java b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeParsersHelperTest.java
index f5e8a93f4ee..73b7acb327c 100644
--- a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeParsersHelperTest.java
+++ b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeParsersHelperTest.java
@@ -24,6 +24,12 @@
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelper.TargetType;
+/**
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ */
public class AttributeParsersHelperTest {
@Attribute(name = "a", value = "bidule", parserOverride = "SomeTypeParser")
From 39f846492a8997c7b3d1bc2f6971179ba4ca3a73 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Wacongne?=
Date: Tue, 19 Mar 2019 16:09:18 +0100
Subject: [PATCH 5/9] remove unused code
---
.../support/oauth2/AnnotationHelper.java | 9 +--------
.../support/oauth2/AnnotationHelperTest.java | 20 -------------------
2 files changed, 1 insertion(+), 28 deletions(-)
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AnnotationHelper.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AnnotationHelper.java
index d121c10b2f7..6ed83c36730 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AnnotationHelper.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AnnotationHelper.java
@@ -14,11 +14,11 @@
import java.util.Collection;
import java.util.Map;
-import java.util.stream.Stream;
import org.springframework.util.StringUtils;
/**
+ * Useful functions to manipulate annotation values
*
* @author Jérôme Wacongne <ch4mp@c4-soft.com>
* @since 5.2.0
@@ -46,11 +46,4 @@ public static String nullIfEmpty(final String str) {
return map;
}
- public static Stream stringStream(final String... values) {
- if (values == null || values.length == 0) {
- return Stream.empty();
- }
- return Stream.of(values).map(AnnotationHelper::nullIfEmpty).filter(a -> a != null);
- }
-
}
diff --git a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AnnotationHelperTest.java b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AnnotationHelperTest.java
index 2953e476156..87fc69d305d 100644
--- a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AnnotationHelperTest.java
+++ b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AnnotationHelperTest.java
@@ -15,12 +15,10 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.security.test.context.support.oauth2.AnnotationHelper.nullIfEmpty;
import static org.springframework.security.test.context.support.oauth2.AnnotationHelper.putIfNotEmpty;
-import static org.springframework.security.test.context.support.oauth2.AnnotationHelper.stringStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
-import java.util.stream.Stream;
import org.junit.Test;
@@ -91,22 +89,4 @@ public void putIfNotEmptyInsertsNonEmptyList() {
assertThat(actual).contains("Toto");
}
- @Test
- public void stringStreamReturnsEmptyStreamForNullArray() {
- final Stream actual = stringStream((String[]) null);
- assertThat(actual).isEmpty();
- }
-
- @Test
- public void stringStreamReturnsEmptyStreamForEmptyArray() {
- final Stream actual = stringStream(new String[] {});
- assertThat(actual).isEmpty();
- }
-
- @Test
- public void stringStreamSkipsNullAndEmptyStrings() {
- final Stream actual = stringStream(new String[] { null, "", "Toto" });
- assertThat(actual).allMatch("Toto"::equals);
- }
-
}
From 0f185ba2fdfb8bade59fffbf539cae9f1170ca7c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Wacongne?=
Date: Tue, 19 Mar 2019 17:47:38 +0100
Subject: [PATCH 6/9] AttributeParsersHelper shouldn't build new default parser
instance each time it is accessed
---
.../attributes/AttributeParsersHelper.java | 32 +++++++++----------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeParsersHelper.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeParsersHelper.java
index 4c90d9e2bdb..239cb81a9f8 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeParsersHelper.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeParsersHelper.java
@@ -68,12 +68,12 @@ public enum TargetType {
DEFAULT_PARSERS.add(new UrlParser());
}
- private final Map> attributeValueParsers;
+ private final Map> parsers;
private AttributeParsersHelper(
final Set> baseParsers,
final String... additionalParserNames) {
- this.attributeValueParsers = new HashMap<>(2 * DEFAULT_PARSERS.size() + 2 * additionalParserNames.length);
+ this.parsers = new HashMap<>(2 * DEFAULT_PARSERS.size() + 2 * additionalParserNames.length);
final Stream> additionalParsers = Stream.of(additionalParserNames).distinct().map(t -> {
try {
return Class.forName(t);
@@ -90,35 +90,35 @@ private AttributeParsersHelper(
});
Stream.concat(baseParsers.stream(), additionalParsers).forEachOrdered(p -> {
- this.attributeValueParsers.put(p.getClass().getName(), p);
- this.attributeValueParsers.put(p.getClass().getSimpleName(), p);
+ this.parsers.put(p.getClass().getName(), p);
+ this.parsers.put(p.getClass().getSimpleName(), p);
});
}
private AttributeValueParser> getParser(final TargetType targetType, final String parserOverrideClassName) {
final Optional> parserOverride =
Optional.ofNullable(StringUtils.isEmpty(parserOverrideClassName) ? null : parserOverrideClassName)
- .map(this.attributeValueParsers::get);
+ .map(parsers::get);
switch (targetType) {
case STRING:
- return parserOverride.orElse(new NoOpParser());
+ return parserOverride.orElse(parsers.get("NoOpParser"));
case BOOLEAN:
- return parserOverride.orElse(new BooleanParser());
+ return parserOverride.orElse(parsers.get("BooleanParser"));
case DOUBLE:
- return parserOverride.orElse(new DoubleParser());
+ return parserOverride.orElse(parsers.get("DoubleParser"));
case INSTANT:
- return parserOverride.orElse(new InstantParser());
+ return parserOverride.orElse(parsers.get("InstantParser"));
case INTEGER:
- return parserOverride.orElse(new IntegerParser());
+ return parserOverride.orElse(parsers.get("IntegerParser"));
case LONG:
- return parserOverride.orElse(new LongParser());
+ return parserOverride.orElse(parsers.get("LongParser"));
case STRING_LIST:
- return parserOverride.orElse(new StringListParser());
+ return parserOverride.orElse(parsers.get("StringListParser"));
case STRING_SET:
- return parserOverride.orElse(new StringSetParser());
+ return parserOverride.orElse(parsers.get("StringSetParser"));
case URL:
- return parserOverride.orElse(new UrlParser());
+ return parserOverride.orElse(parsers.get("UrlParser"));
default:
assert (!StringUtils.isEmpty(parserOverrideClassName));
return parserOverride.get();
@@ -194,7 +194,7 @@ public Map parse(final Attribute... properties) {
* AttributeValueParser} implementations class names to add to
* {@link org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelper#DEFAULT_PARSERS
* default ones}
- * @return helper instance with provided attributeValueParsers plus default ones
+ * @return helper instance with provided parsers plus default ones
*/
public static AttributeParsersHelper withDefaultParsers(final String... additionalParserNames) {
return new AttributeParsersHelper(DEFAULT_PARSERS, additionalParserNames);
@@ -208,7 +208,7 @@ public static AttributeParsersHelper withDefaultParsers(final String... addition
* @param allParserNames
* {@link org.springframework.security.test.context.support.oauth2.attributes.AttributeValueParser
* AttributeValueParser} implementations class names
- * @return helper instance with provided attributeValueParsers only
+ * @return helper instance with provided parsers only
*/
public static AttributeParsersHelper withoutDefaultParsers(final String... allParserNames) {
return new AttributeParsersHelper(Collections.emptySet(), allParserNames);
From 771fe7c14da38ce969513e9ee72e0055f680be0c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Wacongne?=
Date: Tue, 19 Mar 2019 23:10:21 +0100
Subject: [PATCH 7/9] Lambdas instead of default parsers named classes
---
.../oauth2/{attributes => }/Attribute.java | 11 +-
.../AttributeParsersHelper.java | 111 +++++++++---------
.../AttributeValueParser.java | 2 +-
.../context/support/oauth2/WithMockJwt.java | 16 ++-
.../WithMockJwtSecurityContextFactory.java | 1 -
.../oauth2/attributes/BooleanParser.java | 37 ------
.../oauth2/attributes/DoubleParser.java | 37 ------
.../oauth2/attributes/InstantParser.java | 39 ------
.../oauth2/attributes/IntegerParser.java | 37 ------
.../support/oauth2/attributes/LongParser.java | 37 ------
.../support/oauth2/attributes/NoOpParser.java | 32 -----
.../oauth2/attributes/StringListParser.java | 35 ------
.../oauth2/attributes/StringSetParser.java | 34 ------
.../support/oauth2/attributes/UrlParser.java | 44 -------
.../AttributeParsersHelperTest.java | 13 +-
...ithMockJwtSecurityContextFactoryTests.java | 4 +-
.../support/oauth2/WithMockJwtTests.java | 1 -
17 files changed, 77 insertions(+), 414 deletions(-)
rename oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/{attributes => }/Attribute.java (90%)
rename oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/{attributes => }/AttributeParsersHelper.java (72%)
rename oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/{attributes => }/AttributeValueParser.java (98%)
delete mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/BooleanParser.java
delete mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/DoubleParser.java
delete mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/InstantParser.java
delete mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/IntegerParser.java
delete mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/LongParser.java
delete mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/NoOpParser.java
delete mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/StringListParser.java
delete mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/StringSetParser.java
delete mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/UrlParser.java
rename oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/{attributes => }/AttributeParsersHelperTest.java (88%)
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/Attribute.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/Attribute.java
similarity index 90%
rename from oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/Attribute.java
rename to oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/Attribute.java
index f1e1208abae..d75242b8465 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/Attribute.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/Attribute.java
@@ -10,14 +10,14 @@
* 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.test.context.support.oauth2.attributes;
+package org.springframework.security.test.context.support.oauth2;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelper.TargetType;
+import org.springframework.security.test.context.support.oauth2.AttributeParsersHelper.TargetType;
/**
*
@@ -28,8 +28,8 @@
* {@link #parserOverride()} can be referenced either by fully qualified name or simple name.
*
*
- * See {@link AttributeValueParser} and its already provided implementations:
- * {@link AttributeParsersHelper#DEFAULT_PARSERS}
+ * See {@link AttributeValueParser}. Implementations for any {@link TargetType} but {@link TargetType#OTHER} are
+ * provided out of the box (can be overriden, just provide a parser with same name)
*
* Sample usage:
*
@@ -47,8 +47,7 @@
*
*
an {@code audience} claim with a value being a {@code List} with two entries
*
an {@code issuer} claim with a value being a {@code java.net.URL} instance
- *
a {@code machin} claim with {@code chose} String as value (default parser is
- * {@link org.springframework.security.test.context.support.oauth2.attributes.NoOpParser NoOpParser})
+ *
a {@code machin} claim with {@code chose} String as value (default parser is {@code NoOpParser})
*
a {@code truc} claim whith an instance of what {@code your.fancy.ParserImpl} is designed to build from
* {@code bidule} string as value
*
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeParsersHelper.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AttributeParsersHelper.java
similarity index 72%
rename from oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeParsersHelper.java
rename to oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AttributeParsersHelper.java
index 239cb81a9f8..c4fc8e833bf 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeParsersHelper.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AttributeParsersHelper.java
@@ -10,9 +10,12 @@
* 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.test.context.support.oauth2.attributes;
+package org.springframework.security.test.context.support.oauth2;
import java.lang.reflect.InvocationTargetException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -21,7 +24,6 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
-import java.util.Set;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -29,52 +31,26 @@
import org.springframework.util.StringUtils;
/**
- * Helps turn a {@link org.springframework.security.test.context.support.oauth2.attributes.Attribute @Attribute} array
- * into a {@link java.util.Map Map<String, Object>}
+ * Helps turn a {@link org.springframework.security.test.context.support.oauth2.Attribute @Attribute} array into a
+ * {@link java.util.Map Map<String, Object>}
*
* @author Jérôme Wacongne <ch4mp@c4-soft.com>
* @since 5.2.0
*
*/
-public class AttributeParsersHelper {
+class AttributeParsersHelper {
public enum TargetType {
STRING, BOOLEAN, DOUBLE, INSTANT, INTEGER, LONG, STRING_LIST, STRING_SET, URL, OTHER;
}
- /**
- *
- * Turns a {@link org.springframework.security.test.context.support.oauth2.attributes.Attribute @Attribute} array
- * into a {@link java.util.Map Map<String, Object>} as required for
+ * Turns a {@link org.springframework.security.test.context.support.oauth2.Attribute @Attribute} array into a
+ * {@link java.util.Map Map<String, Object>} as required for
* {@link org.springframework.security.oauth2.jwt.Jwt JWT} headers and claims.
*
*
* Process highlights:
*
*
- *
each {@link org.springframework.security.test.context.support.oauth2.attributes.Attribute#value() value()} is
- * parsed according to
- * {@link org.springframework.security.test.context.support.oauth2.attributes.Attribute#parserOverride()
+ *
each {@link org.springframework.security.test.context.support.oauth2.Attribute#value() value()} is parsed
+ * according to {@link org.springframework.security.test.context.support.oauth2.Attribute#parserOverride()
* parser()}
*
obtained values are associated with
- * {@link org.springframework.security.test.context.support.oauth2.attributes.Attribute#name() name()}
values with same name are accumulated in the same collection
*
*
@@ -185,33 +158,59 @@ public Map parse(final Attribute... properties) {
}
/**
- * Instantiates default
- * {@link org.springframework.security.test.context.support.oauth2.attributes.AttributeValueParser
+ * Instantiates default {@link org.springframework.security.test.context.support.oauth2.AttributeValueParser
* AttributeValueParser}s plus all provided ones (using default constructor)
*
- * @param additionalParserNames
- * {@link org.springframework.security.test.context.support.oauth2.attributes.AttributeValueParser
+ * @param additionalParserNames {@link org.springframework.security.test.context.support.oauth2.AttributeValueParser
* AttributeValueParser} implementations class names to add to
- * {@link org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelper#DEFAULT_PARSERS
- * default ones}
+ * {@link org.springframework.security.test.context.support.oauth2.AttributeParsersHelper#DEFAULT_PARSERS default
+ * ones}
* @return helper instance with provided parsers plus default ones
*/
public static AttributeParsersHelper withDefaultParsers(final String... additionalParserNames) {
- return new AttributeParsersHelper(DEFAULT_PARSERS, additionalParserNames);
+ final Map> baseParsers = new HashMap<>(9);
+
+ baseParsers.put("NoOpParser", (final String value) -> value);
+ baseParsers.put(
+ "BooleanParser",
+ (final String value) -> StringUtils.isEmpty(value) ? null : Boolean.valueOf(value));
+ baseParsers
+ .put("DoubleParser", (final String value) -> StringUtils.isEmpty(value) ? null : Double.valueOf(value));
+ baseParsers
+ .put("InstantParser", (final String value) -> StringUtils.isEmpty(value) ? null : Instant.parse(value));
+ baseParsers.put(
+ "IntegerParser",
+ (final String value) -> StringUtils.isEmpty(value) ? null : Integer.valueOf(value));
+ baseParsers.put("LongParser", (final String value) -> StringUtils.isEmpty(value) ? null : Long.valueOf(value));
+ baseParsers.put(
+ "StringListParser",
+ (final String value) -> StringUtils.isEmpty(value) ? Collections.emptyList()
+ : Collections.singletonList(value));
+ baseParsers.put(
+ "StringSetParser",
+ (final String value) -> StringUtils.isEmpty(value) ? Collections.emptySet()
+ : Collections.singleton(value));
+ baseParsers.put("UrlParser", (final String value) -> {
+ try {
+ return (StringUtils.isEmpty(value)) ? null : new URL(value);
+ } catch (final MalformedURLException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ return new AttributeParsersHelper(baseParsers, additionalParserNames);
}
/**
- * Instantiates all provided
- * {@link org.springframework.security.test.context.support.oauth2.attributes.AttributeValueParser
+ * Instantiates all provided {@link org.springframework.security.test.context.support.oauth2.AttributeValueParser
* AttributeValueParser}s using default constructor
*
- * @param allParserNames
- * {@link org.springframework.security.test.context.support.oauth2.attributes.AttributeValueParser
+ * @param allParserNames {@link org.springframework.security.test.context.support.oauth2.AttributeValueParser
* AttributeValueParser} implementations class names
* @return helper instance with provided parsers only
*/
public static AttributeParsersHelper withoutDefaultParsers(final String... allParserNames) {
- return new AttributeParsersHelper(Collections.emptySet(), allParserNames);
+ return new AttributeParsersHelper(Collections.emptyMap(), allParserNames);
}
private static final class ParsedProperty {
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeValueParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AttributeValueParser.java
similarity index 98%
rename from oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeValueParser.java
rename to oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AttributeValueParser.java
index 2a9941cf054..67270a67206 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeValueParser.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AttributeValueParser.java
@@ -10,7 +10,7 @@
* 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.test.context.support.oauth2.attributes;
+package org.springframework.security.test.context.support.oauth2;
/**
*
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwt.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwt.java
index 27d7ecd441e..b02e7ea13b9 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwt.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwt.java
@@ -28,9 +28,7 @@
import org.springframework.security.test.context.support.TestExecutionEvent;
import org.springframework.security.test.context.support.WithSecurityContext;
import org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener;
-import org.springframework.security.test.context.support.oauth2.attributes.Attribute;
-import org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelper;
-import org.springframework.security.test.context.support.oauth2.attributes.AttributeValueParser;
+import org.springframework.security.test.context.support.oauth2.AttributeParsersHelper.TargetType;
import org.springframework.test.context.TestContext;
import org.springframework.test.web.servlet.MockMvc;
@@ -59,11 +57,11 @@
* {@code name} value ({@code "user"} by default)
*
{@link Authentication#getAuthorities() authorities} will be a collection of {@link SimpleGrantedAuthority} as
* defined by this annotation {@link #authorities()} (
- *
+ *
*
* { "ROLE_USER" }
*
- *
+ *
* by default
*
*
@@ -95,7 +93,7 @@
*
* @see Attribute
* @see AttributeValueParser
- * @see AttributeParsersHelper#DEFAULT_PARSERS
+ * @see TargetType
*
* @author Jérôme Wacongne <ch4mp@c4-soft.com>
* @since 5.2.0
@@ -143,12 +141,12 @@
Attribute[] headers() default { @Attribute(name = DEFAULT_HEADER_NAME, value = DEFAULT_HEADER_VALUE) };
/**
- * {@link AttributeParsersHelper#DEFAULT_PARSERS Defaulted parsers} are provided for most common value types. Those
- * will be added to defaults (and override defaults when retrieved by simple name)
+ * Parsers are provided for for all {@link TargetType} but {@link TargetType#OTHER}. Those will be added to parse
+ * more types or override defaults with same {@code SimpleName}.
*
* @return parsers to add to default ones (or override)
*
- * @see AttributeParsersHelper#DEFAULT_PARSERS
+ * @see TargetType
*/
String[] additionalParsers() default {};
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactory.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactory.java
index 0976643721e..a610e93f4ab 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactory.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactory.java
@@ -24,7 +24,6 @@
import org.springframework.security.oauth2.jwt.JwtClaimNames;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.security.test.context.support.WithSecurityContextFactory;
-import org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelper;
/**
* Create a {@link org.springframework.security.core.context.SecurityContext SecurityContext} populated with a
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/BooleanParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/BooleanParser.java
deleted file mode 100644
index 2db0fa31920..00000000000
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/BooleanParser.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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. 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.test.context.support.oauth2.attributes;
-
-import org.springframework.util.StringUtils;
-
-/**
- * Turns an annotation String value into a Boolean
- *
- * @author Jérôme Wacongne <ch4mp@c4-soft.com>
- * @since 5.2.0
- *
- */
-public class BooleanParser implements AttributeValueParser {
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Boolean parse(final String value) {
- if (StringUtils.isEmpty(value)) {
- return null;
- }
- return Boolean.valueOf(value);
- }
-
-}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/DoubleParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/DoubleParser.java
deleted file mode 100644
index da7ead4db3c..00000000000
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/DoubleParser.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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. 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.test.context.support.oauth2.attributes;
-
-import org.springframework.util.StringUtils;
-
-/**
- * Turns an annotation String value into a Double
- *
- * @author Jérôme Wacongne <ch4mp@c4-soft.com>
- * @since 5.2.0
- *
- */
-public class DoubleParser implements AttributeValueParser {
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Double parse(final String value) {
- if (StringUtils.isEmpty(value)) {
- return null;
- }
- return Double.valueOf(value);
- }
-
-}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/InstantParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/InstantParser.java
deleted file mode 100644
index a2c3c6798ff..00000000000
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/InstantParser.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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. 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.test.context.support.oauth2.attributes;
-
-import java.time.Instant;
-
-import org.springframework.util.StringUtils;
-
-/**
- * Turns an annotation String value into an {@link java.time.Instant Instant}
- *
- * @author Jérôme Wacongne <ch4mp@c4-soft.com>
- * @since 5.2.0
- *
- */
-public class InstantParser implements AttributeValueParser {
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Instant parse(final String value) {
- if (StringUtils.isEmpty(value)) {
- return null;
- }
- return Instant.parse(value);
- }
-
-}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/IntegerParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/IntegerParser.java
deleted file mode 100644
index f4bd76f8c00..00000000000
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/IntegerParser.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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. 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.test.context.support.oauth2.attributes;
-
-import org.springframework.util.StringUtils;
-
-/**
- * Turns an annotation String value into an Integer
- *
- * @author Jérôme Wacongne <ch4mp@c4-soft.com>
- * @since 5.2.0
- *
- */
-public class IntegerParser implements AttributeValueParser {
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Integer parse(final String value) {
- if (StringUtils.isEmpty(value)) {
- return null;
- }
- return Integer.valueOf(value);
- }
-
-}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/LongParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/LongParser.java
deleted file mode 100644
index 405b614fe85..00000000000
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/LongParser.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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. 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.test.context.support.oauth2.attributes;
-
-import org.springframework.util.StringUtils;
-
-/**
- * Turns an annotation String value into a Long
- *
- * @author Jérôme Wacongne <ch4mp@c4-soft.com>
- * @since 5.2.0
- *
- */
-public class LongParser implements AttributeValueParser {
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Long parse(final String value) {
- if (StringUtils.isEmpty(value)) {
- return null;
- }
- return Long.valueOf(value);
- }
-
-}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/NoOpParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/NoOpParser.java
deleted file mode 100644
index 6f6f27bb2a5..00000000000
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/NoOpParser.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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. 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.test.context.support.oauth2.attributes;
-
-/**
- * Leaves an annotation String value untouched
- *
- * @author Jérôme Wacongne <ch4mp@c4-soft.com>
- * @since 5.2.0
- *
- */
-public class NoOpParser implements AttributeValueParser {
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String parse(final String value) {
- return value;
- }
-
-}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/StringListParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/StringListParser.java
deleted file mode 100644
index c50d85e9ee3..00000000000
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/StringListParser.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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. 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.test.context.support.oauth2.attributes;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Turns an annotation String value into a {@link java.util.List List<String>}
- *
- * @author Jérôme Wacongne <ch4mp@c4-soft.com>
- * @since 5.2.0
- *
- */
-public class StringListParser implements AttributeValueParser> {
-
- /**
- * {@inheritDoc}
- */
- @Override
- public List parse(final String value) {
- return Collections.singletonList(value);
- }
-
-}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/StringSetParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/StringSetParser.java
deleted file mode 100644
index 7dcf89a92ab..00000000000
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/StringSetParser.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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. 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.test.context.support.oauth2.attributes;
-
-import java.util.Collections;
-import java.util.Set;
-
-/**
- * Turns an annotation String value into a {@link java.util.Set Set<String>}
- *
- * @author Jérôme Wacongne <ch4mp@c4-soft.com>
- * @since 5.2.0
- *
- */
-public class StringSetParser implements AttributeValueParser> {
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Set parse(final String value) {
- return Collections.singleton(value);
- }
-}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/UrlParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/UrlParser.java
deleted file mode 100644
index 83a02ddcb04..00000000000
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/attributes/UrlParser.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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. 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.test.context.support.oauth2.attributes;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import org.springframework.util.StringUtils;
-
-/**
- * Turns an annotation String value into an {@link java.net.URL URL}
- *
- * @author Jérôme Wacongne <ch4mp@c4-soft.com>
- * @since 5.2.0
- *
- */
-public class UrlParser implements AttributeValueParser {
-
- /**
- * {@inheritDoc}
- */
- @Override
- public URL parse(final String value) {
- if (StringUtils.isEmpty(value)) {
- return null;
- }
- try {
- return new URL(value);
- } catch (final MalformedURLException e) {
- throw new RuntimeException(e);
- }
- }
-
-}
diff --git a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeParsersHelperTest.java b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AttributeParsersHelperTest.java
similarity index 88%
rename from oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeParsersHelperTest.java
rename to oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AttributeParsersHelperTest.java
index 73b7acb327c..7a664f5ce23 100644
--- a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/attributes/AttributeParsersHelperTest.java
+++ b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AttributeParsersHelperTest.java
@@ -10,7 +10,7 @@
* 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.test.context.support.oauth2.attributes;
+package org.springframework.security.test.context.support.oauth2;
import static org.assertj.core.api.Assertions.assertThat;
@@ -22,7 +22,10 @@
import org.junit.Test;
import org.springframework.core.annotation.AnnotationUtils;
-import org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelper.TargetType;
+import org.springframework.security.test.context.support.oauth2.Attribute;
+import org.springframework.security.test.context.support.oauth2.AttributeParsersHelper;
+import org.springframework.security.test.context.support.oauth2.AttributeValueParser;
+import org.springframework.security.test.context.support.oauth2.AttributeParsersHelper.TargetType;
/**
*
@@ -39,14 +42,14 @@ private static final class AProperty {
@Attribute(
name = "b",
value = "chose",
- parserOverride = "org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelperTest$SomeTypeParser")
+ parserOverride = "org.springframework.security.test.context.support.oauth2.AttributeParsersHelperTest$SomeTypeParser")
private static final class BProperty {
}
@Test
public void parsePropertiesWithDistinctNames() {
final AttributeParsersHelper helper = AttributeParsersHelper.withoutDefaultParsers(
- "org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelperTest$SomeTypeParser");
+ "org.springframework.security.test.context.support.oauth2.AttributeParsersHelperTest$SomeTypeParser");
final Attribute propertyAnnotationA = AnnotationUtils.findAnnotation(AProperty.class, Attribute.class);
final Attribute propertyAnnotationB = AnnotationUtils.findAnnotation(BProperty.class, Attribute.class);
@@ -87,7 +90,7 @@ private static final class EProperty {
@Test
public void parsePropertiesUsesParseroverrides() {
final AttributeParsersHelper helper = AttributeParsersHelper.withDefaultParsers(
- "org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelperTest$InstantParser");
+ "org.springframework.security.test.context.support.oauth2.AttributeParsersHelperTest$InstantParser");
final Attribute propertyAnnotation = AnnotationUtils.findAnnotation(EProperty.class, Attribute.class);
diff --git a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactoryTests.java b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactoryTests.java
index 3ab510a11da..3b8f5bb7e52 100644
--- a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactoryTests.java
+++ b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactoryTests.java
@@ -26,9 +26,7 @@
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtClaimNames;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
-import org.springframework.security.test.context.support.oauth2.attributes.Attribute;
-import org.springframework.security.test.context.support.oauth2.attributes.AttributeParsersHelper.TargetType;
-import org.springframework.security.test.context.support.oauth2.attributes.AttributeValueParser;
+import org.springframework.security.test.context.support.oauth2.AttributeParsersHelper.TargetType;
/**
*
diff --git a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtTests.java b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtTests.java
index d3893fd4668..9397b03dd1d 100644
--- a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtTests.java
+++ b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtTests.java
@@ -19,7 +19,6 @@
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.security.test.context.support.TestExecutionEvent;
import org.springframework.security.test.context.support.WithSecurityContext;
-import org.springframework.security.test.context.support.oauth2.attributes.Attribute;
/**
*
From bc286f0a1099c6821b74be634754a5ce57ea0db9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Wacongne?=
Date: Wed, 20 Mar 2019 13:48:18 +0100
Subject: [PATCH 8/9] TargetType enum must be public
---
.../context/support/oauth2/Attribute.java | 2 -
.../oauth2/AttributeParsersHelper.java | 4 --
.../context/support/oauth2/TargetType.java | 23 ++++++++
.../context/support/oauth2/WithMockJwt.java | 1 -
.../oauth2/AttributeParsersHelperTest.java | 1 -
...ithMockJwtSecurityContextFactoryTests.java | 1 -
.../OAuth2ResourceServerControllerTest.java | 52 +++++++++++++------
7 files changed, 60 insertions(+), 24 deletions(-)
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/TargetType.java
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/Attribute.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/Attribute.java
index d75242b8465..17a55311609 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/Attribute.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/Attribute.java
@@ -17,8 +17,6 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import org.springframework.security.test.context.support.oauth2.AttributeParsersHelper.TargetType;
-
/**
*
* Annotation to create an entry in a {@link java.util.Map Map<String, Object>} such as
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AttributeParsersHelper.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AttributeParsersHelper.java
index c4fc8e833bf..2ee10870dd4 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AttributeParsersHelper.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AttributeParsersHelper.java
@@ -39,10 +39,6 @@
*
*/
class AttributeParsersHelper {
- public enum TargetType {
- STRING, BOOLEAN, DOUBLE, INSTANT, INTEGER, LONG, STRING_LIST, STRING_SET, URL, OTHER;
- }
-
private final Map> parsers;
private AttributeParsersHelper(
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/TargetType.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/TargetType.java
new file mode 100644
index 00000000000..4dbaa057775
--- /dev/null
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/TargetType.java
@@ -0,0 +1,23 @@
+/*
+ * 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. 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.test.context.support.oauth2;
+
+/**
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ */
+public enum TargetType {
+ STRING, BOOLEAN, DOUBLE, INSTANT, INTEGER, LONG, STRING_LIST, STRING_SET, URL, OTHER;
+}
\ No newline at end of file
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwt.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwt.java
index b02e7ea13b9..940a5008800 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwt.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwt.java
@@ -28,7 +28,6 @@
import org.springframework.security.test.context.support.TestExecutionEvent;
import org.springframework.security.test.context.support.WithSecurityContext;
import org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener;
-import org.springframework.security.test.context.support.oauth2.AttributeParsersHelper.TargetType;
import org.springframework.test.context.TestContext;
import org.springframework.test.web.servlet.MockMvc;
diff --git a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AttributeParsersHelperTest.java b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AttributeParsersHelperTest.java
index 7a664f5ce23..675b451e358 100644
--- a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AttributeParsersHelperTest.java
+++ b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AttributeParsersHelperTest.java
@@ -25,7 +25,6 @@
import org.springframework.security.test.context.support.oauth2.Attribute;
import org.springframework.security.test.context.support.oauth2.AttributeParsersHelper;
import org.springframework.security.test.context.support.oauth2.AttributeValueParser;
-import org.springframework.security.test.context.support.oauth2.AttributeParsersHelper.TargetType;
/**
*
diff --git a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactoryTests.java b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactoryTests.java
index 3b8f5bb7e52..18baa697e6a 100644
--- a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactoryTests.java
+++ b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactoryTests.java
@@ -26,7 +26,6 @@
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtClaimNames;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
-import org.springframework.security.test.context.support.oauth2.AttributeParsersHelper.TargetType;
/**
*
diff --git a/samples/boot/oauth2resourceserver/src/test/java/sample/OAuth2ResourceServerControllerTest.java b/samples/boot/oauth2resourceserver/src/test/java/sample/OAuth2ResourceServerControllerTest.java
index 5b09a09f544..7208d433db1 100644
--- a/samples/boot/oauth2resourceserver/src/test/java/sample/OAuth2ResourceServerControllerTest.java
+++ b/samples/boot/oauth2resourceserver/src/test/java/sample/OAuth2ResourceServerControllerTest.java
@@ -1,17 +1,14 @@
/*
* 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.
- * You may obtain a copy of the License at
+ * 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
+ * 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.
+ * 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;
@@ -27,6 +24,8 @@
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.security.oauth2.jwt.JwtDecoder;
+import org.springframework.security.test.context.support.oauth2.Attribute;
+import org.springframework.security.test.context.support.oauth2.TargetType;
import org.springframework.security.test.context.support.oauth2.WithMockJwt;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
@@ -44,17 +43,40 @@ public class OAuth2ResourceServerControllerTest {
@Autowired
MockMvc mockMvc;
- //TODO: find a way to remove that (JwtDecoder is useless and a stub one could be registered by test framework)
@MockBean
JwtDecoder jwtDecoder;
@Test
- @WithMockJwt()
- public void test() throws Exception {
+ @WithMockJwt(name = "ch4mpy")
+ public void testIndex() throws Exception {
mockMvc.perform(get("/"))
- .andDo(print())
- .andExpect(status().isOk())
- .andExpect(content().string(is("Hello, " + WithMockJwt.DEFAULT_AUTH_NAME + "!")));
+ .andDo(print())
+ .andExpect(status().isOk())
+ .andExpect(content().string(is("Hello, ch4mpy!")));
+ }
+
+ @Test
+ @WithMockJwt("SCOPE_message:read")
+ public void testMessageIsAcciessibleWithCorrectScopeAuthority() throws Exception {
+ mockMvc.perform(get("/message"))
+ .andDo(print())
+ .andExpect(status().isOk())
+ .andExpect(content().string(is("secret message")));
+ }
+
+ @Test
+ @WithMockJwt(claims = @Attribute(name = "scope", value = "message:read", parseTo = TargetType.STRING_SET))
+ public void testMessageIsAcciessibleWithCorrectScopeClaim() throws Exception {
+ mockMvc.perform(get("/message"))
+ .andDo(print())
+ .andExpect(status().isOk())
+ .andExpect(content().string(is("secret message")));
+ }
+
+ @Test
+ @WithMockJwt
+ public void testMessageIsNotAcciessibleWithDefaultAuthority() throws Exception {
+ mockMvc.perform(get("/message")).andDo(print()).andExpect(status().isForbidden());
}
}
From 6865e0111c664e45926837059add96cd5294b850 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Wacongne?=
Date: Sat, 23 Mar 2019 12:27:43 +0100
Subject: [PATCH 9/9] JWT request post-processor
Also
* enable scope collection extracting from "scope" claim if single space separated string
* expose "scopes" at annotation level
---
...ecurity-oauth2-resource-server-test.gradle | 4 +
.../support/oauth2/AuthoritiesAndScopes.java | 137 ------------------
.../WithMockJwtSecurityContextFactory.java | 71 ---------
.../oauth2/{ => annotations}/Attribute.java | 19 ++-
.../AttributeParsersSupport.java} | 84 +++++------
.../AttributeValueParser.java | 17 ++-
.../oauth2/{ => annotations}/TargetType.java | 17 ++-
.../oauth2/{ => annotations}/WithMockJwt.java | 65 ++++++---
.../AbstractOAuth2RequestPostProcessor.java | 116 +++++++++++++++
.../request/JwtRequestPostProcessor.java | 76 ++++++++++
.../OAuth2MockMvcRequestPostProcessors.java | 28 ++++
.../oauth2/support/AuthoritiesAndScopes.java | 117 +++++++++++++++
.../CollectionsSupport.java} | 34 +++--
.../support/oauth2/support/JwtSupport.java | 65 +++++++++
.../AttributeParsersSupportTest.java} | 34 ++---
...ithMockJwtSecurityContextFactoryTests.java | 47 +++---
.../{ => annotations}/WithMockJwtTests.java | 22 ++-
.../AuthoritiesAndScopesTest.java | 53 +++++--
.../CollectionsSupportTest.java} | 23 +--
.../OAuth2ResourceServerControllerTest.java | 37 ++++-
...ityContextRequestPostProcessorSupport.java | 126 ++++++++++++++++
.../SecurityMockMvcRequestPostProcessors.java | 96 ------------
22 files changed, 819 insertions(+), 469 deletions(-)
delete mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AuthoritiesAndScopes.java
delete mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactory.java
rename oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/{ => annotations}/Attribute.java (86%)
rename oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/{AttributeParsersHelper.java => annotations/AttributeParsersSupport.java} (76%)
rename oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/{ => annotations}/AttributeValueParser.java (55%)
rename oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/{ => annotations}/TargetType.java (51%)
rename oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/{ => annotations}/WithMockJwt.java (70%)
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/request/AbstractOAuth2RequestPostProcessor.java
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/request/JwtRequestPostProcessor.java
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/request/OAuth2MockMvcRequestPostProcessors.java
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/support/AuthoritiesAndScopes.java
rename oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/{AnnotationHelper.java => support/CollectionsSupport.java} (51%)
create mode 100644 oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/support/JwtSupport.java
rename oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/{AttributeParsersHelperTest.java => annotations/AttributeParsersSupportTest.java} (74%)
rename oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/{ => annotations}/WithMockJwtSecurityContextFactoryTests.java (81%)
rename oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/{ => annotations}/WithMockJwtTests.java (73%)
rename oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/{ => support}/AuthoritiesAndScopesTest.java (67%)
rename oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/{AnnotationHelperTest.java => support/CollectionsSupportTest.java} (79%)
create mode 100644 test/src/main/java/org/springframework/security/test/web/servlet/request/SecurityContextRequestPostProcessorSupport.java
diff --git a/oauth2-test/spring-security-oauth2-resource-server-test.gradle b/oauth2-test/spring-security-oauth2-resource-server-test.gradle
index 1395227adff..efc3156cd4e 100644
--- a/oauth2-test/spring-security-oauth2-resource-server-test.gradle
+++ b/oauth2-test/spring-security-oauth2-resource-server-test.gradle
@@ -4,4 +4,8 @@ dependencies {
compile project(':spring-security-test')
compile project(':spring-security-oauth2-resource-server')
compile project(':spring-security-oauth2-jose')
+
+ compile 'org.springframework:spring-test'
+
+ provided 'javax.servlet:javax.servlet-api'
}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AuthoritiesAndScopes.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AuthoritiesAndScopes.java
deleted file mode 100644
index 9d90e862281..00000000000
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AuthoritiesAndScopes.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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. 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.test.context.support.oauth2;
-
-import static org.springframework.security.test.context.support.oauth2.AnnotationHelper.putIfNotEmpty;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import org.springframework.security.core.authority.SimpleGrantedAuthority;
-
-/**
- * Helps merging {@code authorities} and {@code scope}.
- *
- * @author Jérôme Wacongne <ch4mp@c4-soft.com>
- * @since 5.2.0
- *
- */
-final class AuthoritiesAndScopes {
- public final Set authorities;
- public final Set scopes;
- public final Optional scopeAttributeName;
-
- private AuthoritiesAndScopes(
- final Set authorities,
- final Set scopes,
- final Optional scopeAttributeName) {
- this.authorities = Collections.unmodifiableSet(authorities);
- this.scopes = Collections.unmodifiableSet(scopes);
- this.scopeAttributeName = scopeAttributeName;
- }
-
- /**
- *
- * Merges {@code authorities} and {@code scope}.
- *
- *
- * Scopes are searched for in attributes with keys "scope", "scp" and "scopes", first entry found being used and
- * others ignored.
- *
- *
- * @param annotatedAuthorities authorities array (probably from an annotation {@code authorities()})
- * @param annotatedScopes scopes array (probably from an annotation {@code scopes()})
- * @param attributes attributes /!\ mutable /!\ map (probably from an annotation {@code attributes()} or
- * {@code claims()})
- * @return a structure containing merged granted authorities and scopes
- */
- public static AuthoritiesAndScopes get(
- final String[] annotatedAuthorities,
- final String[] annotatedScopes,
- final Map attributes) {
- final Optional scopeAttributeName = attributes.keySet()
- .stream()
- .filter(k -> "scope".equals(k) || "scp".equals(k) || "scopes".equals(k))
- .sorted()
- .findFirst();
-
- final Stream attributesScopes =
- scopeAttributeName.map(attributes::get).map(AuthoritiesAndScopes::stream).orElse(Stream.empty());
-
- final Stream authoritiesScopes =
- Stream.of(annotatedAuthorities).filter(a -> a.startsWith("SCOPE_")).map(a -> a.substring(6));
-
- final Set allScopes =
- Stream.concat(Stream.of(annotatedScopes), Stream.concat(authoritiesScopes, attributesScopes))
- .collect(Collectors.toSet());
-
- putIfNotEmpty(scopeAttributeName.orElse("scope"), allScopes, attributes);
-
- final Set allAuthorities =
- Stream.concat(Stream.of(annotatedAuthorities), allScopes.stream().map(scope -> "SCOPE_" + scope))
- .map(SimpleGrantedAuthority::new)
- .collect(Collectors.toSet());
-
- return new AuthoritiesAndScopes(allAuthorities, allScopes, scopeAttributeName);
- }
-
- @SuppressWarnings("unchecked")
- private static Stream stream(final Object col) {
- return col == null ? Stream.empty() : ((Collection) col).stream();
- }
-}
\ No newline at end of file
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactory.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactory.java
deleted file mode 100644
index a610e93f4ab..00000000000
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactory.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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. 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.test.context.support.oauth2;
-
-import static org.springframework.security.test.context.support.oauth2.AnnotationHelper.putIfNotEmpty;
-
-import java.time.Instant;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.oauth2.jwt.Jwt;
-import org.springframework.security.oauth2.jwt.JwtClaimNames;
-import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
-import org.springframework.security.test.context.support.WithSecurityContextFactory;
-
-/**
- * Create a {@link org.springframework.security.core.context.SecurityContext SecurityContext} populated with a
- * {@link org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken
- * JwtAuthenticationToken} containing a {@link org.springframework.security.oauth2.jwt.Jwt JWT} as described by
- * {@link org.springframework.security.test.context.support.oauth2.WithMockJwt @WithMockJwt}
- *
- * @author Jérôme Wacongne <ch4mp@c4-soft.com>
- * @since 5.2.0
- *
- */
-public final class WithMockJwtSecurityContextFactory implements WithSecurityContextFactory {
- public static final String DEFAULT_TOKEN_VALUE = "test.jwt.value";
-
- @Override
- public SecurityContext createSecurityContext(final WithMockJwt annotation) {
- final AttributeParsersHelper parsersHelper =
- AttributeParsersHelper.withDefaultParsers(annotation.additionalParsers());
-
- final Map headers = parsersHelper.parse(annotation.headers());
-
- final Map claims = new HashMap<>(parsersHelper.parse(annotation.claims()));
- if (claims.containsKey(JwtClaimNames.SUB)) {
- throw new RuntimeException(JwtClaimNames.SUB + " claim is not configurable (forced to @WithMockJwt.name)");
- } else {
- putIfNotEmpty(JwtClaimNames.SUB, annotation.name(), claims);
- }
-
- final AuthoritiesAndScopes authoritiesAndScopes =
- AuthoritiesAndScopes.get(annotation.authorities(), new String[] {}, claims);
-
- final SecurityContext context = SecurityContextHolder.createEmptyContext();
- context.setAuthentication(
- new JwtAuthenticationToken(
- new Jwt(
- DEFAULT_TOKEN_VALUE,
- (Instant) claims.get(JwtClaimNames.IAT),
- (Instant) claims.get(JwtClaimNames.EXP),
- headers,
- claims),
- authoritiesAndScopes.authorities));
-
- return context;
- }
-}
\ No newline at end of file
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/Attribute.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/annotations/Attribute.java
similarity index 86%
rename from oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/Attribute.java
rename to oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/annotations/Attribute.java
index 17a55311609..cb529fa4dd4 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/Attribute.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/annotations/Attribute.java
@@ -1,16 +1,19 @@
/*
* 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. You may obtain a copy of the License at
+ * 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
+ * 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.
+ * 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.test.context.support.oauth2;
+package org.springframework.security.test.context.support.oauth2.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -41,7 +44,7 @@
* @Attribute(name = "truc", value = "bidule", parserOverride = "your.fancy.ParserImpl")})
*
*
- * This will create
+ * This would create
*
*
an {@code audience} claim with a value being a {@code List} with two entries
*
an {@code issuer} claim with a value being a {@code java.net.URL} instance
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AttributeParsersHelper.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/annotations/AttributeParsersSupport.java
similarity index 76%
rename from oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AttributeParsersHelper.java
rename to oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/annotations/AttributeParsersSupport.java
index 2ee10870dd4..f4d13286ad4 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AttributeParsersHelper.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/annotations/AttributeParsersSupport.java
@@ -1,18 +1,23 @@
/*
* 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. You may obtain a copy of the License at
+ * 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
+ * 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.
+ * 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.test.context.support.oauth2;
+package org.springframework.security.test.context.support.oauth2.annotations;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
-import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.Instant;
@@ -31,33 +36,27 @@
import org.springframework.util.StringUtils;
/**
- * Helps turn a {@link org.springframework.security.test.context.support.oauth2.Attribute @Attribute} array into a
+ * Helps turn a {@link org.springframework.security.test.context.support.oauth2.annotations.Attribute @Attribute} array into a
* {@link java.util.Map Map<String, Object>}
*
* @author Jérôme Wacongne <ch4mp@c4-soft.com>
* @since 5.2.0
*
*/
-class AttributeParsersHelper {
+class AttributeParsersSupport {
private final Map> parsers;
- private AttributeParsersHelper(
+ private AttributeParsersSupport(
final Map> baseParsers,
final String... additionalParserNames) {
this.parsers = new HashMap<>(baseParsers);
- Stream.of(additionalParserNames).distinct().map(t -> {
+ Stream.of(additionalParserNames).distinct().map(parserName -> {
try {
- return Class.forName(t);
- } catch (final ClassNotFoundException e) {
- throw new RuntimeException(e);
- }
- }).map(c -> {
- try {
- return (AttributeValueParser>) c.getDeclaredConstructor().newInstance();
- } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
- | InvocationTargetException | NoSuchMethodException | SecurityException e) {
- throw new RuntimeException("Missing public no-arg constructor on " + c.getName());
+ final Class> clazz = Class.forName(parserName);
+ return (AttributeValueParser>) clazz.getDeclaredConstructor().newInstance();
+ } catch (final Exception e) {
+ throw new RuntimeException("Missing public no-arg constructor on " + parserName);
}
}).forEachOrdered(p -> {
this.parsers.put(p.getClass().getName(), p);
@@ -65,10 +64,9 @@ private AttributeParsersHelper(
});
}
- private AttributeValueParser> getParser(final TargetType targetType, final String parserOverrideClassName) {
+ private AttributeValueParser> getParser(final TargetType targetType, final String parserName) {
final Optional> parserOverride =
- Optional.ofNullable(StringUtils.isEmpty(parserOverrideClassName) ? null : parserOverrideClassName)
- .map(parsers::get);
+ Optional.ofNullable(StringUtils.isEmpty(parserName) ? null : parserName).map(parsers::get);
switch (targetType) {
case STRING:
@@ -90,7 +88,12 @@ private AttributeValueParser> getParser(final TargetType targetType, final Str
case URL:
return parserOverride.orElse(parsers.get("UrlParser"));
default:
- assert (!StringUtils.isEmpty(parserOverrideClassName));
+ assertFalse(
+ "parserOverride must benon empty when parseTo = \"" + targetType + "\"",
+ StringUtils.isEmpty(parserName));
+ assertTrue(
+ "No registered AttributeValueParser implementation for " + parserName,
+ parserOverride.isPresent());
return parserOverride.get();
}
@@ -98,16 +101,13 @@ private AttributeValueParser> getParser(final TargetType targetType, final Str
private ParsedProperty parse(final Attribute p) {
final AttributeValueParser> parser = getParser(p.parseTo(), p.parserOverride());
- if (parser == null) {
- throw new RuntimeException("No registered AttributeValueParser implementation for " + p.parserOverride());
- }
return new ParsedProperty<>(p.name(), parser.parse(p.value()));
}
/**
*
- * Turns a {@link org.springframework.security.test.context.support.oauth2.Attribute @Attribute} array into a
+ * Turns a {@link org.springframework.security.test.context.support.oauth2.annotations.Attribute @Attribute} array into a
* {@link java.util.Map Map<String, Object>} as required for
* {@link org.springframework.security.oauth2.jwt.Jwt JWT} headers and claims.
*
each {@link org.springframework.security.test.context.support.oauth2.Attribute#value() value()} is parsed
- * according to {@link org.springframework.security.test.context.support.oauth2.Attribute#parserOverride()
+ *
each {@link org.springframework.security.test.context.support.oauth2.annotations.Attribute#value() value()} is parsed
+ * according to {@link org.springframework.security.test.context.support.oauth2.annotations.Attribute#parserOverride()
* parser()}
*
obtained values are associated with
- * {@link org.springframework.security.test.context.support.oauth2.Attribute#name() name()}
values with same name are accumulated in the same collection
*
*
@@ -154,16 +154,16 @@ public Map parse(final Attribute... properties) {
}
/**
- * Instantiates default {@link org.springframework.security.test.context.support.oauth2.AttributeValueParser
+ * Instantiates default {@link org.springframework.security.test.context.support.oauth2.annotations.AttributeValueParser
* AttributeValueParser}s plus all provided ones (using default constructor)
*
- * @param additionalParserNames {@link org.springframework.security.test.context.support.oauth2.AttributeValueParser
+ * @param additionalParserNames {@link org.springframework.security.test.context.support.oauth2.annotations.AttributeValueParser
* AttributeValueParser} implementations class names to add to
- * {@link org.springframework.security.test.context.support.oauth2.AttributeParsersHelper#DEFAULT_PARSERS default
+ * {@link org.springframework.security.test.context.support.oauth2.annotations.AttributeParsersSupport#DEFAULT_PARSERS default
* ones}
* @return helper instance with provided parsers plus default ones
*/
- public static AttributeParsersHelper withDefaultParsers(final String... additionalParserNames) {
+ public static AttributeParsersSupport withDefaultParsers(final String... additionalParserNames) {
final Map> baseParsers = new HashMap<>(9);
baseParsers.put("NoOpParser", (final String value) -> value);
@@ -194,19 +194,19 @@ public static AttributeParsersHelper withDefaultParsers(final String... addition
}
});
- return new AttributeParsersHelper(baseParsers, additionalParserNames);
+ return new AttributeParsersSupport(baseParsers, additionalParserNames);
}
/**
- * Instantiates all provided {@link org.springframework.security.test.context.support.oauth2.AttributeValueParser
+ * Instantiates all provided {@link org.springframework.security.test.context.support.oauth2.annotations.AttributeValueParser
* AttributeValueParser}s using default constructor
*
- * @param allParserNames {@link org.springframework.security.test.context.support.oauth2.AttributeValueParser
+ * @param allParserNames {@link org.springframework.security.test.context.support.oauth2.annotations.AttributeValueParser
* AttributeValueParser} implementations class names
* @return helper instance with provided parsers only
*/
- public static AttributeParsersHelper withoutDefaultParsers(final String... allParserNames) {
- return new AttributeParsersHelper(Collections.emptyMap(), allParserNames);
+ public static AttributeParsersSupport withoutDefaultParsers(final String... allParserNames) {
+ return new AttributeParsersSupport(Collections.emptyMap(), allParserNames);
}
private static final class ParsedProperty {
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AttributeValueParser.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/annotations/AttributeValueParser.java
similarity index 55%
rename from oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AttributeValueParser.java
rename to oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/annotations/AttributeValueParser.java
index 67270a67206..cb38f3de941 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AttributeValueParser.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/annotations/AttributeValueParser.java
@@ -1,16 +1,19 @@
/*
* 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. You may obtain a copy of the License at
+ * 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
+ * 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.
+ * 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.test.context.support.oauth2;
+package org.springframework.security.test.context.support.oauth2.annotations;
/**
*
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/TargetType.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/annotations/TargetType.java
similarity index 51%
rename from oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/TargetType.java
rename to oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/annotations/TargetType.java
index 4dbaa057775..25f0b557888 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/TargetType.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/annotations/TargetType.java
@@ -1,16 +1,19 @@
/*
* 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. You may obtain a copy of the License at
+ * 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
+ * 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.
+ * 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.test.context.support.oauth2;
+package org.springframework.security.test.context.support.oauth2.annotations;
/**
*
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwt.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/annotations/WithMockJwt.java
similarity index 70%
rename from oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwt.java
rename to oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/annotations/WithMockJwt.java
index 940a5008800..87779839089 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/WithMockJwt.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/annotations/WithMockJwt.java
@@ -1,16 +1,21 @@
/*
* 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. You may obtain a copy of the License at
+ * 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
+ * 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.
+ * 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.test.context.support.oauth2;
+package org.springframework.security.test.context.support.oauth2.annotations;
+
+import static org.springframework.security.test.context.support.oauth2.support.CollectionsSupport.asSet;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
@@ -23,11 +28,15 @@
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.security.test.context.support.TestExecutionEvent;
import org.springframework.security.test.context.support.WithSecurityContext;
+import org.springframework.security.test.context.support.WithSecurityContextFactory;
import org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener;
+import org.springframework.security.test.context.support.oauth2.annotations.WithMockJwt.WithMockJwtSecurityContextFactory;
+import org.springframework.security.test.context.support.oauth2.support.JwtSupport;
import org.springframework.test.context.TestContext;
import org.springframework.test.web.servlet.MockMvc;
@@ -55,13 +64,7 @@
*
{@link Authentication#getName() getName()} returns the JWT {@code subject} claim, set from this annotation
* {@code name} value ({@code "user"} by default)
*
{@link Authentication#getAuthorities() authorities} will be a collection of {@link SimpleGrantedAuthority} as
- * defined by this annotation {@link #authorities()} (
- *
- *
- * { "ROLE_USER" }
- *
- *
- * by default
+ * defined by this annotation {@link #authorities()} ({@code "ROLE_USER" } by default)
*
*
* Sample Usage:
@@ -104,16 +107,13 @@
@Documented
@WithSecurityContext(factory = WithMockJwtSecurityContextFactory.class)
public @interface WithMockJwt {
- public static final String DEFAULT_AUTH_NAME = "user";
- public static final String DEFAULT_HEADER_NAME = "alg";
- public static final String DEFAULT_HEADER_VALUE = "test-algorythm";
/**
* Alias for authorities
* @return Authorities the client is to be granted
*/
@AliasFor("authorities")
- String[] value() default { "ROLE_USER" };
+ String[] value() default { "ROLE_USER" };// TODO: use default value in JwtSupport
/**
* Alias for value
@@ -122,11 +122,16 @@
@AliasFor("value")
String[] authorities() default { "ROLE_USER" };
+ /**
+ * @return Scopes the client is to be granted (added to "scope" claim, and authorities with "SCOPE_" prefix)
+ */
+ String[] scopes() default {};
+
/**
* To be used both as authentication {@code Principal} name and token {@code username} attribute.
* @return Resource owner name
*/
- String name() default DEFAULT_AUTH_NAME;
+ String name() default JwtSupport.DEFAULT_AUTH_NAME;
/**
* @return JWT claims
@@ -137,7 +142,8 @@
* Of little use at unit test time...
* @return JWT headers
*/
- Attribute[] headers() default { @Attribute(name = DEFAULT_HEADER_NAME, value = DEFAULT_HEADER_VALUE) };
+ Attribute[] headers() default {
+ @Attribute(name = JwtSupport.DEFAULT_HEADER_NAME, value = JwtSupport.DEFAULT_HEADER_VALUE) };
/**
* Parsers are provided for for all {@link TargetType} but {@link TargetType#OTHER}. Those will be added to parse
@@ -157,4 +163,23 @@
*/
@AliasFor(annotation = WithSecurityContext.class)
TestExecutionEvent setupBefore() default TestExecutionEvent.TEST_METHOD;
+
+ public final class WithMockJwtSecurityContextFactory implements WithSecurityContextFactory {
+ @Override
+ public SecurityContext createSecurityContext(final WithMockJwt annotation) {
+ final AttributeParsersSupport parsersHelper =
+ AttributeParsersSupport.withDefaultParsers(annotation.additionalParsers());
+
+ final SecurityContext context = SecurityContextHolder.createEmptyContext();
+ context.setAuthentication(
+ JwtSupport.authentication(
+ annotation.name(),
+ asSet(annotation.authorities()),
+ asSet(annotation.scopes()),
+ parsersHelper.parse(annotation.claims()),
+ parsersHelper.parse(annotation.headers())));
+
+ return context;
+ }
+ }
}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/request/AbstractOAuth2RequestPostProcessor.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/request/AbstractOAuth2RequestPostProcessor.java
new file mode 100644
index 00000000000..c08de5ca49f
--- /dev/null
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/request/AbstractOAuth2RequestPostProcessor.java
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ * 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.test.context.support.oauth2.request;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.springframework.security.test.context.support.oauth2.support.CollectionsSupport.asSet;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import org.springframework.test.web.servlet.request.RequestPostProcessor;
+
+/**
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ */
+public abstract class AbstractOAuth2RequestPostProcessor>
+ implements
+ RequestPostProcessor {
+
+ private static final String ROLE_PREFIX = "ROLE_";
+
+ private static final String SCOPE_PREFIX = "SCOPE_";
+
+ protected String name;
+
+ protected final Collection authorities;
+
+ protected boolean isAuthoritiesSet = false;
+
+ protected final Collection scopes = new HashSet<>();
+
+ protected final Map attributes = new HashMap<>();
+
+ protected AbstractOAuth2RequestPostProcessor(final String defaultName, final String[] defaultAuthorities) {
+ this.name = defaultName;
+ this.authorities = new HashSet<>(asSet(defaultAuthorities));
+ }
+
+ public T name(final String name) {
+ this.name = name;
+ return downCast();
+ }
+
+ public T authority(final String authority) {
+ assertNotNull(authority);
+ this.isAuthoritiesSet = true;
+ this.authorities.add(authority);
+ if (authority.startsWith(SCOPE_PREFIX)) {
+ this.scopes.add(authority.substring(SCOPE_PREFIX.length()));
+ }
+ return downCast();
+ }
+
+ public T authorities(final String... authorities) {
+ Stream.of(authorities).forEach(this::authority);
+ return downCast();
+ }
+
+ public T role(final String role) {
+ assertNotNull(role);
+ assertFalse(role.startsWith(ROLE_PREFIX));
+ return authority(ROLE_PREFIX + role);
+ }
+
+ public T roles(final String... roles) {
+ Stream.of(roles).forEach(this::role);
+ return downCast();
+ }
+
+ public T scope(final String role) {
+ assertNotNull(role);
+ assertFalse(role.startsWith(SCOPE_PREFIX));
+ return authority(SCOPE_PREFIX + role);
+ }
+
+ public T scopes(final String... scope) {
+ Stream.of(scope).forEach(this::role);
+ return downCast();
+ }
+
+ public T attributes(final Map attributes) {
+ assertNotNull(attributes);
+ attributes.entrySet().stream().forEach(e -> this.attribute(e.getKey(), e.getValue()));
+ return downCast();
+ }
+
+ public T attribute(final String name, final Object value) {
+ assertNotNull(name);
+ this.attributes.put(name, value);
+ return downCast();
+ }
+
+ @SuppressWarnings("unchecked")
+ private T downCast() {
+ return (T) this;
+ }
+
+}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/request/JwtRequestPostProcessor.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/request/JwtRequestPostProcessor.java
new file mode 100644
index 00000000000..a828b127b1d
--- /dev/null
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/request/JwtRequestPostProcessor.java
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ * 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.test.context.support.oauth2.request;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.test.context.support.oauth2.support.JwtSupport;
+import org.springframework.security.test.web.servlet.request.SecurityContextRequestPostProcessorSupport;
+
+/**
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ */
+public class JwtRequestPostProcessor extends AbstractOAuth2RequestPostProcessor {
+
+ private static Map DEFAULT_HEADERS =
+ Collections.singletonMap(JwtSupport.DEFAULT_HEADER_NAME, JwtSupport.DEFAULT_HEADER_VALUE);
+
+ private Map headers = DEFAULT_HEADERS;
+
+ private boolean isHeadersSet = false;
+
+ public JwtRequestPostProcessor() {
+ super(JwtSupport.DEFAULT_AUTH_NAME, JwtSupport.DEFAULT_AUTHORITIES);
+ }
+
+ @Override
+ public MockHttpServletRequest postProcessRequest(final MockHttpServletRequest request) {
+ final Authentication authentication = JwtSupport.authentication(name, authorities, scopes, attributes, headers);
+ SecurityContextRequestPostProcessorSupport.createSecurityContext(authentication, request);
+ return request;
+ }
+
+ public JwtRequestPostProcessor claims(final Map claims) {
+ return attributes(claims);
+ }
+
+ public JwtRequestPostProcessor claim(final String name, final Object value) {
+ return attribute(name, value);
+ }
+
+ public JwtRequestPostProcessor headers(final Map headers) {
+ headers.entrySet().stream().forEach(e -> this.header(e.getKey(), e.getValue()));
+ return this;
+ }
+
+ public JwtRequestPostProcessor header(final String name, final Object value) {
+ assertNotNull(name);
+ if (this.isHeadersSet == false) {
+ this.headers = new HashMap<>();
+ this.isHeadersSet = true;
+ }
+ this.headers.put(name, value);
+ return this;
+ }
+
+}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/request/OAuth2MockMvcRequestPostProcessors.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/request/OAuth2MockMvcRequestPostProcessors.java
new file mode 100644
index 00000000000..2be77e0cf1e
--- /dev/null
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/request/OAuth2MockMvcRequestPostProcessors.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ * 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.test.context.support.oauth2.request;
+
+/**
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ */
+public final class OAuth2MockMvcRequestPostProcessors {
+
+ public static JwtRequestPostProcessor jwt() {
+ return new JwtRequestPostProcessor();
+ }
+
+}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/support/AuthoritiesAndScopes.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/support/AuthoritiesAndScopes.java
new file mode 100644
index 00000000000..94323cbd704
--- /dev/null
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/support/AuthoritiesAndScopes.java
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ * 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.test.context.support.oauth2.support;
+
+import static org.springframework.security.test.context.support.oauth2.support.CollectionsSupport.putIfNotEmpty;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+
+/**
+ * Helps merging {@code authorities} and {@code scope}.
+ *
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ *
+ */
+final class AuthoritiesAndScopes {
+ public final Set authorities;
+ public final Set scopes;
+ public final Optional scopeAttributeName;
+
+ private AuthoritiesAndScopes(
+ final Set authorities,
+ final Set scopes,
+ final Optional scopeAttributeName) {
+ this.authorities = Collections.unmodifiableSet(authorities);
+ this.scopes = Collections.unmodifiableSet(scopes);
+ this.scopeAttributeName = scopeAttributeName;
+ }
+
+ /**
+ * Merges {@code authorities} and {@code scope}. Scopes are scanned for in:
+ *
+ *
scopes of course
+ *
authorities ("SCOPE_" prefix)
+ *
claims with keys "scope", "scp" and "scopes", first entry found being used and others ignored
+ *
+ *
+ * All scopes are merged and set in claims, authorities and allScopes
+ *
+ *
+ * @param authorities authorities array (probably from an annotation {@code authorities()})
+ * @param scopes scopes array (probably from an annotation {@code scopes()})
+ * @param attributes attributes /!\ mutable /!\ map (probably from an annotation {@code attributes()} or
+ * {@code claims()})
+ * @return a structure containing merged granted authorities and scopes
+ */
+ public static AuthoritiesAndScopes get(
+ final Collection authorities,
+ final Collection scopes,
+ final Map attributes) {
+
+ final Optional scopeAttributeName = attributes.keySet()
+ .stream()
+ .filter(k -> "scope".equals(k) || "scp".equals(k) || "scopes".equals(k))
+ .sorted()
+ .findFirst();
+
+ final Optional scopeAttribute = scopeAttributeName.map(attributes::get);
+
+ final boolean scopeIsString = scopeAttribute.map(s -> s instanceof String).orElse(false);
+
+ final Stream attributesScopes = scopeAttribute.map(s -> {
+ if (scopeIsString) {
+ return Stream.of(scopeAttribute.get().toString().split(" "));
+ }
+ return AuthoritiesAndScopes.asStringStream(scopeAttribute.get());
+ }).orElse(Stream.empty());
+
+ final Stream authoritiesScopes =
+ authorities.stream().filter(a -> a.startsWith("SCOPE_")).map(a -> a.substring(6));
+
+ final Set allScopes = Stream.concat(scopes.stream(), Stream.concat(authoritiesScopes, attributesScopes))
+ .collect(Collectors.toSet());
+
+ if (scopeIsString) {
+ putIfNotEmpty(
+ scopeAttributeName.orElse("scope"),
+ allScopes.stream().collect(Collectors.joining(" ")),
+ attributes);
+ } else {
+ putIfNotEmpty(scopeAttributeName.orElse("scope"), allScopes, attributes);
+ }
+
+ final Set allAuthorities =
+ Stream.concat(authorities.stream(), allScopes.stream().map(scope -> "SCOPE_" + scope))
+ .map(SimpleGrantedAuthority::new)
+ .collect(Collectors.toSet());
+
+ return new AuthoritiesAndScopes(allAuthorities, allScopes, scopeAttributeName);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Stream asStringStream(final Object col) {
+ return col == null ? Stream.empty() : ((Collection) col).stream();
+ }
+}
\ No newline at end of file
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AnnotationHelper.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/support/CollectionsSupport.java
similarity index 51%
rename from oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AnnotationHelper.java
rename to oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/support/CollectionsSupport.java
index 6ed83c36730..1d3d4752850 100644
--- a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/AnnotationHelper.java
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/support/CollectionsSupport.java
@@ -1,30 +1,36 @@
/*
* 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. You may obtain a copy of the License at
+ * 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
+ * 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.
+ * 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.test.context.support.oauth2;
+package org.springframework.security.test.context.support.oauth2.support;
import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import org.springframework.util.StringUtils;
/**
- * Useful functions to manipulate annotation values
- *
* @author Jérôme Wacongne <ch4mp@c4-soft.com>
* @since 5.2.0
*
*/
-class AnnotationHelper {
+public class CollectionsSupport {
public static String nullIfEmpty(final String str) {
return StringUtils.isEmpty(str) ? null : str;
@@ -46,4 +52,12 @@ public static String nullIfEmpty(final String str) {
return map;
}
+ public static final Set asSet(final String... values) {
+ return values.length == 0 ? Collections.emptySet() : Stream.of(values).collect(Collectors.toSet());
+ }
+
+ public static final List asList(final String... values) {
+ return values.length == 0 ? Collections.emptyList() : Stream.of(values).collect(Collectors.toList());
+ }
+
}
diff --git a/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/support/JwtSupport.java b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/support/JwtSupport.java
new file mode 100644
index 00000000000..dfc2548fb1e
--- /dev/null
+++ b/oauth2-test/src/main/java/org/springframework/security/test/context/support/oauth2/support/JwtSupport.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ * 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.test.context.support.oauth2.support;
+
+import static org.springframework.security.test.context.support.oauth2.support.CollectionsSupport.putIfNotEmpty;
+
+import java.time.Instant;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.security.oauth2.jwt.Jwt;
+import org.springframework.security.oauth2.jwt.JwtClaimNames;
+import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
+
+/**
+ * @author Jérôme Wacongne <ch4mp@c4-soft.com>
+ * @since 5.2.0
+ */
+public class JwtSupport {
+ public static final String DEFAULT_TOKEN_VALUE = "test.jwt.value";
+ public static final String DEFAULT_AUTH_NAME = "user";
+ public static final String DEFAULT_HEADER_NAME = "test-header";
+ public static final String DEFAULT_HEADER_VALUE = "abracadabra";
+ public static final String[] DEFAULT_AUTHORITIES = { "ROLE_USER" };
+
+ public static JwtAuthenticationToken authentication(
+ final String name,
+ final Collection authorities,
+ final Collection scopes,
+ final Map claims,
+ final Map headers) {
+ final Map postrPocessedClaims = new HashMap<>(claims);
+ if (claims.containsKey(JwtClaimNames.SUB)) {
+ throw new RuntimeException(JwtClaimNames.SUB + " claim is not configurable (forced to \"name\")");
+ } else {
+ putIfNotEmpty(JwtClaimNames.SUB, name, postrPocessedClaims);
+ }
+
+ final AuthoritiesAndScopes authoritiesAndScopes =
+ AuthoritiesAndScopes.get(authorities, scopes, postrPocessedClaims);
+
+ return new JwtAuthenticationToken(
+ new Jwt(
+ DEFAULT_TOKEN_VALUE,
+ (Instant) postrPocessedClaims.get(JwtClaimNames.IAT),
+ (Instant) postrPocessedClaims.get(JwtClaimNames.EXP),
+ headers,
+ postrPocessedClaims),
+ authoritiesAndScopes.authorities);
+ }
+}
diff --git a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AttributeParsersHelperTest.java b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/annotations/AttributeParsersSupportTest.java
similarity index 74%
rename from oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AttributeParsersHelperTest.java
rename to oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/annotations/AttributeParsersSupportTest.java
index 675b451e358..126fadafe42 100644
--- a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AttributeParsersHelperTest.java
+++ b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/annotations/AttributeParsersSupportTest.java
@@ -1,16 +1,19 @@
/*
* 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. You may obtain a copy of the License at
+ * 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
+ * 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.
+ * 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.test.context.support.oauth2;
+package org.springframework.security.test.context.support.oauth2.annotations;
import static org.assertj.core.api.Assertions.assertThat;
@@ -22,9 +25,6 @@
import org.junit.Test;
import org.springframework.core.annotation.AnnotationUtils;
-import org.springframework.security.test.context.support.oauth2.Attribute;
-import org.springframework.security.test.context.support.oauth2.AttributeParsersHelper;
-import org.springframework.security.test.context.support.oauth2.AttributeValueParser;
/**
*
@@ -32,7 +32,7 @@
* @since 5.2.0
*
*/
-public class AttributeParsersHelperTest {
+public class AttributeParsersSupportTest {
@Attribute(name = "a", value = "bidule", parserOverride = "SomeTypeParser")
private static final class AProperty {
@@ -41,14 +41,14 @@ private static final class AProperty {
@Attribute(
name = "b",
value = "chose",
- parserOverride = "org.springframework.security.test.context.support.oauth2.AttributeParsersHelperTest$SomeTypeParser")
+ parserOverride = "org.springframework.security.test.context.support.oauth2.annotations.AttributeParsersSupportTest$SomeTypeParser")
private static final class BProperty {
}
@Test
public void parsePropertiesWithDistinctNames() {
- final AttributeParsersHelper helper = AttributeParsersHelper.withoutDefaultParsers(
- "org.springframework.security.test.context.support.oauth2.AttributeParsersHelperTest$SomeTypeParser");
+ final AttributeParsersSupport helper = AttributeParsersSupport.withoutDefaultParsers(
+ "org.springframework.security.test.context.support.oauth2.annotations.AttributeParsersSupportTest$SomeTypeParser");
final Attribute propertyAnnotationA = AnnotationUtils.findAnnotation(AProperty.class, Attribute.class);
final Attribute propertyAnnotationB = AnnotationUtils.findAnnotation(BProperty.class, Attribute.class);
@@ -70,7 +70,7 @@ private static final class DProperty {
@SuppressWarnings("unchecked")
@Test
public void parsePropertiesWithSameNameAccumulatesValues() {
- final AttributeParsersHelper helper = AttributeParsersHelper.withDefaultParsers();
+ final AttributeParsersSupport helper = AttributeParsersSupport.withDefaultParsers();
final Attribute propertyAnnotationC = AnnotationUtils.findAnnotation(CProperty.class, Attribute.class);
final Attribute propertyAnnotationD = AnnotationUtils.findAnnotation(DProperty.class, Attribute.class);
@@ -88,8 +88,8 @@ private static final class EProperty {
@Test
public void parsePropertiesUsesParseroverrides() {
- final AttributeParsersHelper helper = AttributeParsersHelper.withDefaultParsers(
- "org.springframework.security.test.context.support.oauth2.AttributeParsersHelperTest$InstantParser");
+ final AttributeParsersSupport helper = AttributeParsersSupport.withDefaultParsers(
+ "org.springframework.security.test.context.support.oauth2.annotations.AttributeParsersSupportTest$InstantParser");
final Attribute propertyAnnotation = AnnotationUtils.findAnnotation(EProperty.class, Attribute.class);
diff --git a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactoryTests.java b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/annotations/WithMockJwtSecurityContextFactoryTests.java
similarity index 81%
rename from oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactoryTests.java
rename to oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/annotations/WithMockJwtSecurityContextFactoryTests.java
index 18baa697e6a..9bd3f50abde 100644
--- a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtSecurityContextFactoryTests.java
+++ b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/annotations/WithMockJwtSecurityContextFactoryTests.java
@@ -1,16 +1,19 @@
/*
* 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. You may obtain a copy of the License at
+ * 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
+ * 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.
+ * 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.test.context.support.oauth2;
+package org.springframework.security.test.context.support.oauth2.annotations;
import static org.assertj.core.api.Assertions.assertThat;
@@ -26,6 +29,8 @@
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtClaimNames;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
+import org.springframework.security.test.context.support.oauth2.annotations.WithMockJwt.WithMockJwtSecurityContextFactory;
+import org.springframework.security.test.context.support.oauth2.support.JwtSupport;
/**
*
@@ -76,7 +81,7 @@ private static class CustomAdvanced {
@Attribute(name = JwtClaimNames.JTI, value = "test ID"),
@Attribute(name = "custom-claim", value = "foo") },
additionalParsers = {
- "org.springframework.security.test.context.support.oauth2.WithMockJwtSecurityContextFactoryTests$FooParser" })
+ "org.springframework.security.test.context.support.oauth2.annotations.WithMockJwtSecurityContextFactoryTests$FooParser" })
private static class CustomFull {
}
@@ -86,7 +91,7 @@ public void defaults() {
final Authentication auth = factory.createSecurityContext(annotation).getAuthentication();
- assertThat(auth.getName()).isEqualTo(WithMockJwt.DEFAULT_AUTH_NAME);
+ assertThat(auth.getName()).isEqualTo(JwtSupport.DEFAULT_AUTH_NAME);
assertThat(auth.getAuthorities()).hasSize(1);
assertThat(auth.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_USER"))).isTrue();
assertThat(auth.getPrincipal()).isInstanceOf(Jwt.class);
@@ -96,8 +101,8 @@ public void defaults() {
assertThat(auth.getCredentials()).isEqualTo(jwt);
assertThat(auth.getDetails()).isNull();
- assertThat(jwt.getTokenValue()).isEqualTo(WithMockJwtSecurityContextFactory.DEFAULT_TOKEN_VALUE);
- assertThat(jwt.getSubject()).isEqualTo(WithMockJwt.DEFAULT_AUTH_NAME);
+ assertThat(jwt.getTokenValue()).isEqualTo(JwtSupport.DEFAULT_TOKEN_VALUE);
+ assertThat(jwt.getSubject()).isEqualTo(JwtSupport.DEFAULT_AUTH_NAME);
assertThat(jwt.getAudience()).isNull();
assertThat(jwt.getIssuer()).isNull();
assertThat(jwt.getIssuedAt()).isNull();
@@ -107,7 +112,7 @@ public void defaults() {
final Map headers = jwt.getHeaders();
assertThat(headers).hasSize(1);
- assertThat(headers.get(WithMockJwt.DEFAULT_HEADER_NAME)).isEqualTo(WithMockJwt.DEFAULT_HEADER_VALUE);
+ assertThat(headers.get(JwtSupport.DEFAULT_HEADER_NAME)).isEqualTo(JwtSupport.DEFAULT_HEADER_VALUE);
}
@Test
@@ -116,7 +121,7 @@ public void customMini() {
final Authentication auth = factory.createSecurityContext(annotation).getAuthentication();
- assertThat(auth.getName()).isEqualTo(WithMockJwt.DEFAULT_AUTH_NAME);
+ assertThat(auth.getName()).isEqualTo(JwtSupport.DEFAULT_AUTH_NAME);
assertThat(auth.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_ADMIN"))).isTrue();
assertThat(auth.getPrincipal()).isInstanceOf(Jwt.class);
@@ -125,8 +130,8 @@ public void customMini() {
assertThat(auth.getCredentials()).isEqualTo(jwt);
assertThat(auth.getDetails()).isNull();
- assertThat(jwt.getTokenValue()).isEqualTo(WithMockJwtSecurityContextFactory.DEFAULT_TOKEN_VALUE);
- assertThat(jwt.getSubject()).isEqualTo(WithMockJwt.DEFAULT_AUTH_NAME);
+ assertThat(jwt.getTokenValue()).isEqualTo(JwtSupport.DEFAULT_TOKEN_VALUE);
+ assertThat(jwt.getSubject()).isEqualTo(JwtSupport.DEFAULT_AUTH_NAME);
assertThat(jwt.getAudience()).isNull();
assertThat(jwt.getIssuer()).isNull();
assertThat(jwt.getIssuedAt()).isNull();
@@ -136,7 +141,7 @@ public void customMini() {
final Map headers = jwt.getHeaders();
assertThat(headers).hasSize(1);
- assertThat(headers.get(WithMockJwt.DEFAULT_HEADER_NAME)).isEqualTo(WithMockJwt.DEFAULT_HEADER_VALUE);
+ assertThat(headers.get(JwtSupport.DEFAULT_HEADER_NAME)).isEqualTo(JwtSupport.DEFAULT_HEADER_VALUE);
}
@Test
@@ -160,7 +165,7 @@ public void customFrequent() {
assertThat(auth.getCredentials()).isEqualTo(jwt);
assertThat(auth.getDetails()).isNull();
- assertThat(jwt.getTokenValue()).isEqualTo(WithMockJwtSecurityContextFactory.DEFAULT_TOKEN_VALUE);
+ assertThat(jwt.getTokenValue()).isEqualTo(JwtSupport.DEFAULT_TOKEN_VALUE);
assertThat(jwt.getSubject()).isEqualTo("Test User");
assertThat(jwt.getAudience()).isNull();
assertThat(jwt.getIssuer()).isNull();
@@ -171,7 +176,7 @@ public void customFrequent() {
final Map headers = jwt.getHeaders();
assertThat(headers).hasSize(1);
- assertThat(headers.get(WithMockJwt.DEFAULT_HEADER_NAME)).isEqualTo(WithMockJwt.DEFAULT_HEADER_VALUE);
+ assertThat(headers.get(JwtSupport.DEFAULT_HEADER_NAME)).isEqualTo(JwtSupport.DEFAULT_HEADER_VALUE);
}
@Test
@@ -195,7 +200,7 @@ public void customAdvanced() {
assertThat(auth.getCredentials()).isEqualTo(jwt);
assertThat(auth.getDetails()).isNull();
- assertThat(jwt.getTokenValue()).isEqualTo(WithMockJwtSecurityContextFactory.DEFAULT_TOKEN_VALUE);
+ assertThat(jwt.getTokenValue()).isEqualTo(JwtSupport.DEFAULT_TOKEN_VALUE);
assertThat(jwt.getSubject()).isEqualTo("Test User");
assertThat(jwt.getAudience()).isNull();
assertThat(jwt.getIssuer()).isNull();
@@ -207,7 +212,7 @@ public void customAdvanced() {
final Map headers = jwt.getHeaders();
assertThat(headers).hasSize(1);
- assertThat(headers.get(WithMockJwt.DEFAULT_HEADER_NAME)).isEqualTo(WithMockJwt.DEFAULT_HEADER_VALUE);
+ assertThat(headers.get(JwtSupport.DEFAULT_HEADER_NAME)).isEqualTo(JwtSupport.DEFAULT_HEADER_VALUE);
}
@Test
@@ -241,7 +246,7 @@ public void custom() throws Exception {
assertThat(principal.getIssuer()).isEqualTo(new URL("https://test-issuer.org"));
assertThat(principal.getSubject()).isEqualTo("truc");
assertThat(principal.getNotBefore()).isNull();
- assertThat(principal.getTokenValue()).isEqualTo(WithMockJwtSecurityContextFactory.DEFAULT_TOKEN_VALUE);
+ assertThat(principal.getTokenValue()).isEqualTo(JwtSupport.DEFAULT_TOKEN_VALUE);
assertThat(principal.getClaims().get("custom-claim")).isEqualTo("foo");
}
diff --git a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtTests.java b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/annotations/WithMockJwtTests.java
similarity index 73%
rename from oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtTests.java
rename to oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/annotations/WithMockJwtTests.java
index 9397b03dd1d..d8041da2fc8 100644
--- a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/WithMockJwtTests.java
+++ b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/annotations/WithMockJwtTests.java
@@ -1,16 +1,19 @@
/*
* 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. You may obtain a copy of the License at
+ * 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
+ * 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.
+ * 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.test.context.support.oauth2;
+package org.springframework.security.test.context.support.oauth2.annotations;
import static org.assertj.core.api.Assertions.assertThat;
@@ -19,6 +22,9 @@
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.security.test.context.support.TestExecutionEvent;
import org.springframework.security.test.context.support.WithSecurityContext;
+import org.springframework.security.test.context.support.oauth2.annotations.Attribute;
+import org.springframework.security.test.context.support.oauth2.annotations.WithMockJwt;
+import org.springframework.security.test.context.support.oauth2.support.JwtSupport;
/**
*
@@ -31,7 +37,7 @@ public class WithMockJwtTests {
@Test
public void defaults() {
final WithMockJwt auth = AnnotationUtils.findAnnotation(Annotated.class, WithMockJwt.class);
- assertThat(auth.name()).isEqualTo(WithMockJwt.DEFAULT_AUTH_NAME);
+ assertThat(auth.name()).isEqualTo(JwtSupport.DEFAULT_AUTH_NAME);
assertThat(auth.authorities()).hasSize(1);
assertThat(auth.authorities()).contains("ROLE_USER");
assertThat(auth.headers()).hasAtLeastOneElementOfType(Attribute.class);
diff --git a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AuthoritiesAndScopesTest.java b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/support/AuthoritiesAndScopesTest.java
similarity index 67%
rename from oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AuthoritiesAndScopesTest.java
rename to oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/support/AuthoritiesAndScopesTest.java
index 2d10ec9938c..4fcc6920506 100644
--- a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AuthoritiesAndScopesTest.java
+++ b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/support/AuthoritiesAndScopesTest.java
@@ -1,18 +1,22 @@
/*
* 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. You may obtain a copy of the License at
+ * 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
+ * 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.
+ * 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.test.context.support.oauth2;
+package org.springframework.security.test.context.support.oauth2.support;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.springframework.security.test.context.support.oauth2.support.CollectionsSupport.asSet;
import java.util.Collections;
import java.util.HashMap;
@@ -31,11 +35,11 @@
public class AuthoritiesAndScopesTest {
@Test
- public void testScopeAttribute() {
+ public void testScopeCollectionAttribute() {
final Map attributes = new HashMap<>();
attributes.put("scope", Collections.singleton("c"));
final AuthoritiesAndScopes actual =
- AuthoritiesAndScopes.get(new String[] { "AUTHORITY_A", "SCOPE_a" }, new String[] { "b" }, attributes);
+ AuthoritiesAndScopes.get(asSet("AUTHORITY_A", "SCOPE_a"), asSet("b"), attributes);
assertThat(actual.authorities).hasSize(4);
assertThat(actual.authorities).contains(new SimpleGrantedAuthority("AUTHORITY_A"));
@@ -51,12 +55,35 @@ public void testScopeAttribute() {
assertThat(actual.scopeAttributeName).isEqualTo(Optional.of("scope"));
}
+ @Test
+ public void testScopeStringAttribute() {
+ final Map attributes = new HashMap<>();
+ attributes.put("scope", "c");
+ final AuthoritiesAndScopes actual =
+ AuthoritiesAndScopes.get(asSet("AUTHORITY_A", "SCOPE_a"), asSet("b"), attributes);
+
+ assertThat(actual.authorities).hasSize(4);
+ assertThat(actual.authorities).contains(new SimpleGrantedAuthority("AUTHORITY_A"));
+ assertThat(actual.authorities).contains(new SimpleGrantedAuthority("SCOPE_a"));
+ assertThat(actual.authorities).contains(new SimpleGrantedAuthority("SCOPE_b"));
+ assertThat(actual.authorities).contains(new SimpleGrantedAuthority("SCOPE_c"));
+
+ assertThat(actual.scopes).hasSize(3);
+ assertThat(actual.scopes).contains("a");
+ assertThat(actual.scopes).contains("b");
+ assertThat(actual.scopes).contains("c");
+
+ assertThat(attributes.get("scope")).isEqualTo("a b c");
+
+ assertThat(actual.scopeAttributeName).isEqualTo(Optional.of("scope"));
+ }
+
@Test
public void testScpAttribute() {
final Map attributes = new HashMap<>();
attributes.put("scp", Collections.singleton("c"));
final AuthoritiesAndScopes actual =
- AuthoritiesAndScopes.get(new String[] { "AUTHORITY_A", "SCOPE_a" }, new String[] { "b" }, attributes);
+ AuthoritiesAndScopes.get(asSet("AUTHORITY_A", "SCOPE_a"), asSet("b"), attributes);
assertThat(actual.authorities).hasSize(4);
assertThat(actual.authorities).contains(new SimpleGrantedAuthority("AUTHORITY_A"));
@@ -69,6 +96,8 @@ public void testScpAttribute() {
assertThat(actual.scopes).contains("b");
assertThat(actual.scopes).contains("c");
+ assertThat(attributes.get("scp")).isEqualTo(actual.scopes);
+
assertThat(actual.scopeAttributeName).isEqualTo(Optional.of("scp"));
}
@@ -77,7 +106,7 @@ public void testScopesAttribute() {
final Map attributes = new HashMap<>();
attributes.put("scopes", Collections.singleton("c"));
final AuthoritiesAndScopes actual =
- AuthoritiesAndScopes.get(new String[] { "AUTHORITY_A", "SCOPE_a" }, new String[] { "b" }, attributes);
+ AuthoritiesAndScopes.get(asSet("AUTHORITY_A", "SCOPE_a"), asSet("b"), attributes);
assertThat(actual.authorities).hasSize(4);
assertThat(actual.authorities).contains(new SimpleGrantedAuthority("AUTHORITY_A"));
@@ -100,7 +129,7 @@ public void testAttributeCollision() {
attributes.put("scope", Collections.singleton("d"));
attributes.put("scp", Collections.singleton("e"));
final AuthoritiesAndScopes actual =
- AuthoritiesAndScopes.get(new String[] { "AUTHORITY_A", "SCOPE_a" }, new String[] { "b" }, attributes);
+ AuthoritiesAndScopes.get(asSet("AUTHORITY_A", "SCOPE_a"), asSet("b"), attributes);
assertThat(actual.authorities).hasSize(4);
assertThat(actual.authorities).contains(new SimpleGrantedAuthority("AUTHORITY_A"));
diff --git a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AnnotationHelperTest.java b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/support/CollectionsSupportTest.java
similarity index 79%
rename from oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AnnotationHelperTest.java
rename to oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/support/CollectionsSupportTest.java
index 87fc69d305d..b6c03ba5c70 100644
--- a/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/AnnotationHelperTest.java
+++ b/oauth2-test/src/test/java/org/springframework/security/test/context/support/oauth2/support/CollectionsSupportTest.java
@@ -1,20 +1,23 @@
/*
* 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. You may obtain a copy of the License at
+ * 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
+ * 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.
+ * 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.test.context.support.oauth2;
+package org.springframework.security.test.context.support.oauth2.support;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.springframework.security.test.context.support.oauth2.AnnotationHelper.nullIfEmpty;
-import static org.springframework.security.test.context.support.oauth2.AnnotationHelper.putIfNotEmpty;
+import static org.springframework.security.test.context.support.oauth2.support.CollectionsSupport.nullIfEmpty;
+import static org.springframework.security.test.context.support.oauth2.support.CollectionsSupport.putIfNotEmpty;
import java.util.Collections;
import java.util.HashMap;
@@ -28,7 +31,7 @@
* @since 5.2.0
*
*/
-public class AnnotationHelperTest {
+public class CollectionsSupportTest {
@Test
public void nullIfEmptyReturnsNullForNullString() {
diff --git a/samples/boot/oauth2resourceserver/src/test/java/sample/OAuth2ResourceServerControllerTest.java b/samples/boot/oauth2resourceserver/src/test/java/sample/OAuth2ResourceServerControllerTest.java
index 7208d433db1..72bf55e9228 100644
--- a/samples/boot/oauth2resourceserver/src/test/java/sample/OAuth2ResourceServerControllerTest.java
+++ b/samples/boot/oauth2resourceserver/src/test/java/sample/OAuth2ResourceServerControllerTest.java
@@ -13,20 +13,23 @@
package sample;
import static org.hamcrest.CoreMatchers.is;
+import static org.springframework.security.test.context.support.oauth2.request.OAuth2MockMvcRequestPostProcessors.jwt;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import java.util.Collections;
+
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.security.oauth2.jwt.JwtDecoder;
-import org.springframework.security.test.context.support.oauth2.Attribute;
-import org.springframework.security.test.context.support.oauth2.TargetType;
-import org.springframework.security.test.context.support.oauth2.WithMockJwt;
+import org.springframework.security.test.context.support.oauth2.annotations.Attribute;
+import org.springframework.security.test.context.support.oauth2.annotations.TargetType;
+import org.springframework.security.test.context.support.oauth2.annotations.WithMockJwt;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
@@ -79,4 +82,32 @@ public void testMessageIsNotAcciessibleWithDefaultAuthority() throws Exception {
mockMvc.perform(get("/message")).andDo(print()).andExpect(status().isForbidden());
}
+ @Test
+ public void testRequestPostProcessor() throws Exception {
+ // No post-processor => no authorization => unauthorized
+ mockMvc.perform(get("/message")).andDo(print()).andExpect(status().isUnauthorized());
+
+ mockMvc.perform(get("/").with(jwt().name("ch4mpy")))
+ .andDo(print())
+ .andExpect(status().isOk())
+ .andExpect(content().string(is("Hello, ch4mpy!")));
+
+ mockMvc.perform(get("/message").with(jwt().scope("message:read")))
+ .andDo(print())
+ .andExpect(status().isOk())
+ .andExpect(content().string(is("secret message")));
+
+ mockMvc.perform(get("/message").with(jwt().authority("SCOPE_message:read")))
+ .andDo(print())
+ .andExpect(status().isOk())
+ .andExpect(content().string(is("secret message")));
+
+ mockMvc.perform(get("/message").with(jwt().claim("scope", Collections.singletonList("message:read"))))
+ .andDo(print())
+ .andExpect(status().isOk())
+ .andExpect(content().string(is("secret message")));
+
+ mockMvc.perform(get("/message").with(jwt().name("ch4mpy"))).andDo(print()).andExpect(status().isForbidden());
+ }
+
}
diff --git a/test/src/main/java/org/springframework/security/test/web/servlet/request/SecurityContextRequestPostProcessorSupport.java b/test/src/main/java/org/springframework/security/test/web/servlet/request/SecurityContextRequestPostProcessorSupport.java
new file mode 100644
index 00000000000..37c7f483b80
--- /dev/null
+++ b/test/src/main/java/org/springframework/security/test/web/servlet/request/SecurityContextRequestPostProcessorSupport.java
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ * 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.test.web.servlet.request;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.test.web.support.WebTestUtils;
+import org.springframework.security.web.context.HttpRequestResponseHolder;
+import org.springframework.security.web.context.SecurityContextRepository;
+import org.springframework.test.web.servlet.request.RequestPostProcessor;
+
+/**
+ * Support class for {@link RequestPostProcessor}'s that establish a Spring Security context
+ *
+ * @author Rob Winch
+ * @since 4.0
+ */
+public abstract class SecurityContextRequestPostProcessorSupport {
+
+ public static SecurityContext
+ createSecurityContext(final Authentication authentication, final HttpServletRequest request) {
+ return save(authentication, request);
+ }
+
+ /**
+ * Saves the specified {@link Authentication} into an empty {@link SecurityContext} using the
+ * {@link SecurityContextRepository}.
+ *
+ * @param authentication the {@link Authentication} to save
+ * @param request the {@link HttpServletRequest} to use
+ */
+ static SecurityContext save(final Authentication authentication, final HttpServletRequest request) {
+ final SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
+ securityContext.setAuthentication(authentication);
+ save(securityContext, request);
+ return securityContext;
+ }
+
+ /**
+ * Saves the {@link SecurityContext} using the {@link SecurityContextRepository}
+ *
+ * @param securityContext the {@link SecurityContext} to save
+ * @param request the {@link HttpServletRequest} to use
+ */
+ static void save(final SecurityContext securityContext, HttpServletRequest request) {
+ SecurityContextRepository securityContextRepository = WebTestUtils.getSecurityContextRepository(request);
+ final boolean isTestRepository =
+ securityContextRepository instanceof SecurityContextRequestPostProcessorSupport.TestSecurityContextRepository;
+ if (!isTestRepository) {
+ securityContextRepository = new TestSecurityContextRepository(securityContextRepository);
+ WebTestUtils.setSecurityContextRepository(request, securityContextRepository);
+ }
+
+ HttpServletResponse response = new MockHttpServletResponse();
+
+ final HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response);
+ securityContextRepository.loadContext(requestResponseHolder);
+
+ request = requestResponseHolder.getRequest();
+ response = requestResponseHolder.getResponse();
+
+ securityContextRepository.saveContext(securityContext, request, response);
+ }
+
+ /**
+ * Used to wrap the SecurityContextRepository to provide support for testing in stateless mode
+ */
+ static class TestSecurityContextRepository implements SecurityContextRepository {
+ private final static String ATTR_NAME =
+ SecurityContextRequestPostProcessorSupport.TestSecurityContextRepository.class.getName()
+ .concat(".REPO");
+
+ private final SecurityContextRepository delegate;
+
+ private TestSecurityContextRepository(final SecurityContextRepository delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public SecurityContext loadContext(final HttpRequestResponseHolder requestResponseHolder) {
+ final SecurityContext result = getContext(requestResponseHolder.getRequest());
+ // always load from the delegate to ensure the request/response in the
+ // holder are updated
+ // remember the SecurityContextRepository is used in many different
+ // locations
+ final SecurityContext delegateResult = this.delegate.loadContext(requestResponseHolder);
+ return result == null ? delegateResult : result;
+ }
+
+ @Override
+ public void saveContext(
+ final SecurityContext context,
+ final HttpServletRequest request,
+ final HttpServletResponse response) {
+ request.setAttribute(ATTR_NAME, context);
+ this.delegate.saveContext(context, request, response);
+ }
+
+ @Override
+ public boolean containsContext(final HttpServletRequest request) {
+ return getContext(request) != null || this.delegate.containsContext(request);
+ }
+
+ static SecurityContext getContext(final HttpServletRequest request) {
+ return (SecurityContext) request.getAttribute(ATTR_NAME);
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/src/main/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessors.java b/test/src/main/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessors.java
index ee13abffa4b..75498993cf6 100644
--- a/test/src/main/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessors.java
+++ b/test/src/main/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessors.java
@@ -48,9 +48,7 @@
import org.springframework.security.test.context.TestSecurityContextHolder;
import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers;
import org.springframework.security.test.web.support.WebTestUtils;
-import org.springframework.security.web.context.HttpRequestResponseHolder;
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
-import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
@@ -551,100 +549,6 @@ private static String md5Hex(String a2) {
}
}
- /**
- * Support class for {@link RequestPostProcessor}'s that establish a Spring Security
- * context
- */
- private static abstract class SecurityContextRequestPostProcessorSupport {
-
- /**
- * Saves the specified {@link Authentication} into an empty
- * {@link SecurityContext} using the {@link SecurityContextRepository}.
- *
- * @param authentication the {@link Authentication} to save
- * @param request the {@link HttpServletRequest} to use
- */
- final void save(Authentication authentication, HttpServletRequest request) {
- SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
- securityContext.setAuthentication(authentication);
- save(securityContext, request);
- }
-
- /**
- * Saves the {@link SecurityContext} using the {@link SecurityContextRepository}
- *
- * @param securityContext the {@link SecurityContext} to save
- * @param request the {@link HttpServletRequest} to use
- */
- final void save(SecurityContext securityContext, HttpServletRequest request) {
- SecurityContextRepository securityContextRepository = WebTestUtils
- .getSecurityContextRepository(request);
- boolean isTestRepository = securityContextRepository instanceof TestSecurityContextRepository;
- if (!isTestRepository) {
- securityContextRepository = new TestSecurityContextRepository(
- securityContextRepository);
- WebTestUtils.setSecurityContextRepository(request,
- securityContextRepository);
- }
-
- HttpServletResponse response = new MockHttpServletResponse();
-
- HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(
- request, response);
- securityContextRepository.loadContext(requestResponseHolder);
-
- request = requestResponseHolder.getRequest();
- response = requestResponseHolder.getResponse();
-
- securityContextRepository.saveContext(securityContext, request, response);
- }
-
- /**
- * Used to wrap the SecurityContextRepository to provide support for testing in
- * stateless mode
- */
- static class TestSecurityContextRepository implements SecurityContextRepository {
- private final static String ATTR_NAME = TestSecurityContextRepository.class
- .getName().concat(".REPO");
-
- private final SecurityContextRepository delegate;
-
- private TestSecurityContextRepository(SecurityContextRepository delegate) {
- this.delegate = delegate;
- }
-
- @Override
- public SecurityContext loadContext(
- HttpRequestResponseHolder requestResponseHolder) {
- SecurityContext result = getContext(requestResponseHolder.getRequest());
- // always load from the delegate to ensure the request/response in the
- // holder are updated
- // remember the SecurityContextRepository is used in many different
- // locations
- SecurityContext delegateResult = this.delegate
- .loadContext(requestResponseHolder);
- return result == null ? delegateResult : result;
- }
-
- @Override
- public void saveContext(SecurityContext context, HttpServletRequest request,
- HttpServletResponse response) {
- request.setAttribute(ATTR_NAME, context);
- this.delegate.saveContext(context, request, response);
- }
-
- @Override
- public boolean containsContext(HttpServletRequest request) {
- return getContext(request) != null
- || this.delegate.containsContext(request);
- }
-
- private static SecurityContext getContext(HttpServletRequest request) {
- return (SecurityContext) request.getAttribute(ATTR_NAME);
- }
- }
- }
-
/**
* Associates the {@link SecurityContext} found in
* {@link TestSecurityContextHolder#getContext()} with the