Add jackson module for authorization server
Fixes problems with serialization of complex attribute values of various framework types such as OAuth2AuthorizationRequest and OAuth2ClientAuthenticationToken. Closes gh-324 Closes gh-328
This commit is contained in:
committed by
Steve Riesenberg
parent
67e62a2f21
commit
232b3b7ac6
@@ -10,6 +10,7 @@ dependencies {
|
|||||||
compile 'com.nimbusds:nimbus-jose-jwt'
|
compile 'com.nimbusds:nimbus-jose-jwt'
|
||||||
compile 'com.fasterxml.jackson.core:jackson-databind'
|
compile 'com.fasterxml.jackson.core:jackson-databind'
|
||||||
|
|
||||||
|
optional 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'
|
||||||
optional 'org.springframework:spring-jdbc'
|
optional 'org.springframework:spring-jdbc'
|
||||||
|
|
||||||
testCompile 'org.springframework.security:spring-security-test'
|
testCompile 'org.springframework.security:spring-security-test'
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.Module;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
import org.springframework.dao.DataRetrievalFailureException;
|
import org.springframework.dao.DataRetrievalFailureException;
|
||||||
@@ -41,6 +42,7 @@ import org.springframework.jdbc.support.lob.DefaultLobHandler;
|
|||||||
import org.springframework.jdbc.support.lob.LobCreator;
|
import org.springframework.jdbc.support.lob.LobCreator;
|
||||||
import org.springframework.jdbc.support.lob.LobHandler;
|
import org.springframework.jdbc.support.lob.LobHandler;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
import org.springframework.security.jackson2.SecurityJackson2Modules;
|
||||||
import org.springframework.security.oauth2.core.AbstractOAuth2Token;
|
import org.springframework.security.oauth2.core.AbstractOAuth2Token;
|
||||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||||
@@ -51,6 +53,7 @@ import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
|||||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
||||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
|
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
|
||||||
|
import org.springframework.security.oauth2.server.authorization.jackson2.OAuth2ServerJackson2Module;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
@@ -312,6 +315,11 @@ public class JdbcOAuth2AuthorizationService implements OAuth2AuthorizationServic
|
|||||||
public OAuth2AuthorizationRowMapper(RegisteredClientRepository registeredClientRepository) {
|
public OAuth2AuthorizationRowMapper(RegisteredClientRepository registeredClientRepository) {
|
||||||
Assert.notNull(registeredClientRepository, "registeredClientRepository cannot be null");
|
Assert.notNull(registeredClientRepository, "registeredClientRepository cannot be null");
|
||||||
this.registeredClientRepository = registeredClientRepository;
|
this.registeredClientRepository = registeredClientRepository;
|
||||||
|
|
||||||
|
ClassLoader classLoader = JdbcOAuth2AuthorizationService.class.getClassLoader();
|
||||||
|
List<Module> securityModules = SecurityJackson2Modules.getModules(classLoader);
|
||||||
|
this.objectMapper.registerModules(securityModules);
|
||||||
|
this.objectMapper.registerModule(new OAuth2ServerJackson2Module());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -446,6 +454,13 @@ public class JdbcOAuth2AuthorizationService implements OAuth2AuthorizationServic
|
|||||||
public static class OAuth2AuthorizationParametersMapper implements Function<OAuth2Authorization, List<SqlParameterValue>> {
|
public static class OAuth2AuthorizationParametersMapper implements Function<OAuth2Authorization, List<SqlParameterValue>> {
|
||||||
private ObjectMapper objectMapper = new ObjectMapper();
|
private ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
public OAuth2AuthorizationParametersMapper() {
|
||||||
|
ClassLoader classLoader = JdbcOAuth2AuthorizationService.class.getClassLoader();
|
||||||
|
List<Module> securityModules = SecurityJackson2Modules.getModules(classLoader);
|
||||||
|
this.objectMapper.registerModules(securityModules);
|
||||||
|
this.objectMapper.registerModule(new OAuth2ServerJackson2Module());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<SqlParameterValue> apply(OAuth2Authorization authorization) {
|
public List<SqlParameterValue> apply(OAuth2Authorization authorization) {
|
||||||
List<SqlParameterValue> parameters = new ArrayList<>();
|
List<SqlParameterValue> parameters = new ArrayList<>();
|
||||||
|
|||||||
@@ -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.server.authorization.jackson2;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This mixin class is used to serialize/deserialize {@link HashSet}.
|
||||||
|
*
|
||||||
|
* @author Steve Riesenberg
|
||||||
|
* @see HashSet
|
||||||
|
* @see OAuth2ServerJackson2Module
|
||||||
|
* @since 0.1.2
|
||||||
|
*/
|
||||||
|
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||||
|
abstract class HashSetMixin {
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
HashSetMixin(Set<?> set) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* 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.server.authorization.jackson2;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for {@code JsonNode}.
|
||||||
|
*
|
||||||
|
* @author Joe Grandja
|
||||||
|
* @since 0.1.2
|
||||||
|
*/
|
||||||
|
abstract class JsonNodeUtils {
|
||||||
|
|
||||||
|
static final TypeReference<Set<String>> STRING_SET = new TypeReference<Set<String>>() {
|
||||||
|
};
|
||||||
|
|
||||||
|
static final TypeReference<Map<String, Object>> STRING_OBJECT_MAP = new TypeReference<Map<String, Object>>() {
|
||||||
|
};
|
||||||
|
|
||||||
|
static String findStringValue(JsonNode jsonNode, String fieldName) {
|
||||||
|
if (jsonNode == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
JsonNode value = jsonNode.findValue(fieldName);
|
||||||
|
return (value != null && value.isTextual()) ? value.asText() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static <T> T findValue(JsonNode jsonNode, String fieldName, TypeReference<T> valueTypeReference,
|
||||||
|
ObjectMapper mapper) {
|
||||||
|
if (jsonNode == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
JsonNode value = jsonNode.findValue(fieldName);
|
||||||
|
return (value != null && value.isContainerNode()) ? mapper.convertValue(value, valueTypeReference) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JsonNode findObjectNode(JsonNode jsonNode, String fieldName) {
|
||||||
|
if (jsonNode == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
JsonNode value = jsonNode.findValue(fieldName);
|
||||||
|
return (value != null && value.isObject()) ? value : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* 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.server.authorization.jackson2;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
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 org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest.Builder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@code JsonDeserializer} for {@link OAuth2AuthorizationRequest}.
|
||||||
|
*
|
||||||
|
* @author Joe Grandja
|
||||||
|
* @since 0.1.2
|
||||||
|
* @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 root = mapper.readTree(parser);
|
||||||
|
return deserialize(parser, mapper, root);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OAuth2AuthorizationRequest deserialize(JsonParser parser, ObjectMapper mapper, JsonNode root)
|
||||||
|
throws JsonParseException {
|
||||||
|
AuthorizationGrantType authorizationGrantType = AUTHORIZATION_GRANT_TYPE_CONVERTER
|
||||||
|
.convert(JsonNodeUtils.findObjectNode(root, "authorizationGrantType"));
|
||||||
|
Builder builder = getBuilder(parser, authorizationGrantType);
|
||||||
|
builder.authorizationUri(JsonNodeUtils.findStringValue(root, "authorizationUri"));
|
||||||
|
builder.clientId(JsonNodeUtils.findStringValue(root, "clientId"));
|
||||||
|
builder.redirectUri(JsonNodeUtils.findStringValue(root, "redirectUri"));
|
||||||
|
builder.scopes(JsonNodeUtils.findValue(root, "scopes", JsonNodeUtils.STRING_SET, mapper));
|
||||||
|
builder.state(JsonNodeUtils.findStringValue(root, "state"));
|
||||||
|
builder.additionalParameters(
|
||||||
|
JsonNodeUtils.findValue(root, "additionalParameters", JsonNodeUtils.STRING_OBJECT_MAP, mapper));
|
||||||
|
builder.authorizationRequestUri(JsonNodeUtils.findStringValue(root, "authorizationRequestUri"));
|
||||||
|
builder.attributes(JsonNodeUtils.findValue(root, "attributes", JsonNodeUtils.STRING_OBJECT_MAP, mapper));
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Builder getBuilder(JsonParser parser,
|
||||||
|
AuthorizationGrantType authorizationGrantType) throws JsonParseException {
|
||||||
|
if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(authorizationGrantType)) {
|
||||||
|
return OAuth2AuthorizationRequest.authorizationCode();
|
||||||
|
}
|
||||||
|
if (AuthorizationGrantType.IMPLICIT.equals(authorizationGrantType)) {
|
||||||
|
return OAuth2AuthorizationRequest.implicit();
|
||||||
|
}
|
||||||
|
throw new JsonParseException(parser, "Invalid authorizationGrantType");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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.server.authorization.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 0.1.2
|
||||||
|
* @see OAuth2AuthorizationRequest
|
||||||
|
* @see OAuth2AuthorizationRequestDeserializer
|
||||||
|
* @see OAuth2ServerJackson2Module
|
||||||
|
*/
|
||||||
|
@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,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.server.authorization.jackson2;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
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.ClientAuthenticationMethod;
|
||||||
|
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This mixin class is used to serialize/deserialize {@link OAuth2ClientAuthenticationToken}.
|
||||||
|
*
|
||||||
|
* @author Joe Grandja
|
||||||
|
* @since 0.1.2
|
||||||
|
* @see OAuth2ClientAuthenticationToken
|
||||||
|
* @see OAuth2ServerJackson2Module
|
||||||
|
*/
|
||||||
|
@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 OAuth2ClientAuthenticationTokenMixin {
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
OAuth2ClientAuthenticationTokenMixin(@JsonProperty("clientId") String clientId,
|
||||||
|
@JsonProperty("clientSecret") String clientSecret,
|
||||||
|
@JsonProperty("clientAuthenticationMethod") ClientAuthenticationMethod clientAuthenticationMethod,
|
||||||
|
@JsonProperty("additionalParameters") Map<String, Object> additionalParameters) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* 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.server.authorization.jackson2;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.Version;
|
||||||
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
|
|
||||||
|
import org.springframework.security.jackson2.SecurityJackson2Modules;
|
||||||
|
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||||
|
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jackson {@code Module} for {@code spring-authorization-server}, that registers the
|
||||||
|
* following mix-in annotations:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link UnmodifiableMapMixin}</li>
|
||||||
|
* <li>{@link HashSetMixin}</li>
|
||||||
|
* <li>{@link OAuth2AuthorizationRequestMixin}</li>
|
||||||
|
* <li>{@link OAuth2ClientAuthenticationTokenMixin}</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 OAuth2ServerJackson2Module());
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author Steve Riesenberg
|
||||||
|
* @since 0.1.2
|
||||||
|
* @see SecurityJackson2Modules
|
||||||
|
* @see UnmodifiableMapMixin
|
||||||
|
* @see HashSetMixin
|
||||||
|
* @see OAuth2AuthorizationRequestMixin
|
||||||
|
* @see OAuth2ClientAuthenticationTokenMixin
|
||||||
|
*/
|
||||||
|
public class OAuth2ServerJackson2Module extends SimpleModule {
|
||||||
|
|
||||||
|
public OAuth2ServerJackson2Module() {
|
||||||
|
super(OAuth2ServerJackson2Module.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(HashSet.class, HashSetMixin.class);
|
||||||
|
context.setMixInAnnotations(OAuth2AuthorizationRequest.class, OAuth2AuthorizationRequestMixin.class);
|
||||||
|
context.setMixInAnnotations(OAuth2ClientAuthenticationToken.class, OAuth2ClientAuthenticationTokenMixin.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* 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.server.authorization.jackson2;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.util.StdConverter;
|
||||||
|
|
||||||
|
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code StdConverter} implementations.
|
||||||
|
*
|
||||||
|
* @author Joe Grandja
|
||||||
|
* @since 0.1.2
|
||||||
|
*/
|
||||||
|
abstract class StdConverters {
|
||||||
|
|
||||||
|
static final class AuthorizationGrantTypeConverter extends StdConverter<JsonNode, AuthorizationGrantType> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthorizationGrantType convert(JsonNode jsonNode) {
|
||||||
|
String value = JsonNodeUtils.findStringValue(jsonNode, "value");
|
||||||
|
if (AuthorizationGrantType.AUTHORIZATION_CODE.getValue().equalsIgnoreCase(value)) {
|
||||||
|
return AuthorizationGrantType.AUTHORIZATION_CODE;
|
||||||
|
}
|
||||||
|
if (AuthorizationGrantType.IMPLICIT.getValue().equalsIgnoreCase(value)) {
|
||||||
|
return AuthorizationGrantType.IMPLICIT;
|
||||||
|
}
|
||||||
|
if (AuthorizationGrantType.CLIENT_CREDENTIALS.getValue().equalsIgnoreCase(value)) {
|
||||||
|
return AuthorizationGrantType.CLIENT_CREDENTIALS;
|
||||||
|
}
|
||||||
|
if (AuthorizationGrantType.PASSWORD.getValue().equalsIgnoreCase(value)) {
|
||||||
|
return AuthorizationGrantType.PASSWORD;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* 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.server.authorization.jackson2;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@code JsonDeserializer} for {@link Collections#unmodifiableMap(Map)}.
|
||||||
|
*
|
||||||
|
* @author Joe Grandja
|
||||||
|
* @since 0.1.2
|
||||||
|
* @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,45 @@
|
|||||||
|
/*
|
||||||
|
* 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.server.authorization.jackson2;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This mixin class is used to serialize/deserialize
|
||||||
|
* {@link Collections#unmodifiableMap(Map)}. It also registers a custom deserializer
|
||||||
|
* {@link UnmodifiableMapDeserializer}.
|
||||||
|
*
|
||||||
|
* @author Joe Grandja
|
||||||
|
* @since 0.1.2
|
||||||
|
* @see Collections#unmodifiableMap(Map)
|
||||||
|
* @see UnmodifiableMapDeserializer
|
||||||
|
* @see OAuth2ServerJackson2Module
|
||||||
|
*/
|
||||||
|
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||||
|
@JsonDeserialize(using = UnmodifiableMapDeserializer.class)
|
||||||
|
abstract class UnmodifiableMapMixin {
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
UnmodifiableMapMixin(Map<?, ?> map) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ CREATE TABLE oauth2_authorization (
|
|||||||
registered_client_id varchar(100) NOT NULL,
|
registered_client_id varchar(100) NOT NULL,
|
||||||
principal_name varchar(200) NOT NULL,
|
principal_name varchar(200) NOT NULL,
|
||||||
authorization_grant_type varchar(100) NOT NULL,
|
authorization_grant_type varchar(100) NOT NULL,
|
||||||
attributes varchar(1000) DEFAULT NULL,
|
attributes varchar(4000) DEFAULT NULL,
|
||||||
state varchar(1000) DEFAULT NULL,
|
state varchar(1000) DEFAULT NULL,
|
||||||
authorization_code_value blob DEFAULT NULL,
|
authorization_code_value blob DEFAULT NULL,
|
||||||
authorization_code_issued_at timestamp DEFAULT NULL,
|
authorization_code_issued_at timestamp DEFAULT NULL,
|
||||||
|
|||||||
Reference in New Issue
Block a user