Skip to content
This repository has been archived by the owner on May 31, 2022. It is now read-only.

Commit

Permalink
SECOAUTH-271: add custom deserializer for collection properties in Ba…
Browse files Browse the repository at this point in the history
…seClientDetails
  • Loading branch information
dsyer committed Jun 1, 2012
1 parent c032c0a commit 68f1446
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.springframework.security.oauth2.provider;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
Expand All @@ -9,11 +10,20 @@
import java.util.List;
import java.util.Set;

import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.annotate.JsonDeserialize;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;
import org.codehaus.jackson.map.deser.std.StdDeserializer;
import org.codehaus.jackson.map.type.SimpleType;
import org.codehaus.jackson.type.JavaType;
import org.codehaus.jackson.type.TypeReference;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.util.StringUtils;
Expand All @@ -34,22 +44,26 @@ public class BaseClientDetails implements ClientDetails {
@JsonProperty("client_secret")
private String clientSecret;

@JsonDeserialize(using = ArrayOrStringDeserializer.class)
private Set<String> scope = Collections.emptySet();

@JsonProperty("resource_ids")
@JsonDeserialize(using = ArrayOrStringDeserializer.class)
private Set<String> resourceIds = Collections.emptySet();

@JsonProperty("authorized_grant_types")
@JsonDeserialize(using = ArrayOrStringDeserializer.class)
private Set<String> authorizedGrantTypes = Collections.emptySet();

@JsonProperty("redirect_uri")
@JsonDeserialize(using = ArrayOrStringDeserializer.class)
private Set<String> registeredRedirectUris;

private List<GrantedAuthority> authorities = Collections.emptyList();

@JsonProperty("access_token_validity")
private int accessTokenValiditySeconds = 0;

@JsonProperty("refresh_token_validity")
private int refreshTokenValiditySeconds = 0;

Expand Down Expand Up @@ -170,21 +184,48 @@ public void setRegisteredRedirectUri(Set<String> registeredRedirectUris) {

@SuppressWarnings("unused")
@JsonProperty("authorities")
private Collection<String> getAuthoritiesAsStrings() {
return AuthorityUtils.authorityListToSet(authorities);
private List<String> getAuthoritiesAsStrings() {
return new ArrayList<String>(AuthorityUtils.authorityListToSet(authorities));
}

@SuppressWarnings("unused")
@JsonProperty("authorities")
private void setAuthoritiesAsStrings(List<String> roles) {
this.authorities = AuthorityUtils.createAuthorityList(roles.toArray(new String[roles.size()]));
@JsonDeserialize(using = ArrayOrStringDeserializer.class)
private void setAuthoritiesAsStrings(Set<String> values) {
setAuthorities(AuthorityUtils.createAuthorityList(values.toArray(new String[values.size()])));
}

public static class ArrayOrStringDeserializer extends StdDeserializer<Set<String>> {

public ArrayOrStringDeserializer() {
super(Set.class);
}

@Override
public JavaType getValueType() {
return SimpleType.construct(String.class);
}

@Override
public Set<String> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException,
JsonProcessingException {
JsonToken token = jp.getCurrentToken();
if (token.isScalarValue()) {
String list = jp.getText();
list = list.replaceAll("\\s+", ",");
return new LinkedHashSet<String>(Arrays.asList(StringUtils.commaDelimitedListToStringArray(list)));
}
return jp.readValueAs(new TypeReference<Set<String>>() {
});
}
}

@JsonIgnore
public Collection<GrantedAuthority> getAuthorities() {
return authorities;
}

@JsonIgnore
public void setAuthorities(Collection<GrantedAuthority> authorities) {
this.authorities = new ArrayList<GrantedAuthority>(authorities);
}
Expand Down Expand Up @@ -281,4 +322,13 @@ else if (!scope.equals(other.scope))
return true;
}

@Override
public String toString() {
return "BaseClientDetails [clientId=" + clientId + ", clientSecret=" + clientSecret + ", scope=" + scope
+ ", resourceIds=" + resourceIds + ", authorizedGrantTypes=" + authorizedGrantTypes
+ ", registeredRedirectUris=" + registeredRedirectUris + ", authorities=" + authorities
+ ", accessTokenValiditySeconds=" + accessTokenValiditySeconds + ", refreshTokenValiditySeconds="
+ refreshTokenValiditySeconds + "]";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,17 @@ public void testJsonSerialize() throws Exception {
public void testJsonDeserialize() throws Exception {
String value = "{\"foo\":\"bar\",\"scope\":[\"bar\",\"foo\"],\"authorized_grant_types\":[\"authorization_code\"],\"access_token_validity\":0,\"authorities\":[\"ROLE_USER\"]}";
BaseClientDetails details = new ObjectMapper().readValue(value, BaseClientDetails.class);
// System.err.println(new ObjectMapper().writeValueAsString(details));
BaseClientDetails expected = new BaseClientDetails("", "foo,bar", "authorization_code", "ROLE_USER");
assertEquals(expected, details);
}

@Test
public void testJsonDeserializeWithArraysAsStrings() throws Exception {
// Collection values can be deserialized from space or comma-separated lists
String value = "{\"foo\":\"bar\",\"scope\":\"bar foo\",\"authorized_grant_types\":\"authorization_code\",\"access_token_validity\":0,\"authorities\":\"ROLE_USER,ROLE_ADMIN\"}";
BaseClientDetails details = new ObjectMapper().readValue(value, BaseClientDetails.class);
BaseClientDetails expected = new BaseClientDetails("", "foo,bar", "authorization_code", "ROLE_USER,ROLE_ADMIN");
assertEquals(expected, details);
}

}

0 comments on commit 68f1446

Please sign in to comment.