فهرست منبع

Make OAuth2AccessTokenResponse converters public

Nikita Konev 5 سال پیش
والد
کامیت
704f98688d

+ 84 - 0
oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2AccessTokenResponseConverter.java

@@ -0,0 +1,84 @@
+/*
+ * Copyright 2002-2020 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.oauth2.core.http.converter;
+
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.security.oauth2.core.OAuth2AccessToken;
+import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
+import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
+import org.springframework.util.StringUtils;
+
+import java.util.*;
+
+/**
+ * A {@link Converter} that converts the provided
+ * OAuth 2.0 Access Token Response parameters to an {@link OAuth2AccessTokenResponse}.
+ *
+ * @author Joe Grandja
+ * @author Nikita Konev
+ * @since 5.3
+ */
+public final class OAuth2AccessTokenResponseConverter implements Converter<Map<String, String>, OAuth2AccessTokenResponse> {
+	private static final Set<String> TOKEN_RESPONSE_PARAMETER_NAMES = new HashSet<>(Arrays.asList(
+			OAuth2ParameterNames.ACCESS_TOKEN,
+			OAuth2ParameterNames.EXPIRES_IN,
+			OAuth2ParameterNames.REFRESH_TOKEN,
+			OAuth2ParameterNames.SCOPE,
+			OAuth2ParameterNames.TOKEN_TYPE
+	));
+
+	@Override
+	public OAuth2AccessTokenResponse convert(Map<String, String> tokenResponseParameters) {
+		String accessToken = tokenResponseParameters.get(OAuth2ParameterNames.ACCESS_TOKEN);
+
+		OAuth2AccessToken.TokenType accessTokenType = null;
+		if (OAuth2AccessToken.TokenType.BEARER.getValue().equalsIgnoreCase(
+				tokenResponseParameters.get(OAuth2ParameterNames.TOKEN_TYPE))) {
+			accessTokenType = OAuth2AccessToken.TokenType.BEARER;
+		}
+
+		long expiresIn = 0;
+		if (tokenResponseParameters.containsKey(OAuth2ParameterNames.EXPIRES_IN)) {
+			try {
+				expiresIn = Long.parseLong(tokenResponseParameters.get(OAuth2ParameterNames.EXPIRES_IN));
+			} catch (NumberFormatException ex) {
+			}
+		}
+
+		Set<String> scopes = Collections.emptySet();
+		if (tokenResponseParameters.containsKey(OAuth2ParameterNames.SCOPE)) {
+			String scope = tokenResponseParameters.get(OAuth2ParameterNames.SCOPE);
+			scopes = new HashSet<>(Arrays.asList(StringUtils.delimitedListToStringArray(scope, " ")));
+		}
+
+		String refreshToken = tokenResponseParameters.get(OAuth2ParameterNames.REFRESH_TOKEN);
+
+		Map<String, Object> additionalParameters = new LinkedHashMap<>();
+		for (Map.Entry<String, String> entry : tokenResponseParameters.entrySet()) {
+			if (!TOKEN_RESPONSE_PARAMETER_NAMES.contains(entry.getKey())) {
+				additionalParameters.put(entry.getKey(), entry.getValue());
+			}
+		}
+
+		return OAuth2AccessTokenResponse.withToken(accessToken)
+				.tokenType(accessTokenType)
+				.expiresIn(expiresIn)
+				.scopes(scopes)
+				.refreshToken(refreshToken)
+				.additionalParameters(additionalParameters)
+				.build();
+	}
+}

+ 1 - 102
oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2AccessTokenResponseHttpMessageConverter.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -25,24 +25,12 @@ import org.springframework.http.converter.GenericHttpMessageConverter;
 import org.springframework.http.converter.HttpMessageConverter;
 import org.springframework.http.converter.HttpMessageNotReadableException;
 import org.springframework.http.converter.HttpMessageNotWritableException;
-import org.springframework.security.oauth2.core.OAuth2AccessToken;
 import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
-import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
 import org.springframework.util.Assert;
-import org.springframework.util.CollectionUtils;
-import org.springframework.util.StringUtils;
 
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
-import java.time.Instant;
-import java.time.temporal.ChronoUnit;
-import java.util.HashSet;
 import java.util.Map;
-import java.util.Set;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.HashMap;
 
 /**
  * A {@link HttpMessageConverter} for an {@link OAuth2AccessTokenResponse OAuth 2.0 Access Token Response}.
@@ -125,93 +113,4 @@ public class OAuth2AccessTokenResponseHttpMessageConverter extends AbstractHttpM
 		this.tokenResponseParametersConverter = tokenResponseParametersConverter;
 	}
 
-	/**
-	 * A {@link Converter} that converts the provided
-	 * OAuth 2.0 Access Token Response parameters to an {@link OAuth2AccessTokenResponse}.
-	 */
-	private static class OAuth2AccessTokenResponseConverter implements Converter<Map<String, String>, OAuth2AccessTokenResponse> {
-		private static final Set<String> TOKEN_RESPONSE_PARAMETER_NAMES = new HashSet<>(Arrays.asList(
-				OAuth2ParameterNames.ACCESS_TOKEN,
-				OAuth2ParameterNames.TOKEN_TYPE,
-				OAuth2ParameterNames.EXPIRES_IN,
-				OAuth2ParameterNames.REFRESH_TOKEN,
-				OAuth2ParameterNames.SCOPE
-		));
-
-		@Override
-		public OAuth2AccessTokenResponse convert(Map<String, String> tokenResponseParameters) {
-			String accessToken = tokenResponseParameters.get(OAuth2ParameterNames.ACCESS_TOKEN);
-
-			OAuth2AccessToken.TokenType accessTokenType = null;
-			if (OAuth2AccessToken.TokenType.BEARER.getValue().equalsIgnoreCase(
-					tokenResponseParameters.get(OAuth2ParameterNames.TOKEN_TYPE))) {
-				accessTokenType = OAuth2AccessToken.TokenType.BEARER;
-			}
-
-			long expiresIn = 0;
-			if (tokenResponseParameters.containsKey(OAuth2ParameterNames.EXPIRES_IN)) {
-				try {
-					expiresIn = Long.parseLong(tokenResponseParameters.get(OAuth2ParameterNames.EXPIRES_IN));
-				} catch (NumberFormatException ex) { }
-			}
-
-			Set<String> scopes = Collections.emptySet();
-			if (tokenResponseParameters.containsKey(OAuth2ParameterNames.SCOPE)) {
-				String scope = tokenResponseParameters.get(OAuth2ParameterNames.SCOPE);
-				scopes = new HashSet<>(Arrays.asList(StringUtils.delimitedListToStringArray(scope, " ")));
-			}
-
-			String refreshToken = tokenResponseParameters.get(OAuth2ParameterNames.REFRESH_TOKEN);
-
-			Map<String, Object> additionalParameters = new LinkedHashMap<>();
-			for (Map.Entry<String, String> entry : tokenResponseParameters.entrySet()) {
-				if (!TOKEN_RESPONSE_PARAMETER_NAMES.contains(entry.getKey())) {
-					additionalParameters.put(entry.getKey(), entry.getValue());
-				}
-			}
-
-			return OAuth2AccessTokenResponse.withToken(accessToken)
-					.tokenType(accessTokenType)
-					.expiresIn(expiresIn)
-					.scopes(scopes)
-					.refreshToken(refreshToken)
-					.additionalParameters(additionalParameters)
-					.build();
-		}
-	}
-
-	/**
-	 * A {@link Converter} that converts the provided {@link OAuth2AccessTokenResponse}
-	 * to a {@code Map} representation of the OAuth 2.0 Access Token Response parameters.
-	 */
-	private static class OAuth2AccessTokenResponseParametersConverter implements Converter<OAuth2AccessTokenResponse, Map<String, String>> {
-
-		@Override
-		public Map<String, String> convert(OAuth2AccessTokenResponse tokenResponse) {
-			Map<String, String> parameters = new HashMap<>();
-
-			long expiresIn = -1;
-			if (tokenResponse.getAccessToken().getExpiresAt() != null) {
-				expiresIn = ChronoUnit.SECONDS.between(Instant.now(), tokenResponse.getAccessToken().getExpiresAt());
-			}
-
-			parameters.put(OAuth2ParameterNames.ACCESS_TOKEN, tokenResponse.getAccessToken().getTokenValue());
-			parameters.put(OAuth2ParameterNames.TOKEN_TYPE, tokenResponse.getAccessToken().getTokenType().getValue());
-			parameters.put(OAuth2ParameterNames.EXPIRES_IN, String.valueOf(expiresIn));
-			if (!CollectionUtils.isEmpty(tokenResponse.getAccessToken().getScopes())) {
-				parameters.put(OAuth2ParameterNames.SCOPE,
-						StringUtils.collectionToDelimitedString(tokenResponse.getAccessToken().getScopes(), " "));
-			}
-			if (tokenResponse.getRefreshToken() != null) {
-				parameters.put(OAuth2ParameterNames.REFRESH_TOKEN, tokenResponse.getRefreshToken().getTokenValue());
-			}
-			if (!CollectionUtils.isEmpty(tokenResponse.getAdditionalParameters())) {
-				for (Map.Entry<String, Object> entry : tokenResponse.getAdditionalParameters().entrySet()) {
-					parameters.put(entry.getKey(), entry.getValue().toString());
-				}
-			}
-
-			return parameters;
-		}
-	}
 }

