Add Jackson support for oauth2-client session related classes
Fixes gh-4886
This commit is contained in:
parent
ca5cc13948
commit
04f3fe8af9
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2015-2019 the original author or authors.
|
||||
* Copyright 2015-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.
|
||||
|
@ -61,6 +61,7 @@ import java.util.Set;
|
|||
* mapper.registerModule(new WebJackson2Module());
|
||||
* mapper.registerModule(new WebServletJackson2Module());
|
||||
* mapper.registerModule(new WebServerJackson2Module());
|
||||
* mapper.registerModule(new OAuth2ClientJackson2Module());
|
||||
* </pre>
|
||||
*
|
||||
* @author Jitendra Singh.
|
||||
|
@ -77,6 +78,10 @@ public final class SecurityJackson2Modules {
|
|||
);
|
||||
private static final String webServletJackson2ModuleClass =
|
||||
"org.springframework.security.web.jackson2.WebServletJackson2Module";
|
||||
private static final String oauth2ClientJackson2ModuleClass =
|
||||
"org.springframework.security.oauth2.client.jackson2.OAuth2ClientJackson2Module";
|
||||
private static final String javaTimeJackson2ModuleClass =
|
||||
"com.fasterxml.jackson.datatype.jsr310.JavaTimeModule";
|
||||
|
||||
private SecurityJackson2Modules() {
|
||||
}
|
||||
|
@ -121,6 +126,12 @@ public final class SecurityJackson2Modules {
|
|||
if (ClassUtils.isPresent("javax.servlet.http.Cookie", loader)) {
|
||||
addToModulesList(loader, modules, webServletJackson2ModuleClass);
|
||||
}
|
||||
if (ClassUtils.isPresent("org.springframework.security.oauth2.client.OAuth2AuthorizedClient", loader)) {
|
||||
addToModulesList(loader, modules, oauth2ClientJackson2ModuleClass);
|
||||
}
|
||||
if (ClassUtils.isPresent(javaTimeJackson2ModuleClass, loader)) {
|
||||
addToModulesList(loader, modules, javaTimeJackson2ModuleClass);
|
||||
}
|
||||
return modules;
|
||||
}
|
||||
|
||||
|
@ -188,8 +199,11 @@ public final class SecurityJackson2Modules {
|
|||
"java.util.Collections$UnmodifiableRandomAccessList",
|
||||
"java.util.Collections$SingletonList",
|
||||
"java.util.Date",
|
||||
"java.time.Instant",
|
||||
"java.net.URL",
|
||||
"java.util.TreeMap",
|
||||
"java.util.HashMap",
|
||||
"java.util.LinkedHashMap",
|
||||
"org.springframework.security.core.context.SecurityContextImpl"
|
||||
)));
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ dependencies {
|
|||
constraints {
|
||||
management "ch.qos.logback:logback-classic:1.+"
|
||||
management "com.fasterxml.jackson.core:jackson-databind:2.+"
|
||||
management 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.+'
|
||||
management "com.google.appengine:appengine-api-1.0-sdk:$gaeVersion"
|
||||
management "com.google.appengine:appengine-api-labs:$gaeVersion"
|
||||
management "com.google.appengine:appengine-api-stubs:$gaeVersion"
|
||||
|
|
|
@ -10,15 +10,17 @@ dependencies {
|
|||
optional project(':spring-security-oauth2-jose')
|
||||
optional 'io.projectreactor:reactor-core'
|
||||
optional 'org.springframework:spring-webflux'
|
||||
optional 'com.fasterxml.jackson.core:jackson-databind'
|
||||
optional 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'
|
||||
|
||||
testCompile project(path: ':spring-security-oauth2-core', configuration: 'tests')
|
||||
testCompile project(path: ':spring-security-oauth2-jose', configuration: 'tests')
|
||||
testCompile powerMock2Dependencies
|
||||
testCompile 'com.squareup.okhttp3:mockwebserver'
|
||||
testCompile 'com.fasterxml.jackson.core:jackson-databind'
|
||||
testCompile 'io.projectreactor.netty:reactor-netty'
|
||||
testCompile 'io.projectreactor:reactor-test'
|
||||
testCompile 'io.projectreactor.tools:blockhound'
|
||||
testCompile 'org.skyscreamer:jsonassert'
|
||||
|
||||
provided 'javax.servlet:javax.servlet-api'
|
||||
}
|
||||
|
|
|
@ -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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.util.StdConverter;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.core.AuthenticationMethod;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.springframework.security.oauth2.client.jackson2.JsonNodeUtils.MAP_TYPE_REFERENCE;
|
||||
import static org.springframework.security.oauth2.client.jackson2.JsonNodeUtils.SET_TYPE_REFERENCE;
|
||||
import static org.springframework.security.oauth2.client.jackson2.JsonNodeUtils.findObjectNode;
|
||||
import static org.springframework.security.oauth2.client.jackson2.JsonNodeUtils.findStringValue;
|
||||
import static org.springframework.security.oauth2.client.jackson2.JsonNodeUtils.findValue;
|
||||
|
||||
/**
|
||||
* A {@code JsonDeserializer} for {@link ClientRegistration}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.3
|
||||
* @see ClientRegistration
|
||||
* @see ClientRegistrationMixin
|
||||
*/
|
||||
final class ClientRegistrationDeserializer extends JsonDeserializer<ClientRegistration> {
|
||||
private static final StdConverter<JsonNode, ClientAuthenticationMethod> CLIENT_AUTHENTICATION_METHOD_CONVERTER =
|
||||
new StdConverters.ClientAuthenticationMethodConverter();
|
||||
private static final StdConverter<JsonNode, AuthorizationGrantType> AUTHORIZATION_GRANT_TYPE_CONVERTER =
|
||||
new StdConverters.AuthorizationGrantTypeConverter();
|
||||
private static final StdConverter<JsonNode, AuthenticationMethod> AUTHENTICATION_METHOD_CONVERTER =
|
||||
new StdConverters.AuthenticationMethodConverter();
|
||||
|
||||
@Override
|
||||
public ClientRegistration deserialize(JsonParser parser, DeserializationContext context) throws IOException {
|
||||
ObjectMapper mapper = (ObjectMapper) parser.getCodec();
|
||||
JsonNode clientRegistrationNode = mapper.readTree(parser);
|
||||
JsonNode providerDetailsNode = findObjectNode(clientRegistrationNode, "providerDetails");
|
||||
JsonNode userInfoEndpointNode = findObjectNode(providerDetailsNode, "userInfoEndpoint");
|
||||
|
||||
return ClientRegistration
|
||||
.withRegistrationId(findStringValue(clientRegistrationNode, "registrationId"))
|
||||
.clientId(findStringValue(clientRegistrationNode, "clientId"))
|
||||
.clientSecret(findStringValue(clientRegistrationNode, "clientSecret"))
|
||||
.clientAuthenticationMethod(
|
||||
CLIENT_AUTHENTICATION_METHOD_CONVERTER.convert(
|
||||
findObjectNode(clientRegistrationNode, "clientAuthenticationMethod")))
|
||||
.authorizationGrantType(
|
||||
AUTHORIZATION_GRANT_TYPE_CONVERTER.convert(
|
||||
findObjectNode(clientRegistrationNode, "authorizationGrantType")))
|
||||
.redirectUriTemplate(findStringValue(clientRegistrationNode, "redirectUriTemplate"))
|
||||
.scope(findValue(clientRegistrationNode, "scopes", SET_TYPE_REFERENCE, mapper))
|
||||
.clientName(findStringValue(clientRegistrationNode, "clientName"))
|
||||
.authorizationUri(findStringValue(providerDetailsNode, "authorizationUri"))
|
||||
.tokenUri(findStringValue(providerDetailsNode, "tokenUri"))
|
||||
.userInfoUri(findStringValue(userInfoEndpointNode, "uri"))
|
||||
.userInfoAuthenticationMethod(
|
||||
AUTHENTICATION_METHOD_CONVERTER.convert(
|
||||
findObjectNode(userInfoEndpointNode, "authenticationMethod")))
|
||||
.userNameAttributeName(findStringValue(userInfoEndpointNode, "userNameAttributeName"))
|
||||
.jwkSetUri(findStringValue(providerDetailsNode, "jwkSetUri"))
|
||||
.providerConfigurationMetadata(findValue(providerDetailsNode, "configurationMetadata", MAP_TYPE_REFERENCE, mapper))
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
|
||||
/**
|
||||
* This mixin class is used to serialize/deserialize {@link ClientRegistration}.
|
||||
* It also registers a custom deserializer {@link ClientRegistrationDeserializer}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.3
|
||||
* @see ClientRegistration
|
||||
* @see ClientRegistrationDeserializer
|
||||
* @see OAuth2ClientJackson2Module
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonDeserialize(using = ClientRegistrationDeserializer.class)
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
||||
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
abstract class ClientRegistrationMixin {
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This mixin class is used to serialize/deserialize {@link DefaultOAuth2User}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.3
|
||||
* @see DefaultOAuth2User
|
||||
* @see OAuth2ClientJackson2Module
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
||||
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
abstract class DefaultOAuth2UserMixin {
|
||||
|
||||
@JsonCreator
|
||||
DefaultOAuth2UserMixin(
|
||||
@JsonProperty("authorities") Collection<? extends GrantedAuthority> authorities,
|
||||
@JsonProperty("attributes") Map<String, Object> attributes,
|
||||
@JsonProperty("nameAttributeKey") String nameAttributeKey) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
|
||||
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* This mixin class is used to serialize/deserialize {@link DefaultOidcUser}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.3
|
||||
* @see DefaultOidcUser
|
||||
* @see OAuth2ClientJackson2Module
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
||||
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
@JsonIgnoreProperties(value = {"attributes"}, ignoreUnknown = true)
|
||||
abstract class DefaultOidcUserMixin {
|
||||
|
||||
@JsonCreator
|
||||
DefaultOidcUserMixin(
|
||||
@JsonProperty("authorities") Collection<? extends GrantedAuthority> authorities,
|
||||
@JsonProperty("idToken") OidcIdToken idToken,
|
||||
@JsonProperty("userInfo") OidcUserInfo userInfo,
|
||||
@JsonProperty("nameAttributeKey") String nameAttributeKey) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Utility class for {@code JsonNode}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.3
|
||||
*/
|
||||
abstract class JsonNodeUtils {
|
||||
static final TypeReference<Set<String>> SET_TYPE_REFERENCE = new TypeReference<Set<String>>() {};
|
||||
static final TypeReference<Map<String, Object>> MAP_TYPE_REFERENCE = new TypeReference<Map<String, Object>>() {};
|
||||
|
||||
|
||||
static String findStringValue(JsonNode jsonNode, String fieldName) {
|
||||
if (jsonNode == null) {
|
||||
return null;
|
||||
}
|
||||
JsonNode nodeValue = jsonNode.findValue(fieldName);
|
||||
if (nodeValue != null && nodeValue.isTextual()) {
|
||||
return nodeValue.asText();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static <T> T findValue(JsonNode jsonNode, String fieldName, TypeReference<T> valueTypeReference, ObjectMapper mapper) {
|
||||
if (jsonNode == null) {
|
||||
return null;
|
||||
}
|
||||
JsonNode nodeValue = jsonNode.findValue(fieldName);
|
||||
if (nodeValue != null && nodeValue.isContainerNode()) {
|
||||
return (T) mapper.convertValue(nodeValue, valueTypeReference);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static JsonNode findObjectNode(JsonNode jsonNode, String fieldName) {
|
||||
if (jsonNode == null) {
|
||||
return null;
|
||||
}
|
||||
JsonNode nodeValue = jsonNode.findValue(fieldName);
|
||||
if (nodeValue != null && nodeValue.isObject()) {
|
||||
return nodeValue;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.util.StdDateFormat;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This mixin class is used to serialize/deserialize {@link OAuth2AccessToken}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.3
|
||||
* @see OAuth2AccessToken
|
||||
* @see OAuth2ClientJackson2Module
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
||||
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
abstract class OAuth2AccessTokenMixin {
|
||||
|
||||
@JsonCreator
|
||||
OAuth2AccessTokenMixin(
|
||||
@JsonProperty("tokenType") @JsonDeserialize(converter = StdConverters.AccessTokenTypeConverter.class) OAuth2AccessToken.TokenType tokenType,
|
||||
@JsonProperty("tokenValue") String tokenValue,
|
||||
@JsonProperty("issuedAt") @JsonFormat(pattern = StdDateFormat.DATE_FORMAT_STR_ISO8601, timezone = "UTC") Instant issuedAt,
|
||||
@JsonProperty("expiresAt") @JsonFormat(pattern = StdDateFormat.DATE_FORMAT_STR_ISO8601, timezone = "UTC") Instant expiresAt,
|
||||
@JsonProperty("scopes") Set<String> scopes) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* This mixin class is used to serialize/deserialize {@link OAuth2AuthenticationToken}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.3
|
||||
* @see OAuth2AuthenticationToken
|
||||
* @see OAuth2ClientJackson2Module
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
||||
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
@JsonIgnoreProperties(value = {"authenticated"}, ignoreUnknown = true)
|
||||
abstract class OAuth2AuthenticationTokenMixin {
|
||||
|
||||
@JsonCreator
|
||||
OAuth2AuthenticationTokenMixin(
|
||||
@JsonProperty("principal") OAuth2User principal,
|
||||
@JsonProperty("authorities") Collection<? extends GrantedAuthority> authorities,
|
||||
@JsonProperty("authorizedClientRegistrationId") String authorizedClientRegistrationId) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.util.StdConverter;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.springframework.security.oauth2.client.jackson2.JsonNodeUtils.MAP_TYPE_REFERENCE;
|
||||
import static org.springframework.security.oauth2.client.jackson2.JsonNodeUtils.SET_TYPE_REFERENCE;
|
||||
import static org.springframework.security.oauth2.client.jackson2.JsonNodeUtils.findObjectNode;
|
||||
import static org.springframework.security.oauth2.client.jackson2.JsonNodeUtils.findStringValue;
|
||||
import static org.springframework.security.oauth2.client.jackson2.JsonNodeUtils.findValue;
|
||||
|
||||
/**
|
||||
* A {@code JsonDeserializer} for {@link OAuth2AuthorizationRequest}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.3
|
||||
* @see OAuth2AuthorizationRequest
|
||||
* @see OAuth2AuthorizationRequestMixin
|
||||
*/
|
||||
final class OAuth2AuthorizationRequestDeserializer extends JsonDeserializer<OAuth2AuthorizationRequest> {
|
||||
private static final StdConverter<JsonNode, AuthorizationGrantType> AUTHORIZATION_GRANT_TYPE_CONVERTER =
|
||||
new StdConverters.AuthorizationGrantTypeConverter();
|
||||
|
||||
@Override
|
||||
public OAuth2AuthorizationRequest deserialize(JsonParser parser, DeserializationContext context) throws IOException {
|
||||
ObjectMapper mapper = (ObjectMapper) parser.getCodec();
|
||||
JsonNode authorizationRequestNode = mapper.readTree(parser);
|
||||
|
||||
AuthorizationGrantType authorizationGrantType = AUTHORIZATION_GRANT_TYPE_CONVERTER.convert(
|
||||
findObjectNode(authorizationRequestNode, "authorizationGrantType"));
|
||||
|
||||
OAuth2AuthorizationRequest.Builder builder;
|
||||
if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(authorizationGrantType)) {
|
||||
builder = OAuth2AuthorizationRequest.authorizationCode();
|
||||
} else if (AuthorizationGrantType.IMPLICIT.equals(authorizationGrantType)) {
|
||||
builder = OAuth2AuthorizationRequest.implicit();
|
||||
} else {
|
||||
throw new JsonParseException(parser, "Invalid authorizationGrantType");
|
||||
}
|
||||
|
||||
return builder
|
||||
.authorizationUri(findStringValue(authorizationRequestNode, "authorizationUri"))
|
||||
.clientId(findStringValue(authorizationRequestNode, "clientId"))
|
||||
.redirectUri(findStringValue(authorizationRequestNode, "redirectUri"))
|
||||
.scopes(findValue(authorizationRequestNode, "scopes", SET_TYPE_REFERENCE, mapper))
|
||||
.state(findStringValue(authorizationRequestNode, "state"))
|
||||
.additionalParameters(findValue(authorizationRequestNode, "additionalParameters", MAP_TYPE_REFERENCE, mapper))
|
||||
.authorizationRequestUri(findStringValue(authorizationRequestNode, "authorizationRequestUri"))
|
||||
.attributes(findValue(authorizationRequestNode, "attributes", MAP_TYPE_REFERENCE, mapper))
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||
|
||||
/**
|
||||
* This mixin class is used to serialize/deserialize {@link OAuth2AuthorizationRequest}.
|
||||
* It also registers a custom deserializer {@link OAuth2AuthorizationRequestDeserializer}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.3
|
||||
* @see OAuth2AuthorizationRequest
|
||||
* @see OAuth2AuthorizationRequestDeserializer
|
||||
* @see OAuth2ClientJackson2Module
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonDeserialize(using = OAuth2AuthorizationRequestDeserializer.class)
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
||||
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
abstract class OAuth2AuthorizationRequestMixin {
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
|
||||
|
||||
/**
|
||||
* This mixin class is used to serialize/deserialize {@link OAuth2AuthorizedClient}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.3
|
||||
* @see OAuth2AuthorizedClient
|
||||
* @see OAuth2ClientJackson2Module
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
||||
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
abstract class OAuth2AuthorizedClientMixin {
|
||||
|
||||
@JsonCreator
|
||||
OAuth2AuthorizedClientMixin(
|
||||
@JsonProperty("clientRegistration") ClientRegistration clientRegistration,
|
||||
@JsonProperty("principalName") String principalName,
|
||||
@JsonProperty("accessToken") OAuth2AccessToken accessToken,
|
||||
@JsonProperty("refreshToken") OAuth2RefreshToken refreshToken) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.core.Version;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import org.springframework.security.jackson2.SecurityJackson2Modules;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
|
||||
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
|
||||
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Jackson {@code Module} for {@code spring-security-oauth2-client},
|
||||
* that registers the following mix-in annotations:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link OAuth2AuthorizationRequestMixin}</li>
|
||||
* <li>{@link ClientRegistrationMixin}</li>
|
||||
* <li>{@link OAuth2AccessTokenMixin}</li>
|
||||
* <li>{@link OAuth2RefreshTokenMixin}</li>
|
||||
* <li>{@link OAuth2AuthorizedClientMixin}</li>
|
||||
* <li>{@link OAuth2UserAuthorityMixin}</li>
|
||||
* <li>{@link DefaultOAuth2UserMixin}</li>
|
||||
* <li>{@link OidcIdTokenMixin}</li>
|
||||
* <li>{@link OidcUserInfoMixin}</li>
|
||||
* <li>{@link OidcUserAuthorityMixin}</li>
|
||||
* <li>{@link DefaultOidcUserMixin}</li>
|
||||
* <li>{@link OAuth2AuthenticationTokenMixin}</li>
|
||||
* </ul>
|
||||
*
|
||||
* If not already enabled, default typing will be automatically enabled
|
||||
* as type info is required to properly serialize/deserialize objects.
|
||||
* In order to use this module just add it to your {@code ObjectMapper} configuration.
|
||||
*
|
||||
* <pre>
|
||||
* ObjectMapper mapper = new ObjectMapper();
|
||||
* mapper.registerModule(new OAuth2ClientJackson2Module());
|
||||
* </pre>
|
||||
*
|
||||
* <b>NOTE:</b> Use {@link SecurityJackson2Modules#getModules(ClassLoader)} to get a list of all security modules.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.3
|
||||
* @see SecurityJackson2Modules
|
||||
* @see OAuth2AuthorizationRequestMixin
|
||||
* @see ClientRegistrationMixin
|
||||
* @see OAuth2AccessTokenMixin
|
||||
* @see OAuth2RefreshTokenMixin
|
||||
* @see OAuth2AuthorizedClientMixin
|
||||
* @see OAuth2UserAuthorityMixin
|
||||
* @see DefaultOAuth2UserMixin
|
||||
* @see OidcIdTokenMixin
|
||||
* @see OidcUserInfoMixin
|
||||
* @see OidcUserAuthorityMixin
|
||||
* @see DefaultOidcUserMixin
|
||||
* @see OAuth2AuthenticationTokenMixin
|
||||
*/
|
||||
public class OAuth2ClientJackson2Module extends SimpleModule {
|
||||
|
||||
public OAuth2ClientJackson2Module() {
|
||||
super(OAuth2ClientJackson2Module.class.getName(), new Version(1, 0, 0, null, null, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupModule(SetupContext context) {
|
||||
SecurityJackson2Modules.enableDefaultTyping(context.getOwner());
|
||||
context.setMixInAnnotations(Collections.unmodifiableMap(Collections.emptyMap()).getClass(), UnmodifiableMapMixin.class);
|
||||
context.setMixInAnnotations(OAuth2AuthorizationRequest.class, OAuth2AuthorizationRequestMixin.class);
|
||||
context.setMixInAnnotations(ClientRegistration.class, ClientRegistrationMixin.class);
|
||||
context.setMixInAnnotations(OAuth2AccessToken.class, OAuth2AccessTokenMixin.class);
|
||||
context.setMixInAnnotations(OAuth2RefreshToken.class, OAuth2RefreshTokenMixin.class);
|
||||
context.setMixInAnnotations(OAuth2AuthorizedClient.class, OAuth2AuthorizedClientMixin.class);
|
||||
context.setMixInAnnotations(OAuth2UserAuthority.class, OAuth2UserAuthorityMixin.class);
|
||||
context.setMixInAnnotations(DefaultOAuth2User.class, DefaultOAuth2UserMixin.class);
|
||||
context.setMixInAnnotations(OidcIdToken.class, OidcIdTokenMixin.class);
|
||||
context.setMixInAnnotations(OidcUserInfo.class, OidcUserInfoMixin.class);
|
||||
context.setMixInAnnotations(OidcUserAuthority.class, OidcUserAuthorityMixin.class);
|
||||
context.setMixInAnnotations(DefaultOidcUser.class, DefaultOidcUserMixin.class);
|
||||
context.setMixInAnnotations(OAuth2AuthenticationToken.class, OAuth2AuthenticationTokenMixin.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.databind.util.StdDateFormat;
|
||||
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
* This mixin class is used to serialize/deserialize {@link OAuth2RefreshToken}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.3
|
||||
* @see OAuth2RefreshToken
|
||||
* @see OAuth2ClientJackson2Module
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
||||
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
abstract class OAuth2RefreshTokenMixin {
|
||||
|
||||
@JsonCreator
|
||||
OAuth2RefreshTokenMixin(
|
||||
@JsonProperty("tokenValue") String tokenValue,
|
||||
@JsonProperty("issuedAt") @JsonFormat(pattern = StdDateFormat.DATE_FORMAT_STR_ISO8601, timezone = "UTC") Instant issuedAt) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This mixin class is used to serialize/deserialize {@link OAuth2UserAuthority}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.3
|
||||
* @see OAuth2UserAuthority
|
||||
* @see OAuth2ClientJackson2Module
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
||||
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
abstract class OAuth2UserAuthorityMixin {
|
||||
|
||||
@JsonCreator
|
||||
OAuth2UserAuthorityMixin(
|
||||
@JsonProperty("authority") String authority,
|
||||
@JsonProperty("attributes") Map<String, Object> attributes) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.databind.util.StdDateFormat;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This mixin class is used to serialize/deserialize {@link OidcIdToken}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.3
|
||||
* @see OidcIdToken
|
||||
* @see OAuth2ClientJackson2Module
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
||||
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
abstract class OidcIdTokenMixin {
|
||||
|
||||
@JsonCreator
|
||||
OidcIdTokenMixin(
|
||||
@JsonProperty("tokenValue") String tokenValue,
|
||||
@JsonProperty("issuedAt") @JsonFormat(pattern = StdDateFormat.DATE_FORMAT_STR_ISO8601, timezone = "UTC") Instant issuedAt,
|
||||
@JsonProperty("expiresAt") @JsonFormat(pattern = StdDateFormat.DATE_FORMAT_STR_ISO8601, timezone = "UTC") Instant expiresAt,
|
||||
@JsonProperty("claims") Map<String, Object> claims) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
|
||||
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
|
||||
|
||||
/**
|
||||
* This mixin class is used to serialize/deserialize {@link OidcUserAuthority}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.3
|
||||
* @see OidcUserAuthority
|
||||
* @see OAuth2ClientJackson2Module
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
||||
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
@JsonIgnoreProperties(value = {"attributes"}, ignoreUnknown = true)
|
||||
abstract class OidcUserAuthorityMixin {
|
||||
|
||||
@JsonCreator
|
||||
OidcUserAuthorityMixin(
|
||||
@JsonProperty("authority") String authority,
|
||||
@JsonProperty("idToken") OidcIdToken idToken,
|
||||
@JsonProperty("userInfo") OidcUserInfo userInfo) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This mixin class is used to serialize/deserialize {@link OidcUserInfo}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.3
|
||||
* @see OidcUserInfo
|
||||
* @see OAuth2ClientJackson2Module
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
||||
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
abstract class OidcUserInfoMixin {
|
||||
|
||||
@JsonCreator
|
||||
OidcUserInfoMixin(@JsonProperty("claims") Map<String, Object> claims) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.util.StdConverter;
|
||||
import org.springframework.security.oauth2.core.AuthenticationMethod;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
|
||||
import static org.springframework.security.oauth2.client.jackson2.JsonNodeUtils.findStringValue;
|
||||
|
||||
/**
|
||||
* {@code StdConverter} implementations.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.3
|
||||
*/
|
||||
abstract class StdConverters {
|
||||
|
||||
static final class AccessTokenTypeConverter extends StdConverter<JsonNode, OAuth2AccessToken.TokenType> {
|
||||
@Override
|
||||
public OAuth2AccessToken.TokenType convert(JsonNode jsonNode) {
|
||||
String value = findStringValue(jsonNode, "value");
|
||||
if (OAuth2AccessToken.TokenType.BEARER.getValue().equalsIgnoreCase(value)) {
|
||||
return OAuth2AccessToken.TokenType.BEARER;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static final class ClientAuthenticationMethodConverter extends StdConverter<JsonNode, ClientAuthenticationMethod> {
|
||||
@Override
|
||||
public ClientAuthenticationMethod convert(JsonNode jsonNode) {
|
||||
String value = findStringValue(jsonNode, "value");
|
||||
if (ClientAuthenticationMethod.BASIC.getValue().equalsIgnoreCase(value)) {
|
||||
return ClientAuthenticationMethod.BASIC;
|
||||
} else if (ClientAuthenticationMethod.POST.getValue().equalsIgnoreCase(value)) {
|
||||
return ClientAuthenticationMethod.POST;
|
||||
} else if (ClientAuthenticationMethod.NONE.getValue().equalsIgnoreCase(value)) {
|
||||
return ClientAuthenticationMethod.NONE;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static final class AuthorizationGrantTypeConverter extends StdConverter<JsonNode, AuthorizationGrantType> {
|
||||
@Override
|
||||
public AuthorizationGrantType convert(JsonNode jsonNode) {
|
||||
String value = findStringValue(jsonNode, "value");
|
||||
if (AuthorizationGrantType.AUTHORIZATION_CODE.getValue().equalsIgnoreCase(value)) {
|
||||
return AuthorizationGrantType.AUTHORIZATION_CODE;
|
||||
} else if (AuthorizationGrantType.IMPLICIT.getValue().equalsIgnoreCase(value)) {
|
||||
return AuthorizationGrantType.IMPLICIT;
|
||||
} else if (AuthorizationGrantType.CLIENT_CREDENTIALS.getValue().equalsIgnoreCase(value)) {
|
||||
return AuthorizationGrantType.CLIENT_CREDENTIALS;
|
||||
} else if (AuthorizationGrantType.PASSWORD.getValue().equalsIgnoreCase(value)) {
|
||||
return AuthorizationGrantType.PASSWORD;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static final class AuthenticationMethodConverter extends StdConverter<JsonNode, AuthenticationMethod> {
|
||||
@Override
|
||||
public AuthenticationMethod convert(JsonNode jsonNode) {
|
||||
String value = findStringValue(jsonNode, "value");
|
||||
if (AuthenticationMethod.HEADER.getValue().equalsIgnoreCase(value)) {
|
||||
return AuthenticationMethod.HEADER;
|
||||
} else if (AuthenticationMethod.FORM.getValue().equalsIgnoreCase(value)) {
|
||||
return AuthenticationMethod.FORM;
|
||||
} else if (AuthenticationMethod.QUERY.getValue().equalsIgnoreCase(value)) {
|
||||
return AuthenticationMethod.QUERY;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A {@code JsonDeserializer} for {@link Collections#unmodifiableMap(Map)}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.3
|
||||
* @see Collections#unmodifiableMap(Map)
|
||||
* @see UnmodifiableMapMixin
|
||||
*/
|
||||
final class UnmodifiableMapDeserializer extends JsonDeserializer<Map<?, ?>> {
|
||||
|
||||
@Override
|
||||
public Map<?, ?> deserialize(JsonParser parser, DeserializationContext context) throws IOException {
|
||||
ObjectMapper mapper = (ObjectMapper) parser.getCodec();
|
||||
JsonNode mapNode = mapper.readTree(parser);
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
if (mapNode != null && mapNode.isObject()) {
|
||||
Iterable<Map.Entry<String, JsonNode>> fields = mapNode::fields;
|
||||
for (Map.Entry<String, JsonNode> field : fields) {
|
||||
result.put(field.getKey(), mapper.readValue(field.getValue().traverse(mapper), Object.class));
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableMap(result);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This mixin class is used to serialize/deserialize {@link Collections#unmodifiableMap(Map)}.
|
||||
* It also registers a custom deserializer {@link UnmodifiableMapDeserializer}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.3
|
||||
* @see Collections#unmodifiableMap(Map)
|
||||
* @see UnmodifiableMapDeserializer
|
||||
* @see OAuth2ClientJackson2Module
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonDeserialize(using = UnmodifiableMapDeserializer.class)
|
||||
abstract class UnmodifiableMapMixin {
|
||||
|
||||
@JsonCreator
|
||||
UnmodifiableMapMixin(Map<?, ?> map) {
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 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.
|
||||
|
@ -16,11 +16,9 @@
|
|||
|
||||
package org.springframework.security.oauth2.client.authentication;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||
import org.springframework.security.oauth2.core.oidc.user.TestOidcUsers;
|
||||
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
|
||||
import org.springframework.security.oauth2.core.user.TestOAuth2Users;
|
||||
|
||||
/**
|
||||
|
@ -28,10 +26,16 @@ import org.springframework.security.oauth2.core.user.TestOAuth2Users;
|
|||
* @since 5.2
|
||||
*/
|
||||
public class TestOAuth2AuthenticationTokens {
|
||||
public static OAuth2AuthenticationToken authenticated(String... roles) {
|
||||
OAuth2User principal = TestOAuth2Users.create();
|
||||
Collection<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList(roles);
|
||||
|
||||
public static OAuth2AuthenticationToken authenticated() {
|
||||
DefaultOAuth2User principal = TestOAuth2Users.create();
|
||||
String registrationId = "registration-id";
|
||||
return new OAuth2AuthenticationToken(principal, authorities, registrationId);
|
||||
return new OAuth2AuthenticationToken(principal, principal.getAuthorities(), registrationId);
|
||||
}
|
||||
|
||||
public static OAuth2AuthenticationToken oidcAuthenticated() {
|
||||
DefaultOidcUser principal = TestOidcUsers.create();
|
||||
String registrationId = "registration-id";
|
||||
return new OAuth2AuthenticationToken(principal, principal.getAuthorities(), registrationId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,351 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.skyscreamer.jsonassert.JSONAssert;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.jackson2.SecurityJackson2Modules;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||
import org.springframework.security.oauth2.client.authentication.TestOAuth2AuthenticationTokens;
|
||||
import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
|
||||
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
|
||||
import org.springframework.security.oauth2.core.oidc.user.TestOidcUsers;
|
||||
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.NAME;
|
||||
|
||||
/**
|
||||
* Tests for {@link OAuth2AuthenticationTokenMixin}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
*/
|
||||
public class OAuth2AuthenticationTokenMixinTests {
|
||||
private static DateFormat dateFormatter;
|
||||
private ObjectMapper mapper;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
ClassLoader loader = getClass().getClassLoader();
|
||||
this.mapper = new ObjectMapper();
|
||||
this.mapper.registerModules(SecurityJackson2Modules.getModules(loader));
|
||||
this.mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||
dateFormatter = this.mapper.getDateFormat();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializeWhenMixinRegisteredThenSerializes() throws Exception {
|
||||
// OidcUser
|
||||
OAuth2AuthenticationToken authentication = TestOAuth2AuthenticationTokens.oidcAuthenticated();
|
||||
String expectedJson = asJson(authentication);
|
||||
String json = this.mapper.writeValueAsString(authentication);
|
||||
JSONAssert.assertEquals(expectedJson, json, true);
|
||||
|
||||
// OAuth2User
|
||||
authentication = TestOAuth2AuthenticationTokens.authenticated();
|
||||
expectedJson = asJson(authentication);
|
||||
json = this.mapper.writeValueAsString(authentication);
|
||||
JSONAssert.assertEquals(expectedJson, json, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializeWhenRequiredAttributesOnlyThenSerializes() throws Exception {
|
||||
DefaultOidcUser principal = TestOidcUsers.create();
|
||||
principal = new DefaultOidcUser(principal.getAuthorities(), principal.getIdToken());
|
||||
OAuth2AuthenticationToken authentication = new OAuth2AuthenticationToken(
|
||||
principal, Collections.emptyList(), "registration-id");
|
||||
String expectedJson = asJson(authentication);
|
||||
String json = this.mapper.writeValueAsString(authentication);
|
||||
JSONAssert.assertEquals(expectedJson, json, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializeWhenMixinNotRegisteredThenThrowJsonProcessingException() {
|
||||
OAuth2AuthenticationToken authentication = TestOAuth2AuthenticationTokens.oidcAuthenticated();
|
||||
String json = asJson(authentication);
|
||||
assertThatThrownBy(() -> new ObjectMapper().readValue(json, OAuth2AuthenticationToken.class))
|
||||
.isInstanceOf(JsonProcessingException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializeWhenMixinRegisteredThenDeserializes() throws Exception {
|
||||
// OidcUser
|
||||
OAuth2AuthenticationToken expectedAuthentication = TestOAuth2AuthenticationTokens.oidcAuthenticated();
|
||||
String json = asJson(expectedAuthentication);
|
||||
OAuth2AuthenticationToken authentication = this.mapper.readValue(json, OAuth2AuthenticationToken.class);
|
||||
assertThat(authentication.getAuthorities())
|
||||
.containsExactlyElementsOf(expectedAuthentication.getAuthorities());
|
||||
assertThat(authentication.getDetails())
|
||||
.isEqualTo(expectedAuthentication.getDetails());
|
||||
assertThat(authentication.isAuthenticated())
|
||||
.isEqualTo(expectedAuthentication.isAuthenticated());
|
||||
assertThat(authentication.getAuthorizedClientRegistrationId())
|
||||
.isEqualTo(expectedAuthentication.getAuthorizedClientRegistrationId());
|
||||
DefaultOidcUser expectedOidcUser = (DefaultOidcUser) expectedAuthentication.getPrincipal();
|
||||
DefaultOidcUser oidcUser = (DefaultOidcUser) authentication.getPrincipal();
|
||||
assertThat(oidcUser.getAuthorities().containsAll(expectedOidcUser.getAuthorities())).isTrue();
|
||||
assertThat(oidcUser.getAttributes())
|
||||
.containsExactlyEntriesOf(expectedOidcUser.getAttributes());
|
||||
assertThat(oidcUser.getName())
|
||||
.isEqualTo(expectedOidcUser.getName());
|
||||
OidcIdToken expectedIdToken = expectedOidcUser.getIdToken();
|
||||
OidcIdToken idToken = oidcUser.getIdToken();
|
||||
assertThat(idToken.getTokenValue())
|
||||
.isEqualTo(expectedIdToken.getTokenValue());
|
||||
assertThat(idToken.getIssuedAt())
|
||||
.isEqualTo(expectedIdToken.getIssuedAt());
|
||||
assertThat(idToken.getExpiresAt())
|
||||
.isEqualTo(expectedIdToken.getExpiresAt());
|
||||
assertThat(idToken.getClaims())
|
||||
.containsExactlyEntriesOf(expectedIdToken.getClaims());
|
||||
OidcUserInfo expectedUserInfo = expectedOidcUser.getUserInfo();
|
||||
OidcUserInfo userInfo = oidcUser.getUserInfo();
|
||||
assertThat(userInfo.getClaims())
|
||||
.containsExactlyEntriesOf(expectedUserInfo.getClaims());
|
||||
|
||||
// OAuth2User
|
||||
expectedAuthentication = TestOAuth2AuthenticationTokens.authenticated();
|
||||
json = asJson(expectedAuthentication);
|
||||
authentication = this.mapper.readValue(json, OAuth2AuthenticationToken.class);
|
||||
assertThat(authentication.getAuthorities())
|
||||
.containsExactlyElementsOf(expectedAuthentication.getAuthorities());
|
||||
assertThat(authentication.getDetails())
|
||||
.isEqualTo(expectedAuthentication.getDetails());
|
||||
assertThat(authentication.isAuthenticated())
|
||||
.isEqualTo(expectedAuthentication.isAuthenticated());
|
||||
assertThat(authentication.getAuthorizedClientRegistrationId())
|
||||
.isEqualTo(expectedAuthentication.getAuthorizedClientRegistrationId());
|
||||
DefaultOAuth2User expectedOauth2User = (DefaultOAuth2User) expectedAuthentication.getPrincipal();
|
||||
DefaultOAuth2User oauth2User = (DefaultOAuth2User) authentication.getPrincipal();
|
||||
assertThat(oauth2User.getAuthorities().containsAll(expectedOauth2User.getAuthorities())).isTrue();
|
||||
assertThat(oauth2User.getAttributes())
|
||||
.containsExactlyEntriesOf(expectedOauth2User.getAttributes());
|
||||
assertThat(oauth2User.getName())
|
||||
.isEqualTo(expectedOauth2User.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializeWhenRequiredAttributesOnlyThenDeserializes() throws Exception {
|
||||
DefaultOidcUser expectedPrincipal = TestOidcUsers.create();
|
||||
expectedPrincipal = new DefaultOidcUser(expectedPrincipal.getAuthorities(), expectedPrincipal.getIdToken());
|
||||
OAuth2AuthenticationToken expectedAuthentication = new OAuth2AuthenticationToken(
|
||||
expectedPrincipal, Collections.emptyList(), "registration-id");
|
||||
String json = asJson(expectedAuthentication);
|
||||
OAuth2AuthenticationToken authentication = this.mapper.readValue(json, OAuth2AuthenticationToken.class);
|
||||
assertThat(authentication.getAuthorities()).isEmpty();
|
||||
assertThat(authentication.getDetails())
|
||||
.isEqualTo(expectedAuthentication.getDetails());
|
||||
assertThat(authentication.isAuthenticated())
|
||||
.isEqualTo(expectedAuthentication.isAuthenticated());
|
||||
assertThat(authentication.getAuthorizedClientRegistrationId())
|
||||
.isEqualTo(expectedAuthentication.getAuthorizedClientRegistrationId());
|
||||
DefaultOidcUser principal = (DefaultOidcUser) authentication.getPrincipal();
|
||||
assertThat(principal.getAuthorities().containsAll(expectedPrincipal.getAuthorities())).isTrue();
|
||||
assertThat(principal.getAttributes())
|
||||
.containsExactlyEntriesOf(expectedPrincipal.getAttributes());
|
||||
assertThat(principal.getName())
|
||||
.isEqualTo(expectedPrincipal.getName());
|
||||
OidcIdToken expectedIdToken = expectedPrincipal.getIdToken();
|
||||
OidcIdToken idToken = principal.getIdToken();
|
||||
assertThat(idToken.getTokenValue())
|
||||
.isEqualTo(expectedIdToken.getTokenValue());
|
||||
assertThat(idToken.getIssuedAt())
|
||||
.isEqualTo(expectedIdToken.getIssuedAt());
|
||||
assertThat(idToken.getExpiresAt())
|
||||
.isEqualTo(expectedIdToken.getExpiresAt());
|
||||
assertThat(idToken.getClaims())
|
||||
.containsExactlyEntriesOf(expectedIdToken.getClaims());
|
||||
assertThat(principal.getUserInfo()).isNull();
|
||||
}
|
||||
|
||||
private static String asJson(OAuth2AuthenticationToken authentication) {
|
||||
String principalJson = authentication.getPrincipal() instanceof DefaultOidcUser ?
|
||||
asJson((DefaultOidcUser) authentication.getPrincipal()) :
|
||||
asJson((DefaultOAuth2User) authentication.getPrincipal());
|
||||
// @formatter:off
|
||||
return "{\n" +
|
||||
" \"@class\": \"org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken\",\n" +
|
||||
" \"principal\": " + principalJson + ",\n" +
|
||||
" \"authorities\": " + asJson(authentication.getAuthorities(), "java.util.Collections$UnmodifiableRandomAccessList") + ",\n" +
|
||||
" \"authorizedClientRegistrationId\": \"" + authentication.getAuthorizedClientRegistrationId() + "\",\n" +
|
||||
" \"details\": null\n" +
|
||||
"}";
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static String asJson(DefaultOAuth2User oauth2User) {
|
||||
// @formatter:off
|
||||
return "{\n" +
|
||||
" \"@class\": \"org.springframework.security.oauth2.core.user.DefaultOAuth2User\",\n" +
|
||||
" \"authorities\": " + asJson(oauth2User.getAuthorities(), "java.util.Collections$UnmodifiableSet") + ",\n" +
|
||||
" \"attributes\": {\n" +
|
||||
" \"@class\": \"java.util.Collections$UnmodifiableMap\",\n" +
|
||||
" \"username\": \"user\"\n" +
|
||||
" },\n" +
|
||||
" \"nameAttributeKey\": \"username\"\n" +
|
||||
" }";
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static String asJson(DefaultOidcUser oidcUser) {
|
||||
// @formatter:off
|
||||
return "{\n" +
|
||||
" \"@class\": \"org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser\",\n" +
|
||||
" \"authorities\": " + asJson(oidcUser.getAuthorities(), "java.util.Collections$UnmodifiableSet") + ",\n" +
|
||||
" \"idToken\": " + asJson(oidcUser.getIdToken()) + ",\n" +
|
||||
" \"userInfo\": " + asJson(oidcUser.getUserInfo()) + ",\n" +
|
||||
" \"nameAttributeKey\": \"" + IdTokenClaimNames.SUB + "\"\n" +
|
||||
" }";
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static String asJson(Collection<? extends GrantedAuthority> authorities, String classTypeInfo) {
|
||||
OAuth2UserAuthority oauth2UserAuthority = null;
|
||||
OidcUserAuthority oidcUserAuthority = null;
|
||||
List<SimpleGrantedAuthority> simpleAuthorities = new ArrayList<>();
|
||||
for (GrantedAuthority authority : authorities) {
|
||||
if (authority instanceof OidcUserAuthority) {
|
||||
oidcUserAuthority = (OidcUserAuthority) authority;
|
||||
} else if (authority instanceof OAuth2UserAuthority) {
|
||||
oauth2UserAuthority = (OAuth2UserAuthority) authority;
|
||||
} else if (authority instanceof SimpleGrantedAuthority) {
|
||||
simpleAuthorities.add((SimpleGrantedAuthority) authority);
|
||||
}
|
||||
}
|
||||
String authoritiesJson = oidcUserAuthority != null ?
|
||||
asJson(oidcUserAuthority) :
|
||||
oauth2UserAuthority != null ?
|
||||
asJson(oauth2UserAuthority) :
|
||||
"";
|
||||
if (!simpleAuthorities.isEmpty()) {
|
||||
if (!StringUtils.isEmpty(authoritiesJson)) {
|
||||
authoritiesJson += ",";
|
||||
}
|
||||
authoritiesJson += asJson(simpleAuthorities);
|
||||
}
|
||||
// @formatter:off
|
||||
return "[\n" +
|
||||
" \"" + classTypeInfo + "\",\n" +
|
||||
" [" + authoritiesJson + "]\n" +
|
||||
" ]";
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static String asJson(OAuth2UserAuthority oauth2UserAuthority) {
|
||||
// @formatter:off
|
||||
return "{\n" +
|
||||
" \"@class\": \"org.springframework.security.oauth2.core.user.OAuth2UserAuthority\",\n" +
|
||||
" \"authority\": \"" + oauth2UserAuthority.getAuthority() + "\",\n" +
|
||||
" \"attributes\": {\n" +
|
||||
" \"@class\": \"java.util.Collections$UnmodifiableMap\",\n" +
|
||||
" \"username\": \"user\"\n" +
|
||||
" }\n" +
|
||||
" }";
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static String asJson(OidcUserAuthority oidcUserAuthority) {
|
||||
// @formatter:off
|
||||
return "{\n" +
|
||||
" \"@class\": \"org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority\",\n" +
|
||||
" \"authority\": \"" + oidcUserAuthority.getAuthority() + "\",\n" +
|
||||
" \"idToken\": " + asJson(oidcUserAuthority.getIdToken()) + ",\n" +
|
||||
" \"userInfo\": " + asJson(oidcUserAuthority.getUserInfo()) + "\n" +
|
||||
" }";
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static String asJson(List<SimpleGrantedAuthority> simpleAuthorities) {
|
||||
// @formatter:off
|
||||
return simpleAuthorities.stream()
|
||||
.map(authority -> "{\n" +
|
||||
" \"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\",\n" +
|
||||
" \"authority\": \"" + authority.getAuthority() + "\"\n" +
|
||||
" }")
|
||||
.collect(Collectors.joining(","));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static String asJson(OidcIdToken idToken) {
|
||||
String aud = "";
|
||||
if (!CollectionUtils.isEmpty(idToken.getAudience())) {
|
||||
aud = StringUtils.collectionToDelimitedString(idToken.getAudience(), ",", "\"", "\"");
|
||||
}
|
||||
// @formatter:off
|
||||
return "{\n" +
|
||||
" \"@class\": \"org.springframework.security.oauth2.core.oidc.OidcIdToken\",\n" +
|
||||
" \"tokenValue\": \"" + idToken.getTokenValue() + "\",\n" +
|
||||
" \"issuedAt\": \"" + dateFormatter.format(Date.from(idToken.getIssuedAt())) + "\",\n" +
|
||||
" \"expiresAt\": \"" + dateFormatter.format(Date.from(idToken.getExpiresAt())) + "\",\n" +
|
||||
" \"claims\": {\n" +
|
||||
" \"@class\": \"java.util.Collections$UnmodifiableMap\",\n" +
|
||||
" \"iat\": [\n" +
|
||||
" \"java.time.Instant\",\n" +
|
||||
" \"" + idToken.getIssuedAt().toString() + "\"\n" +
|
||||
" ],\n" +
|
||||
" \"exp\": [\n" +
|
||||
" \"java.time.Instant\",\n" +
|
||||
" \"" + idToken.getExpiresAt().toString() + "\"\n" +
|
||||
" ],\n" +
|
||||
" \"sub\": \"" + idToken.getSubject() + "\",\n" +
|
||||
" \"iss\": \"" + idToken.getIssuer() + "\",\n" +
|
||||
" \"aud\": [\n" +
|
||||
" \"java.util.Collections$UnmodifiableSet\",\n" +
|
||||
" [" + aud + "]\n" +
|
||||
" ],\n" +
|
||||
" \"azp\": \"" + idToken.getAuthorizedParty() + "\"\n" +
|
||||
" }\n" +
|
||||
" }";
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static String asJson(OidcUserInfo userInfo) {
|
||||
if (userInfo == null) {
|
||||
return null;
|
||||
}
|
||||
// @formatter:off
|
||||
return "{\n" +
|
||||
" \"@class\": \"org.springframework.security.oauth2.core.oidc.OidcUserInfo\",\n" +
|
||||
" \"claims\": {\n" +
|
||||
" \"@class\": \"java.util.Collections$UnmodifiableMap\",\n" +
|
||||
" \"sub\": \"" + userInfo.getSubject() + "\",\n" +
|
||||
" \"name\": \"" + userInfo.getClaim(NAME) + "\"\n" +
|
||||
" }\n" +
|
||||
" }";
|
||||
// @formatter:on
|
||||
}
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.skyscreamer.jsonassert.JSONAssert;
|
||||
import org.springframework.security.jackson2.SecurityJackson2Modules;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||
import org.springframework.security.oauth2.core.endpoint.TestOAuth2AuthorizationRequests;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
* Tests for {@link OAuth2AuthorizationRequestMixin}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
*/
|
||||
public class OAuth2AuthorizationRequestMixinTests {
|
||||
private ObjectMapper mapper;
|
||||
private OAuth2AuthorizationRequest.Builder authorizationRequestBuilder;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
ClassLoader loader = getClass().getClassLoader();
|
||||
this.mapper = new ObjectMapper();
|
||||
this.mapper.registerModules(SecurityJackson2Modules.getModules(loader));
|
||||
Map<String, Object> additionalParameters = new LinkedHashMap<>();
|
||||
additionalParameters.put("param1", "value1");
|
||||
additionalParameters.put("param2", "value2");
|
||||
this.authorizationRequestBuilder = TestOAuth2AuthorizationRequests.request()
|
||||
.scope("read", "write")
|
||||
.additionalParameters(additionalParameters);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializeWhenMixinRegisteredThenSerializes() throws Exception {
|
||||
OAuth2AuthorizationRequest authorizationRequest = this.authorizationRequestBuilder.build();
|
||||
String expectedJson = asJson(authorizationRequest);
|
||||
String json = this.mapper.writeValueAsString(authorizationRequest);
|
||||
JSONAssert.assertEquals(expectedJson, json, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializeWhenRequiredAttributesOnlyThenSerializes() throws Exception {
|
||||
OAuth2AuthorizationRequest authorizationRequest =
|
||||
this.authorizationRequestBuilder
|
||||
.scopes(null)
|
||||
.state(null)
|
||||
.additionalParameters(null)
|
||||
.attributes(null)
|
||||
.build();
|
||||
String expectedJson = asJson(authorizationRequest);
|
||||
String json = this.mapper.writeValueAsString(authorizationRequest);
|
||||
JSONAssert.assertEquals(expectedJson, json, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializeWhenMixinNotRegisteredThenThrowJsonProcessingException() {
|
||||
String json = asJson(this.authorizationRequestBuilder.build());
|
||||
assertThatThrownBy(() -> new ObjectMapper().readValue(json, OAuth2AuthorizationRequest.class))
|
||||
.isInstanceOf(JsonProcessingException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializeWhenMixinRegisteredThenDeserializes() throws Exception {
|
||||
OAuth2AuthorizationRequest expectedAuthorizationRequest = this.authorizationRequestBuilder.build();
|
||||
String json = asJson(expectedAuthorizationRequest);
|
||||
OAuth2AuthorizationRequest authorizationRequest = this.mapper.readValue(json, OAuth2AuthorizationRequest.class);
|
||||
assertThat(authorizationRequest.getAuthorizationUri())
|
||||
.isEqualTo(expectedAuthorizationRequest.getAuthorizationUri());
|
||||
assertThat(authorizationRequest.getGrantType())
|
||||
.isEqualTo(expectedAuthorizationRequest.getGrantType());
|
||||
assertThat(authorizationRequest.getResponseType())
|
||||
.isEqualTo(expectedAuthorizationRequest.getResponseType());
|
||||
assertThat(authorizationRequest.getClientId())
|
||||
.isEqualTo(expectedAuthorizationRequest.getClientId());
|
||||
assertThat(authorizationRequest.getRedirectUri())
|
||||
.isEqualTo(expectedAuthorizationRequest.getRedirectUri());
|
||||
assertThat(authorizationRequest.getScopes())
|
||||
.isEqualTo(expectedAuthorizationRequest.getScopes());
|
||||
assertThat(authorizationRequest.getState())
|
||||
.isEqualTo(expectedAuthorizationRequest.getState());
|
||||
assertThat(authorizationRequest.getAdditionalParameters())
|
||||
.containsExactlyEntriesOf(expectedAuthorizationRequest.getAdditionalParameters());
|
||||
assertThat(authorizationRequest.getAuthorizationRequestUri())
|
||||
.isEqualTo(expectedAuthorizationRequest.getAuthorizationRequestUri());
|
||||
assertThat(authorizationRequest.getAttributes())
|
||||
.containsExactlyEntriesOf(expectedAuthorizationRequest.getAttributes());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializeWhenRequiredAttributesOnlyThenDeserializes() throws Exception {
|
||||
OAuth2AuthorizationRequest expectedAuthorizationRequest =
|
||||
this.authorizationRequestBuilder
|
||||
.scopes(null)
|
||||
.state(null)
|
||||
.additionalParameters(null)
|
||||
.attributes(null)
|
||||
.build();
|
||||
String json = asJson(expectedAuthorizationRequest);
|
||||
OAuth2AuthorizationRequest authorizationRequest = this.mapper.readValue(json, OAuth2AuthorizationRequest.class);
|
||||
assertThat(authorizationRequest.getAuthorizationUri())
|
||||
.isEqualTo(expectedAuthorizationRequest.getAuthorizationUri());
|
||||
assertThat(authorizationRequest.getGrantType())
|
||||
.isEqualTo(expectedAuthorizationRequest.getGrantType());
|
||||
assertThat(authorizationRequest.getResponseType())
|
||||
.isEqualTo(expectedAuthorizationRequest.getResponseType());
|
||||
assertThat(authorizationRequest.getClientId())
|
||||
.isEqualTo(expectedAuthorizationRequest.getClientId());
|
||||
assertThat(authorizationRequest.getRedirectUri())
|
||||
.isEqualTo(expectedAuthorizationRequest.getRedirectUri());
|
||||
assertThat(authorizationRequest.getScopes()).isEmpty();
|
||||
assertThat(authorizationRequest.getState()).isNull();
|
||||
assertThat(authorizationRequest.getAdditionalParameters()).isEmpty();
|
||||
assertThat(authorizationRequest.getAuthorizationRequestUri())
|
||||
.isEqualTo(expectedAuthorizationRequest.getAuthorizationRequestUri());
|
||||
assertThat(authorizationRequest.getAttributes()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializeWhenInvalidAuthorizationGrantTypeThenThrowJsonParseException() {
|
||||
OAuth2AuthorizationRequest authorizationRequest = this.authorizationRequestBuilder.build();
|
||||
String json = asJson(authorizationRequest).replace("authorization_code", "client_credentials");
|
||||
assertThatThrownBy(() -> this.mapper.readValue(json, OAuth2AuthorizationRequest.class))
|
||||
.isInstanceOf(JsonParseException.class)
|
||||
.hasMessageContaining("Invalid authorizationGrantType");
|
||||
}
|
||||
|
||||
private static String asJson(OAuth2AuthorizationRequest authorizationRequest) {
|
||||
String scopes = "";
|
||||
if (!CollectionUtils.isEmpty(authorizationRequest.getScopes())) {
|
||||
scopes = StringUtils.collectionToDelimitedString(authorizationRequest.getScopes(), ",", "\"", "\"");
|
||||
}
|
||||
String additionalParameters = "\"@class\": \"java.util.Collections$UnmodifiableMap\"";
|
||||
if (!CollectionUtils.isEmpty(authorizationRequest.getAdditionalParameters())) {
|
||||
additionalParameters += "," + authorizationRequest.getAdditionalParameters().keySet().stream()
|
||||
.map(key -> "\"" + key + "\": \"" + authorizationRequest.getAdditionalParameters().get(key) + "\"")
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
String attributes = "\"@class\": \"java.util.Collections$UnmodifiableMap\"";
|
||||
if (!CollectionUtils.isEmpty(authorizationRequest.getAttributes())) {
|
||||
attributes += "," + authorizationRequest.getAttributes().keySet().stream()
|
||||
.map(key -> "\"" + key + "\": \"" + authorizationRequest.getAttributes().get(key) + "\"")
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
// @formatter:off
|
||||
return "{\n" +
|
||||
" \"@class\": \"org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest\",\n" +
|
||||
" \"authorizationUri\": \"" + authorizationRequest.getAuthorizationUri() + "\",\n" +
|
||||
" \"authorizationGrantType\": {\n" +
|
||||
" \"value\": \"" + authorizationRequest.getGrantType().getValue() + "\"\n" +
|
||||
" },\n" +
|
||||
" \"responseType\": {\n" +
|
||||
" \"value\": \"" + authorizationRequest.getResponseType().getValue() + "\"\n" +
|
||||
" },\n" +
|
||||
" \"clientId\": \"" + authorizationRequest.getClientId() + "\",\n" +
|
||||
" \"redirectUri\": \"" + authorizationRequest.getRedirectUri() + "\",\n" +
|
||||
" \"scopes\": [\n" +
|
||||
" \"java.util.Collections$UnmodifiableSet\",\n" +
|
||||
" [" + scopes + "]\n" +
|
||||
" ],\n" +
|
||||
" \"state\": " + (authorizationRequest.getState() != null ? "\"" + authorizationRequest.getState() + "\"" : "null") + ",\n" +
|
||||
" \"additionalParameters\": {\n" +
|
||||
" " + additionalParameters + "\n" +
|
||||
" },\n" +
|
||||
" \"authorizationRequestUri\": \"" + authorizationRequest.getAuthorizationRequestUri() + "\",\n" +
|
||||
" \"attributes\": {\n" +
|
||||
" " + attributes + "\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
// @formatter:on
|
||||
}
|
||||
}
|
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
* 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.client.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.skyscreamer.jsonassert.JSONAssert;
|
||||
import org.springframework.security.jackson2.SecurityJackson2Modules;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.client.registration.TestClientRegistrations;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
|
||||
import org.springframework.security.oauth2.core.TestOAuth2AccessTokens;
|
||||
import org.springframework.security.oauth2.core.TestOAuth2RefreshTokens;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
* Tests for {@link OAuth2AuthorizedClientMixin}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
*/
|
||||
public class OAuth2AuthorizedClientMixinTests {
|
||||
private static DateFormat dateFormatter;
|
||||
private ObjectMapper mapper;
|
||||
private ClientRegistration.Builder clientRegistrationBuilder;
|
||||
private OAuth2AccessToken accessToken;
|
||||
private OAuth2RefreshToken refreshToken;
|
||||
private String principalName;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
ClassLoader loader = getClass().getClassLoader();
|
||||
this.mapper = new ObjectMapper();
|
||||
this.mapper.registerModules(SecurityJackson2Modules.getModules(loader));
|
||||
dateFormatter = this.mapper.getDateFormat();
|
||||
Map<String, Object> providerConfigurationMetadata = new LinkedHashMap<>();
|
||||
providerConfigurationMetadata.put("config1", "value1");
|
||||
providerConfigurationMetadata.put("config2", "value2");
|
||||
this.clientRegistrationBuilder = TestClientRegistrations.clientRegistration()
|
||||
.scope("read", "write")
|
||||
.providerConfigurationMetadata(providerConfigurationMetadata);
|
||||
this.accessToken = TestOAuth2AccessTokens.scopes("read", "write");
|
||||
this.refreshToken = TestOAuth2RefreshTokens.refreshToken();
|
||||
this.principalName = "principal-name";
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializeWhenMixinRegisteredThenSerializes() throws Exception {
|
||||
OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(
|
||||
this.clientRegistrationBuilder.build(), this.principalName, this.accessToken, this.refreshToken);
|
||||
String expectedJson = asJson(authorizedClient);
|
||||
String json = this.mapper.writeValueAsString(authorizedClient);
|
||||
JSONAssert.assertEquals(expectedJson, json, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializeWhenRequiredAttributesOnlyThenSerializes() throws Exception {
|
||||
ClientRegistration clientRegistration =
|
||||
TestClientRegistrations.clientRegistration()
|
||||
.clientSecret(null)
|
||||
.clientName(null)
|
||||
.userInfoUri(null)
|
||||
.userNameAttributeName(null)
|
||||
.jwkSetUri(null)
|
||||
.build();
|
||||
OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(
|
||||
clientRegistration, this.principalName, TestOAuth2AccessTokens.noScopes());
|
||||
String expectedJson = asJson(authorizedClient);
|
||||
String json = this.mapper.writeValueAsString(authorizedClient);
|
||||
JSONAssert.assertEquals(expectedJson, json, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializeWhenMixinNotRegisteredThenThrowJsonProcessingException() {
|
||||
OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(
|
||||
this.clientRegistrationBuilder.build(), this.principalName, this.accessToken);
|
||||
String json = asJson(authorizedClient);
|
||||
assertThatThrownBy(() -> new ObjectMapper().readValue(json, OAuth2AuthorizedClient.class))
|
||||
.isInstanceOf(JsonProcessingException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializeWhenMixinRegisteredThenDeserializes() throws Exception {
|
||||
ClientRegistration expectedClientRegistration = this.clientRegistrationBuilder.build();
|
||||
OAuth2AccessToken expectedAccessToken = this.accessToken;
|
||||
OAuth2RefreshToken expectedRefreshToken = this.refreshToken;
|
||||
OAuth2AuthorizedClient expectedAuthorizedClient = new OAuth2AuthorizedClient(
|
||||
expectedClientRegistration, this.principalName, expectedAccessToken, expectedRefreshToken);
|
||||
String json = asJson(expectedAuthorizedClient);
|
||||
OAuth2AuthorizedClient authorizedClient = this.mapper.readValue(json, OAuth2AuthorizedClient.class);
|
||||
ClientRegistration clientRegistration = authorizedClient.getClientRegistration();
|
||||
assertThat(clientRegistration.getRegistrationId())
|
||||
.isEqualTo(expectedClientRegistration.getRegistrationId());
|
||||
assertThat(clientRegistration.getClientId())
|
||||
.isEqualTo(expectedClientRegistration.getClientId());
|
||||
assertThat(clientRegistration.getClientSecret())
|
||||
.isEqualTo(expectedClientRegistration.getClientSecret());
|
||||
assertThat(clientRegistration.getClientAuthenticationMethod())
|
||||
.isEqualTo(expectedClientRegistration.getClientAuthenticationMethod());
|
||||
assertThat(clientRegistration.getAuthorizationGrantType())
|
||||
.isEqualTo(expectedClientRegistration.getAuthorizationGrantType());
|
||||
assertThat(clientRegistration.getRedirectUriTemplate())
|
||||
.isEqualTo(expectedClientRegistration.getRedirectUriTemplate());
|
||||
assertThat(clientRegistration.getScopes())
|
||||
.isEqualTo(expectedClientRegistration.getScopes());
|
||||
assertThat(clientRegistration.getProviderDetails().getAuthorizationUri())
|
||||
.isEqualTo(expectedClientRegistration.getProviderDetails().getAuthorizationUri());
|
||||
assertThat(clientRegistration.getProviderDetails().getTokenUri())
|
||||
.isEqualTo(expectedClientRegistration.getProviderDetails().getTokenUri());
|
||||
assertThat(clientRegistration.getProviderDetails().getUserInfoEndpoint().getUri())
|
||||
.isEqualTo(expectedClientRegistration.getProviderDetails().getUserInfoEndpoint().getUri());
|
||||
assertThat(clientRegistration.getProviderDetails().getUserInfoEndpoint().getAuthenticationMethod())
|
||||
.isEqualTo(expectedClientRegistration.getProviderDetails().getUserInfoEndpoint().getAuthenticationMethod());
|
||||
assertThat(clientRegistration.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName())
|
||||
.isEqualTo(expectedClientRegistration.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName());
|
||||
assertThat(clientRegistration.getProviderDetails().getJwkSetUri())
|
||||
.isEqualTo(expectedClientRegistration.getProviderDetails().getJwkSetUri());
|
||||
assertThat(clientRegistration.getProviderDetails().getConfigurationMetadata())
|
||||
.containsExactlyEntriesOf(clientRegistration.getProviderDetails().getConfigurationMetadata());
|
||||
assertThat(clientRegistration.getClientName())
|
||||
.isEqualTo(expectedClientRegistration.getClientName());
|
||||
assertThat(authorizedClient.getPrincipalName())
|
||||
.isEqualTo(expectedAuthorizedClient.getPrincipalName());
|
||||
OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
|
||||
assertThat(accessToken.getTokenType())
|
||||
.isEqualTo(expectedAccessToken.getTokenType());
|
||||
assertThat(accessToken.getScopes())
|
||||
.isEqualTo(expectedAccessToken.getScopes());
|
||||
assertThat(accessToken.getTokenValue())
|
||||
.isEqualTo(expectedAccessToken.getTokenValue());
|
||||
assertThat(accessToken.getIssuedAt())
|
||||
.isEqualTo(expectedAccessToken.getIssuedAt());
|
||||
assertThat(accessToken.getExpiresAt())
|
||||
.isEqualTo(expectedAccessToken.getExpiresAt());
|
||||
OAuth2RefreshToken refreshToken = authorizedClient.getRefreshToken();
|
||||
assertThat(refreshToken.getTokenValue())
|
||||
.isEqualTo(expectedRefreshToken.getTokenValue());
|
||||
assertThat(refreshToken.getIssuedAt())
|
||||
.isEqualTo(expectedRefreshToken.getIssuedAt());
|
||||
assertThat(refreshToken.getExpiresAt())
|
||||
.isEqualTo(expectedRefreshToken.getExpiresAt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializeWhenRequiredAttributesOnlyThenDeserializes() throws Exception {
|
||||
ClientRegistration expectedClientRegistration =
|
||||
TestClientRegistrations.clientRegistration()
|
||||
.clientSecret(null)
|
||||
.clientName(null)
|
||||
.userInfoUri(null)
|
||||
.userNameAttributeName(null)
|
||||
.jwkSetUri(null)
|
||||
.build();
|
||||
OAuth2AccessToken expectedAccessToken = TestOAuth2AccessTokens.noScopes();
|
||||
OAuth2AuthorizedClient expectedAuthorizedClient = new OAuth2AuthorizedClient(
|
||||
expectedClientRegistration, this.principalName, expectedAccessToken);
|
||||
String json = asJson(expectedAuthorizedClient);
|
||||
OAuth2AuthorizedClient authorizedClient = this.mapper.readValue(json, OAuth2AuthorizedClient.class);
|
||||
ClientRegistration clientRegistration = authorizedClient.getClientRegistration();
|
||||
assertThat(clientRegistration.getRegistrationId())
|
||||
.isEqualTo(expectedClientRegistration.getRegistrationId());
|
||||
assertThat(clientRegistration.getClientId())
|
||||
.isEqualTo(expectedClientRegistration.getClientId());
|
||||
assertThat(clientRegistration.getClientSecret()).isEmpty();
|
||||
assertThat(clientRegistration.getClientAuthenticationMethod())
|
||||
.isEqualTo(expectedClientRegistration.getClientAuthenticationMethod());
|
||||
assertThat(clientRegistration.getAuthorizationGrantType())
|
||||
.isEqualTo(expectedClientRegistration.getAuthorizationGrantType());
|
||||
assertThat(clientRegistration.getRedirectUriTemplate())
|
||||
.isEqualTo(expectedClientRegistration.getRedirectUriTemplate());
|
||||
assertThat(clientRegistration.getScopes())
|
||||
.isEqualTo(expectedClientRegistration.getScopes());
|
||||
assertThat(clientRegistration.getProviderDetails().getAuthorizationUri())
|
||||
.isEqualTo(expectedClientRegistration.getProviderDetails().getAuthorizationUri());
|
||||
assertThat(clientRegistration.getProviderDetails().getTokenUri())
|
||||
.isEqualTo(expectedClientRegistration.getProviderDetails().getTokenUri());
|
||||
assertThat(clientRegistration.getProviderDetails().getUserInfoEndpoint().getUri()).isNull();
|
||||
assertThat(clientRegistration.getProviderDetails().getUserInfoEndpoint().getAuthenticationMethod())
|
||||
.isEqualTo(expectedClientRegistration.getProviderDetails().getUserInfoEndpoint().getAuthenticationMethod());
|
||||
assertThat(clientRegistration.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName()).isNull();
|
||||
assertThat(clientRegistration.getProviderDetails().getJwkSetUri()).isNull();
|
||||
assertThat(clientRegistration.getProviderDetails().getConfigurationMetadata()).isEmpty();
|
||||
assertThat(clientRegistration.getClientName())
|
||||
.isEqualTo(clientRegistration.getRegistrationId());
|
||||
assertThat(authorizedClient.getPrincipalName())
|
||||
.isEqualTo(expectedAuthorizedClient.getPrincipalName());
|
||||
OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
|
||||
assertThat(accessToken.getTokenType())
|
||||
.isEqualTo(expectedAccessToken.getTokenType());
|
||||
assertThat(accessToken.getScopes()).isEmpty();
|
||||
assertThat(accessToken.getTokenValue())
|
||||
.isEqualTo(expectedAccessToken.getTokenValue());
|
||||
assertThat(accessToken.getIssuedAt())
|
||||
.isEqualTo(expectedAccessToken.getIssuedAt());
|
||||
assertThat(accessToken.getExpiresAt())
|
||||
.isEqualTo(expectedAccessToken.getExpiresAt());
|
||||
assertThat(authorizedClient.getRefreshToken()).isNull();
|
||||
}
|
||||
|
||||
private static String asJson(OAuth2AuthorizedClient authorizedClient) {
|
||||
// @formatter:off
|
||||
return "{\n" +
|
||||
" \"@class\": \"org.springframework.security.oauth2.client.OAuth2AuthorizedClient\",\n" +
|
||||
" \"clientRegistration\": " + asJson(authorizedClient.getClientRegistration()) + ",\n" +
|
||||
" \"principalName\": \"" + authorizedClient.getPrincipalName() + "\",\n" +
|
||||
" \"accessToken\": " + asJson(authorizedClient.getAccessToken()) + ",\n" +
|
||||
" \"refreshToken\": " + asJson(authorizedClient.getRefreshToken()) + "\n" +
|
||||
"}";
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static String asJson(ClientRegistration clientRegistration) {
|
||||
ClientRegistration.ProviderDetails providerDetails = clientRegistration.getProviderDetails();
|
||||
ClientRegistration.ProviderDetails.UserInfoEndpoint userInfoEndpoint = providerDetails.getUserInfoEndpoint();
|
||||
String scopes = "";
|
||||
if (!CollectionUtils.isEmpty(clientRegistration.getScopes())) {
|
||||
scopes = StringUtils.collectionToDelimitedString(clientRegistration.getScopes(), ",", "\"", "\"");
|
||||
}
|
||||
String configurationMetadata = "\"@class\": \"java.util.Collections$UnmodifiableMap\"";
|
||||
if (!CollectionUtils.isEmpty(providerDetails.getConfigurationMetadata())) {
|
||||
configurationMetadata += "," + providerDetails.getConfigurationMetadata().keySet().stream()
|
||||
.map(key -> "\"" + key + "\": \"" + providerDetails.getConfigurationMetadata().get(key) + "\"")
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
// @formatter:off
|
||||
return "{\n" +
|
||||
" \"@class\": \"org.springframework.security.oauth2.client.registration.ClientRegistration\",\n" +
|
||||
" \"registrationId\": \"" + clientRegistration.getRegistrationId() + "\",\n" +
|
||||
" \"clientId\": \"" + clientRegistration.getClientId() + "\",\n" +
|
||||
" \"clientSecret\": \"" + clientRegistration.getClientSecret() + "\",\n" +
|
||||
" \"clientAuthenticationMethod\": {\n" +
|
||||
" \"value\": \"" + clientRegistration.getClientAuthenticationMethod().getValue() + "\"\n" +
|
||||
" },\n" +
|
||||
" \"authorizationGrantType\": {\n" +
|
||||
" \"value\": \"" + clientRegistration.getAuthorizationGrantType().getValue() + "\"\n" +
|
||||
" },\n" +
|
||||
" \"redirectUriTemplate\": \"" + clientRegistration.getRedirectUriTemplate() + "\",\n" +
|
||||
" \"scopes\": [\n" +
|
||||
" \"java.util.Collections$UnmodifiableSet\",\n" +
|
||||
" [" + scopes + "]\n" +
|
||||
" ],\n" +
|
||||
" \"providerDetails\": {\n" +
|
||||
" \"@class\": \"org.springframework.security.oauth2.client.registration.ClientRegistration$ProviderDetails\",\n" +
|
||||
" \"authorizationUri\": \"" + providerDetails.getAuthorizationUri() + "\",\n" +
|
||||
" \"tokenUri\": \"" + providerDetails.getTokenUri() + "\",\n" +
|
||||
" \"userInfoEndpoint\": {\n" +
|
||||
" \"@class\": \"org.springframework.security.oauth2.client.registration.ClientRegistration$ProviderDetails$UserInfoEndpoint\",\n" +
|
||||
" \"uri\": " + (userInfoEndpoint.getUri() != null ? "\"" + userInfoEndpoint.getUri() + "\"" : null) + ",\n" +
|
||||
" \"authenticationMethod\": {\n" +
|
||||
" \"value\": \"" + userInfoEndpoint.getAuthenticationMethod().getValue() + "\"\n" +
|
||||
" },\n" +
|
||||
" \"userNameAttributeName\": " + (userInfoEndpoint.getUserNameAttributeName() != null ? "\"" + userInfoEndpoint.getUserNameAttributeName() + "\"" : null) + "\n" +
|
||||
" },\n" +
|
||||
" \"jwkSetUri\": " + (providerDetails.getJwkSetUri() != null ? "\"" + providerDetails.getJwkSetUri() + "\"" : null) + ",\n" +
|
||||
" \"configurationMetadata\": {\n" +
|
||||
" " + configurationMetadata + "\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"clientName\": \"" + clientRegistration.getClientName() + "\"\n" +
|
||||
"}";
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static String asJson(OAuth2AccessToken accessToken) {
|
||||
String scopes = "";
|
||||
if (!CollectionUtils.isEmpty(accessToken.getScopes())) {
|
||||
scopes = StringUtils.collectionToDelimitedString(accessToken.getScopes(), ",", "\"", "\"");
|
||||
}
|
||||
// @formatter:off
|
||||
return "{\n" +
|
||||
" \"@class\": \"org.springframework.security.oauth2.core.OAuth2AccessToken\",\n" +
|
||||
" \"tokenType\": {\n" +
|
||||
" \"value\": \"" + accessToken.getTokenType().getValue() + "\"\n" +
|
||||
" },\n" +
|
||||
" \"tokenValue\": \"" + accessToken.getTokenValue() + "\",\n" +
|
||||
" \"issuedAt\": \"" + dateFormatter.format(Date.from(accessToken.getIssuedAt())) + "\",\n" +
|
||||
" \"expiresAt\": \"" + dateFormatter.format(Date.from(accessToken.getExpiresAt())) + "\",\n" +
|
||||
" \"scopes\": [\n" +
|
||||
" \"java.util.Collections$UnmodifiableSet\",\n" +
|
||||
" [" + scopes + "]\n" +
|
||||
" ]\n" +
|
||||
"}";
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static String asJson(OAuth2RefreshToken refreshToken) {
|
||||
if (refreshToken == null) {
|
||||
return null;
|
||||
}
|
||||
// @formatter:off
|
||||
return "{\n" +
|
||||
" \"@class\": \"org.springframework.security.oauth2.core.OAuth2RefreshToken\",\n" +
|
||||
" \"tokenValue\": \"" + refreshToken.getTokenValue() + "\",\n" +
|
||||
" \"issuedAt\": \"" + dateFormatter.format(Date.from(refreshToken.getIssuedAt())) + "\",\n" +
|
||||
" \"expiresAt\": " + (refreshToken.getExpiresAt() != null ? "\"" + dateFormatter.format(Date.from(refreshToken.getExpiresAt())) + "\"" : null) + "\n" +
|
||||
"}";
|
||||
// @formatter:on
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
|
@ -16,15 +16,15 @@
|
|||
package org.springframework.security.oauth2.core.oidc.user;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
/**
|
||||
* @author Joe Grandja
|
||||
|
@ -32,16 +32,37 @@ import java.util.Map;
|
|||
public class TestOidcUsers {
|
||||
|
||||
public static DefaultOidcUser create() {
|
||||
List<GrantedAuthority> roles = AuthorityUtils.createAuthorityList("ROLE_USER");
|
||||
return new DefaultOidcUser(roles, idToken());
|
||||
OidcIdToken idToken = idToken();
|
||||
OidcUserInfo userInfo = userInfo();
|
||||
return new DefaultOidcUser(
|
||||
authorities(idToken, userInfo), idToken, userInfo);
|
||||
}
|
||||
|
||||
private static OidcIdToken idToken() {
|
||||
Map<String, Object> claims = new HashMap<>();
|
||||
claims.put(IdTokenClaimNames.SUB, "subject");
|
||||
claims.put(IdTokenClaimNames.ISS, "http://localhost/issuer");
|
||||
claims.put(IdTokenClaimNames.AUD, Collections.singletonList("client"));
|
||||
claims.put(IdTokenClaimNames.AZP, "client");
|
||||
return new OidcIdToken("id-token", Instant.now(), Instant.now().plusSeconds(3600), claims);
|
||||
Instant issuedAt = Instant.now();
|
||||
Instant expiresAt = issuedAt.plusSeconds(3600);
|
||||
return OidcIdToken.withTokenValue("id-token")
|
||||
.issuedAt(issuedAt)
|
||||
.expiresAt(expiresAt)
|
||||
.subject("subject")
|
||||
.issuer("http://localhost/issuer")
|
||||
.audience(Collections.unmodifiableSet(new LinkedHashSet<>(Collections.singletonList("client"))))
|
||||
.authorizedParty("client")
|
||||
.build();
|
||||
}
|
||||
|
||||
private static OidcUserInfo userInfo() {
|
||||
return OidcUserInfo.builder()
|
||||
.subject("subject")
|
||||
.name("full name")
|
||||
.build();
|
||||
}
|
||||
|
||||
private static Collection<? extends GrantedAuthority> authorities(OidcIdToken idToken, OidcUserInfo userInfo) {
|
||||
return new LinkedHashSet<>(
|
||||
Arrays.asList(
|
||||
new OidcUserAuthority(idToken, userInfo),
|
||||
new SimpleGrantedAuthority("SCOPE_read"),
|
||||
new SimpleGrantedAuthority("SCOPE_write")));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -17,10 +17,12 @@
|
|||
package org.springframework.security.oauth2.core.user;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -29,10 +31,18 @@ import java.util.Map;
|
|||
public class TestOAuth2Users {
|
||||
|
||||
public static DefaultOAuth2User create() {
|
||||
List<GrantedAuthority> roles = AuthorityUtils.createAuthorityList("ROLE_USER");
|
||||
String attrName = "username";
|
||||
String nameAttributeKey = "username";
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put(attrName, "user");
|
||||
return new DefaultOAuth2User(roles, attributes, attrName);
|
||||
attributes.put(nameAttributeKey, "user");
|
||||
Collection<GrantedAuthority> authorities = authorities(attributes);
|
||||
return new DefaultOAuth2User(authorities, attributes, nameAttributeKey);
|
||||
}
|
||||
|
||||
private static Collection<GrantedAuthority> authorities(Map<String, Object> attributes) {
|
||||
return new LinkedHashSet<>(
|
||||
Arrays.asList(
|
||||
new OAuth2UserAuthority(attributes),
|
||||
new SimpleGrantedAuthority("SCOPE_read"),
|
||||
new SimpleGrantedAuthority("SCOPE_write")));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue