Permalink
Browse files

SECOAUTH-358: Provide support for Jackson 2

* add both jackson dependencies (2.0 is optional)
* add jackson2 dependency in bundlor template
* use both jackson 1 and 2 for OAuth2Exception
* use both jackson 1 and 2 for OAuth2AccessToken
* add specific jackson2 tests (with their own jackson2 objectMapper instance)
* fix @author tags
  • Loading branch information...
1 parent ea2203d commit 77502bcc958b1d479fee6e18ffe531ffceab049c @bclozel bclozel committed with dsyer Nov 23, 2012
Showing with 650 additions and 28 deletions.
  1. +21 −2 spring-security-oauth2/pom.xml
  2. +5 −5 ...g-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessToken.java
  3. +3 −3 ...y/oauth2/common/{OAuth2AccessTokenDeserializer.java → OAuth2AccessTokenJackson1Deserializer.java}
  4. +4 −4 ...urity/oauth2/common/{OAuth2AccessTokenSerializer.java → OAuth2AccessTokenJackson1Serializer.java}
  5. +100 −0 ...c/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Deserializer.java
  6. +72 −0 ...src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Serializer.java
  7. +9 −5 ...y-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2Exception.java
  8. +1 −1 ...2/common/exceptions/{OAuth2ExceptionDeserializer.java → OAuth2ExceptionJackson1Deserializer.java}
  9. +1 −1 ...auth2/common/exceptions/{OAuth2ExceptionSerializer.java → OAuth2ExceptionJackson1Serializer.java}
  10. +125 −0 ...va/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Deserializer.java
  11. +50 −0 ...java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Serializer.java
  12. +0 −3 ...h2/src/test/java/org/springframework/security/oauth2/common/BaseOAuth2AccessTokenJacksonTest.java
  13. +11 −2 .../common/{TestOAuth2AccessTokenDeserializer.java → TestOAuth2AccessTokenJackson1Deserializer.java}
  14. +11 −2 ...uth2/common/{TestOAuth2AccessTokenSerializer.java → TestOAuth2AccessTokenJackson1Serializer.java}
  15. +118 −0 ...st/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson2Deserializer.java
  16. +118 −0 ...test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson2Serializer.java
  17. +1 −0 spring-security-oauth2/template.mf