+ 66 - 0
oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2AccessTokenResponseParametersConverter.java

@@ -0,0 +1,66 @@
+/*
+ * Copyright 2002-2020 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.oauth2.core.http.converter;
+
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
+import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A {@link Converter} that converts the provided {@link OAuth2AccessTokenResponse}
+ * to a {@code Map} representation of the OAuth 2.0 Access Token Response parameters.
+ *
+ * @author Joe Grandja
+ * @author Nikita Konev
+ * @since 5.3
+ */
+public final class OAuth2AccessTokenResponseParametersConverter implements Converter<OAuth2AccessTokenResponse, Map<String, String>> {
+
+	@Override
+	public Map<String, String> convert(OAuth2AccessTokenResponse tokenResponse) {
+		Map<String, String> parameters = new HashMap<>();
+
+		long expiresIn = -1;
+		if (tokenResponse.getAccessToken().getExpiresAt() != null) {
+			expiresIn = ChronoUnit.SECONDS.between(Instant.now(), tokenResponse.getAccessToken().getExpiresAt());
+		}
+
+		parameters.put(OAuth2ParameterNames.ACCESS_TOKEN, tokenResponse.getAccessToken().getTokenValue());
+		parameters.put(OAuth2ParameterNames.TOKEN_TYPE, tokenResponse.getAccessToken().getTokenType().getValue());
+		parameters.put(OAuth2ParameterNames.EXPIRES_IN, String.valueOf(expiresIn));
+		if (!CollectionUtils.isEmpty(tokenResponse.getAccessToken().getScopes())) {
+			parameters.put(OAuth2ParameterNames.SCOPE,
+					StringUtils.collectionToDelimitedString(tokenResponse.getAccessToken().getScopes(), " "));
+		}
+		if (tokenResponse.getRefreshToken() != null) {
+			parameters.put(OAuth2ParameterNames.REFRESH_TOKEN, tokenResponse.getRefreshToken().getTokenValue());
+		}
+		if (!CollectionUtils.isEmpty(tokenResponse.getAdditionalParameters())) {
+			for (Map.Entry<String, Object> entry : tokenResponse.getAdditionalParameters().entrySet()) {
+				parameters.put(entry.getKey(), entry.getValue().toString());
+			}
+		}
+
+		return parameters;
+	}
+}