@@ -12,6 +12,11 @@
<name>OAuth2 for Spring Security</name>
<description>Module for providing OAuth2 support to Spring Security</description>
+ <properties>
+ <jackson1.version>1.9.2</jackson1.version>
+ <jackson2.version>2.1.1</jackson2.version>
+ </properties>
+
<build>
<plugins>
<plugin>
@@ -142,8 +147,22 @@
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
- <version>1.9.2</version>
- </dependency>
+ <version>${jackson1.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ <version>${jackson2.version}</version>
+ <optional>true</optional>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>${jackson2.version}</version>
+ <optional>true</optional>
+ </dependency>
<dependency>
<groupId>junit</groupId>
@@ -16,15 +16,15 @@
import java.util.Map;
import java.util.Set;
-import org.codehaus.jackson.map.annotate.JsonDeserialize;
-import org.codehaus.jackson.map.annotate.JsonSerialize;
-
/**
* @author Dave Syer
*
*/
-@JsonSerialize(using = OAuth2AccessTokenSerializer.class)
-@JsonDeserialize(using = OAuth2AccessTokenDeserializer.class)
+@org.codehaus.jackson.map.annotate.JsonSerialize(using = OAuth2AccessTokenJackson1Serializer.class)
+@org.codehaus.jackson.map.annotate.JsonDeserialize(using = OAuth2AccessTokenJackson1Deserializer.class)
+@com.fasterxml.jackson.databind.annotation.JsonSerialize(using = OAuth2AccessTokenJackson2Serializer.class)
+@com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = OAuth2AccessTokenJackson2Deserializer.class)
+
public interface OAuth2AccessToken {
public static String BEARER_TYPE = "Bearer";
@@ -37,12 +37,12 @@
* </p>
*
* @author Rob Winch
- * @see OAuth2AccessTokenDeserializer
+ * @see OAuth2AccessTokenJackson1Serializer
*/
@SuppressWarnings("deprecation")
-public final class OAuth2AccessTokenDeserializer extends StdDeserializer<OAuth2AccessToken> {
+public final class OAuth2AccessTokenJackson1Deserializer extends StdDeserializer<OAuth2AccessToken> {
- public OAuth2AccessTokenDeserializer() {
+ public OAuth2AccessTokenJackson1Deserializer() {
super(OAuth2AccessToken.class);
}
@@ -26,15 +26,15 @@
/**
* Provides the ability to serialize an {@link OAuth2AccessToken} with jackson by implementing {@link JsonSerializer}.
- * Refer to {@link OAuth2AccessTokenDeserializer} to learn more about the JSON format that is used.
+ * Refer to {@link OAuth2AccessTokenJackson1Deserializer} to learn more about the JSON format that is used.
*
* @author Rob Winch
- * @see OAuth2AccessTokenDeserializer
+ * @see OAuth2AccessTokenJackson1Deserializer
*/
@SuppressWarnings("deprecation")
-public final class OAuth2AccessTokenSerializer extends SerializerBase<OAuth2AccessToken> {
+public final class OAuth2AccessTokenJackson1Serializer extends SerializerBase<OAuth2AccessToken> {
- public OAuth2AccessTokenSerializer() {
+ public OAuth2AccessTokenJackson1Serializer() {
super(OAuth2AccessToken.class);
}
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2006-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.springframework.security.oauth2.common;
+
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+import org.springframework.security.oauth2.common.util.OAuth2Utils;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * <p>
+ * Provides the ability to deserialize JSON response into an {@link org.springframework.security.oauth2.common.OAuth2AccessToken} with jackson2 by implementing
+ * {@link com.fasterxml.jackson.databind.JsonDeserializer}.
+ * </p>
+ * <p>
+ * The expected format of the access token is defined by <a
+ * href="http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-5.1">Successful Response</a>.
+ * </p>
+ *
+ * @author Rob Winch
+ * @author Brian Clozel
+ * @see org.springframework.security.oauth2.common.OAuth2AccessTokenJackson2Serializer
+ */
+@SuppressWarnings("deprecation")
+public final class OAuth2AccessTokenJackson2Deserializer extends StdDeserializer<OAuth2AccessToken> {
+
+ public OAuth2AccessTokenJackson2Deserializer() {
+ super(OAuth2AccessToken.class);
+ }
+
+ @Override
+ public OAuth2AccessToken deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException,
+ JsonProcessingException {
+
+ String tokenValue = null;
+ String tokenType = null;
+ String refreshToken = null;
+ Long expiresIn = null;
+ Set<String> scope = null;
+ Map<String, Object> additionalInformation = new LinkedHashMap<String, Object>();
+
+ // TODO What should occur if a parameter exists twice
+ while (jp.nextToken() != JsonToken.END_OBJECT) {
+ String name = jp.getCurrentName();
+ jp.nextToken();
+ if (OAuth2AccessToken.ACCESS_TOKEN.equals(name)) {
+ tokenValue = jp.getText();
+ }
+ else if (OAuth2AccessToken.TOKEN_TYPE.equals(name)) {
+ tokenType = jp.getText();
+ }
+ else if (OAuth2AccessToken.REFRESH_TOKEN.equals(name)) {
+ refreshToken = jp.getText();
+ }
+ else if (OAuth2AccessToken.EXPIRES_IN.equals(name)) {
+ expiresIn = jp.getLongValue();
+ }
+ else if (OAuth2AccessToken.SCOPE.equals(name)) {
+ String text = jp.getText();
+ scope = OAuth2Utils.parseParameterList(text);
+ } else {
+ additionalInformation.put(name, jp.readValueAs(Object.class));
+ }
+ }
+
+ // TODO What should occur if a required parameter (tokenValue or tokenType) is missing?
+
+ DefaultOAuth2AccessToken accessToken = new DefaultOAuth2AccessToken(tokenValue);
+ accessToken.setTokenType(tokenType);
+ if (expiresIn != null) {
+ accessToken.setExpiration(new Date(System.currentTimeMillis() + (expiresIn * 1000)));
+ }
+ if (refreshToken != null) {
+ accessToken.setRefreshToken(new DefaultOAuth2RefreshToken(refreshToken));
+ }
+ accessToken.setScope(scope);
+ accessToken.setAdditionalInformation(additionalInformation);
+
+ return accessToken;
+ }
+}
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2006-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.springframework.security.oauth2.common;
+
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import org.springframework.util.Assert;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Provides the ability to serialize an {@link org.springframework.security.oauth2.common.OAuth2AccessToken} with jackson2 by implementing {@link com.fasterxml.jackson.databind.JsonDeserializer}.
+ * Refer to {@link org.springframework.security.oauth2.common.OAuth2AccessTokenJackson1Deserializer} to learn more about the JSON format that is used.
+ *
+ * @author Rob Winch
+ * @author Brian Clozel
+ * @see org.springframework.security.oauth2.common.OAuth2AccessTokenJackson2Deserializer
+ */
+@SuppressWarnings("deprecation")
+public final class OAuth2AccessTokenJackson2Serializer extends StdSerializer<OAuth2AccessToken> {
+
+ public OAuth2AccessTokenJackson2Serializer() {
+ super(OAuth2AccessToken.class);
+ }
+
+ @Override
+ public void serialize(OAuth2AccessToken token, JsonGenerator jgen, SerializerProvider provider) throws IOException,
+ JsonGenerationException {
+ jgen.writeStartObject();
+ jgen.writeStringField(OAuth2AccessToken.ACCESS_TOKEN, token.getValue());
+ jgen.writeStringField(OAuth2AccessToken.TOKEN_TYPE, token.getTokenType());
+ OAuth2RefreshToken refreshToken = token.getRefreshToken();
+ if (refreshToken != null) {
+ jgen.writeStringField(OAuth2AccessToken.REFRESH_TOKEN, refreshToken.getValue());
+ }
+ Date expiration = token.getExpiration();
+ if (expiration != null) {
+ long now = System.currentTimeMillis();
+ jgen.writeNumberField(OAuth2AccessToken.EXPIRES_IN, (expiration.getTime() - now) / 1000);
+ }
+ Set<String> scope = token.getScope();
+ if (scope != null && !scope.isEmpty()) {
+ StringBuffer scopes = new StringBuffer();
+ for (String s : scope) {
+ Assert.hasLength(s, "Scopes cannot be null or empty. Got " + scope + "");
+ scopes.append(s);
+ scopes.append(" ");
+ }
+ jgen.writeStringField(OAuth2AccessToken.SCOPE, scopes.substring(0, scopes.length() - 1));
+ }
+ Map<String, Object> additionalInformation = token.getAdditionalInformation();
+ for (String key : additionalInformation.keySet()) {
+ jgen.writeObjectField(key, additionalInformation.get(key));
+ }
+ jgen.writeEndObject();
+ }
+}
@@ -1,21 +1,25 @@
package org.springframework.security.oauth2.common.exceptions;
+import org.springframework.security.oauth2.common.OAuth2AccessTokenJackson1Deserializer;
+import org.springframework.security.oauth2.common.OAuth2AccessTokenJackson1Serializer;
+import org.springframework.security.oauth2.common.OAuth2AccessTokenJackson2Deserializer;
+import org.springframework.security.oauth2.common.OAuth2AccessTokenJackson2Serializer;
+
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
-import org.codehaus.jackson.map.annotate.JsonDeserialize;
-import org.codehaus.jackson.map.annotate.JsonSerialize;
-
/**
* Base exception for OAuth 2 exceptions.
*
* @author Ryan Heaton
* @author Rob Winch
* @author Dave Syer
*/
-@JsonSerialize(using = OAuth2ExceptionSerializer.class)
-@JsonDeserialize(using = OAuth2ExceptionDeserializer.class)
+@org.codehaus.jackson.map.annotate.JsonSerialize(using = OAuth2ExceptionJackson1Serializer.class)
+@org.codehaus.jackson.map.annotate.JsonDeserialize(using = OAuth2ExceptionJackson1Deserializer.class)
+@com.fasterxml.jackson.databind.annotation.JsonSerialize(using = OAuth2ExceptionJackson2Serializer.class)
+@com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = OAuth2ExceptionJackson2Deserializer.class)
public class OAuth2Exception extends RuntimeException {
public static final String ERROR = "error";
@@ -28,7 +28,7 @@
* @author Dave Syer
*
*/
-public class OAuth2ExceptionDeserializer extends JsonDeserializer<OAuth2Exception> {
+public class OAuth2ExceptionJackson1Deserializer extends JsonDeserializer<OAuth2Exception> {
@Override
public OAuth2Exception deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException,
@@ -24,7 +24,7 @@
* @author Dave Syer
*
*/
-public class OAuth2ExceptionSerializer extends JsonSerializer<OAuth2Exception> {
+public class OAuth2ExceptionJackson1Serializer extends JsonSerializer<OAuth2Exception> {
@Override
public void serialize(OAuth2Exception value, JsonGenerator jgen, SerializerProvider provider) throws IOException,
Oops, something went wrong. Retry.

0 comments on commit 77502bc

Please sign in to comment.