+ 126 - 0
oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/http/converter/OAuth2AccessTokenResponseConverterTest.java

@@ -0,0 +1,126 @@
+/*
+ * Copyright 2002-2020 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.oauth2.core.http.converter;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.security.oauth2.core.OAuth2AccessToken;
+import org.springframework.security.oauth2.core.OAuth2RefreshToken;
+import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
+
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Tests for {@link OAuth2AccessTokenResponseConverter}.
+ *
+ * @author Nikita Konev
+ */
+public class OAuth2AccessTokenResponseConverterTest {
+
+	private OAuth2AccessTokenResponseConverter messageConverter;
+
+	@Before
+	public void setup() {
+		this.messageConverter = new OAuth2AccessTokenResponseConverter();
+	}
+
+
+	@Test
+	public void shouldConvertFull() {
+		Map<String, String> map = new HashMap<>();
+		map.put("access_token", "access-token-1234");
+		map.put("token_type", "bearer");
+		map.put("expires_in", "3600");
+		map.put("scope", "read write");
+		map.put("refresh_token", "refresh-token-1234");
+		map.put("custom_parameter_1", "custom-value-1");
+		map.put("custom_parameter_2", "custom-value-2");
+		OAuth2AccessTokenResponse converted = messageConverter.convert(map);
+		OAuth2AccessToken accessToken = converted.getAccessToken();
+		Assert.assertNotNull(accessToken);
+		Assert.assertEquals("access-token-1234", accessToken.getTokenValue());
+		Assert.assertEquals(OAuth2AccessToken.TokenType.BEARER, accessToken.getTokenType());
+		Set<String> scopes = accessToken.getScopes();
+		Assert.assertNotNull(scopes);
+		Assert.assertEquals(2, scopes.size());
+		Assert.assertTrue(scopes.contains("read"));
+		Assert.assertTrue(scopes.contains("write"));
+		Assert.assertEquals(3600, Duration.between(accessToken.getIssuedAt(), accessToken.getExpiresAt()).getSeconds());
+
+		OAuth2RefreshToken refreshToken = converted.getRefreshToken();
+		Assert.assertNotNull(refreshToken);
+		Assert.assertEquals("refresh-token-1234", refreshToken.getTokenValue());
+
+		Map<String, Object> additionalParameters = converted.getAdditionalParameters();
+		Assert.assertNotNull(additionalParameters);
+		Assert.assertEquals(2, additionalParameters.size());
+		Assert.assertEquals("custom-value-1", additionalParameters.get("custom_parameter_1"));
+		Assert.assertEquals("custom-value-2", additionalParameters.get("custom_parameter_2"));
+	}
+
+	@Test
+	public void shouldConvertMinimal() {
+		Map<String, String> map = new HashMap<>();
+		map.put("access_token", "access-token-1234");
+		map.put("token_type", "bearer");
+		OAuth2AccessTokenResponse converted = messageConverter.convert(map);
+		OAuth2AccessToken accessToken = converted.getAccessToken();
+		Assert.assertNotNull(accessToken);
+		Assert.assertEquals("access-token-1234", accessToken.getTokenValue());
+		Assert.assertEquals(OAuth2AccessToken.TokenType.BEARER, accessToken.getTokenType());
+		Set<String> scopes = accessToken.getScopes();
+		Assert.assertNotNull(scopes);
+		Assert.assertEquals(0, scopes.size());
+
+		Assert.assertEquals(1, Duration.between(accessToken.getIssuedAt(), accessToken.getExpiresAt()).getSeconds());
+
+		OAuth2RefreshToken refreshToken = converted.getRefreshToken();
+		Assert.assertNull(refreshToken);
+
+		Map<String, Object> additionalParameters = converted.getAdditionalParameters();
+		Assert.assertNotNull(additionalParameters);
+		Assert.assertEquals(0, additionalParameters.size());
+	}
+
+	@Test
+	public void shouldConvertWithUnsupportedExpiresIn() {
+		Map<String, String> map = new HashMap<>();
+		map.put("access_token", "access-token-1234");
+		map.put("token_type", "bearer");
+		map.put("expires_in", "2100-01-01-abc");
+		OAuth2AccessTokenResponse converted = messageConverter.convert(map);
+		OAuth2AccessToken accessToken = converted.getAccessToken();
+		Assert.assertNotNull(accessToken);
+		Assert.assertEquals("access-token-1234", accessToken.getTokenValue());
+		Assert.assertEquals(OAuth2AccessToken.TokenType.BEARER, accessToken.getTokenType());
+		Set<String> scopes = accessToken.getScopes();
+		Assert.assertNotNull(scopes);
+		Assert.assertEquals(0, scopes.size());
+
+		Assert.assertEquals(1, Duration.between(accessToken.getIssuedAt(), accessToken.getExpiresAt()).getSeconds());
+
+		OAuth2RefreshToken refreshToken = converted.getRefreshToken();
+		Assert.assertNull(refreshToken);
+
+		Map<String, Object> additionalParameters = converted.getAdditionalParameters();
+		Assert.assertNotNull(additionalParameters);
+		Assert.assertEquals(0, additionalParameters.size());
+	}
+}

+ 89 - 0
oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/http/converter/OAuth2AccessTokenResponseParametersConverterTest.java

@@ -0,0 +1,89 @@
+/*
+ * Copyright 2002-2020 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.oauth2.core.http.converter;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.security.oauth2.core.OAuth2AccessToken;
+import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests for {@link OAuth2AccessTokenResponseParametersConverter}.
+ *
+ * @author Nikita Konev
+ */
+public class OAuth2AccessTokenResponseParametersConverterTest {
+
+	private OAuth2AccessTokenResponseParametersConverter messageConverter;
+
+	@Before
+	public void setup() {
+		this.messageConverter = new OAuth2AccessTokenResponseParametersConverter();
+	}
+
+
+	@Test
+	public void convertFull() {
+		Map<String, Object> additionalParameters = new HashMap<>();
+		additionalParameters.put("custom_parameter_1", "custom-value-1");
+		additionalParameters.put("custom_parameter_2", "custom-value-2");
+
+		Set<String> scopes = new HashSet<>();
+		scopes.add("read");
+		scopes.add("write");
+
+		OAuth2AccessTokenResponse build = OAuth2AccessTokenResponse
+				.withToken("access-token-value-1234")
+				.expiresIn(3699)
+				.additionalParameters(additionalParameters)
+				.refreshToken("refresh-token-value-1234")
+				.scopes(scopes)
+				.tokenType(OAuth2AccessToken.TokenType.BEARER)
+				.build();
+		Map<String, String> result = messageConverter.convert(build);
+		Assert.assertEquals(7, result.size());
+
+		Assert.assertEquals("access-token-value-1234", result.get("access_token"));
+		Assert.assertEquals("refresh-token-value-1234", result.get("refresh_token"));
+		Assert.assertEquals("read write", result.get("scope"));
+		Assert.assertEquals("Bearer", result.get("token_type"));
+		Assert.assertNotNull(result.get("expires_in"));
+		Assert.assertEquals("custom-value-1", result.get("custom_parameter_1"));
+		Assert.assertEquals("custom-value-2", result.get("custom_parameter_2"));
+	}
+
+	@Test
+	public void convertMinimal() {
+		OAuth2AccessTokenResponse build = OAuth2AccessTokenResponse
+				.withToken("access-token-value-1234")
+				.tokenType(OAuth2AccessToken.TokenType.BEARER)
+				.build();
+		Map<String, String> result = messageConverter.convert(build);
+		Assert.assertEquals(3, result.size());
+
+		Assert.assertEquals("access-token-value-1234", result.get("access_token"));
+		Assert.assertEquals("Bearer", result.get("token_type"));
+		Assert.assertNotNull(result.get("expires_in"));
+	}
+}