Skip to content

Commit

Permalink
Refactor verification response into a JSON web key object.
Browse files Browse the repository at this point in the history
  • Loading branch information
fhanik committed Nov 17, 2016
1 parent 4aef986 commit c752a72
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 181 deletions.
Expand Up @@ -15,24 +15,32 @@


package org.cloudfoundry.identity.uaa.oauth.jwk; package org.cloudfoundry.identity.uaa.oauth.jwk;


import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;


import java.security.PublicKey;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;


public abstract class JsonWebKey { /**
* See https://tools.ietf.org/html/rfc7517
*/

@JsonDeserialize(using = JsonWebKeyDeserializer.class)
@JsonSerialize(using = JsonWebKeySerializer.class)
public class JsonWebKey {


enum KeyUse { public enum KeyUse {
sig, sig,
enc enc
} }


enum KeyType { public enum KeyType {
RSA RSA,
MAC
} }


enum KeyOperation { public enum KeyOperation {
sign, sign,
verify, verify,
encrypt, encrypt,
Expand All @@ -45,7 +53,7 @@ enum KeyOperation {


private final Map<String, Object> json; private final Map<String, Object> json;


protected JsonWebKey(Map<String, Object> json) { public JsonWebKey(Map<String, Object> json) {
if (json.get("kty")==null) { if (json.get("kty")==null) {
throw new IllegalArgumentException("kty field is required"); throw new IllegalArgumentException("kty field is required");
} }
Expand Down Expand Up @@ -91,6 +99,12 @@ public int hashCode() {
} }
} }


abstract PublicKey getPublicKey(); //helper methods
public String getAlgorithm() {
return (String) getKeyProperties().get("alg");
}


public String getValue() {
return (String) getKeyProperties().get("value");
}
} }
Expand Up @@ -21,31 +21,22 @@
import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.cloudfoundry.identity.uaa.util.JsonUtils;


import java.io.IOException; import java.io.IOException;
import java.util.LinkedHashSet;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;

public class KeySetDeserializer extends JsonDeserializer<KeySet> {


/**
* See https://tools.ietf.org/html/rfc7517
*/
public class JsonWebKeyDeserializer extends JsonDeserializer<JsonWebKey> {
@Override @Override
public KeySet deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { public JsonWebKey deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonNode node = JsonUtils.readTree(p); JsonNode node = JsonUtils.readTree(p);
ArrayNode keys = (ArrayNode) node.get("keys"); Map<String, Object> map = JsonUtils.getNodeAsMap(node);
if (keys==null) { if (map.get("kty")==null) {
throw new JsonParseException(p, "keys attribute cannot be null"); throw new JsonParseException(p, "kty is a required attribute on a JsonWebKey");
} }
LinkedHashSet<JsonWebKey> result = new LinkedHashSet<>(); return new JsonWebKey(map);
for (int i=0; i<keys.size(); i++) {
Map<String, Object> map = JsonUtils.getNodeAsMap(keys.get(i));
RsaJsonWebKey key = new RsaJsonWebKey(map);
result.remove(key);
result.add(key);
}
return new KeySet(result.stream().collect(Collectors.toList()));
} }

} }
Expand Up @@ -21,16 +21,20 @@
import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.SerializerProvider;


import java.io.IOException; import java.io.IOException;
import java.util.Map;


public class KeySetSerializer extends JsonSerializer<KeySet> { /**
* See https://tools.ietf.org/html/rfc7517
*/

public class JsonWebKeySerializer extends JsonSerializer<JsonWebKey> {
@Override @Override
public void serialize(KeySet value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException { public void serialize(JsonWebKey value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
gen.writeStartObject(); gen.writeStartObject();
gen.writeArrayFieldStart("keys"); for (Map.Entry<String, Object> entry : value.getKeyProperties().entrySet()) {
for (JsonWebKey key : value.getKeys()) { gen.writeFieldName(entry.getKey());
gen.writeObject(key.getKeyProperties()); gen.writeObject(entry.getValue());
} }
gen.writeEndArray();
gen.writeEndObject(); gen.writeEndObject();
} }
} }
Expand Up @@ -15,23 +15,32 @@


package org.cloudfoundry.identity.uaa.oauth.jwk; package org.cloudfoundry.identity.uaa.oauth.jwk;


import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;


import java.util.Collections; import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Set;


@JsonDeserialize(using = KeySetDeserializer.class) /**
@JsonSerialize(using = KeySetSerializer.class) * See https://tools.ietf.org/html/rfc7517
public class KeySet { */
public class JsonWebKeySet<T extends JsonWebKey> {


private final List<JsonWebKey> keys; private final List<T> keys;


public KeySet(List<JsonWebKey> keys) { public JsonWebKeySet(@JsonProperty("keys") List<T> keys) {
this.keys = Collections.unmodifiableList(keys); Set<T> set = new LinkedHashSet<>();
//rules for how to override duplicates
for (T t : keys) {
set.remove(t);
set.add(t);
}
this.keys = new LinkedList(set);
} }


public List<JsonWebKey> getKeys() { public List<T> getKeys() {
return keys; return Collections.unmodifiableList(keys);
} }
} }
Expand Up @@ -14,95 +14,55 @@


package org.cloudfoundry.identity.uaa.oauth.token; package org.cloudfoundry.identity.uaa.oauth.token;


import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude; import org.cloudfoundry.identity.uaa.oauth.jwk.JsonWebKey;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;


import java.util.Map;

@Deprecated
/** /**
* Created by pivotal on 11/18/15. * Use {@link JsonWebKey}
*/ */
@JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE) public class VerificationKeyResponse extends JsonWebKey{
public class VerificationKeyResponse {

@JsonProperty("kid")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String kid;

@JsonProperty("alg")
private String algorithm;

@JsonProperty("value")
private String key;

@JsonProperty("kty")
private String type;

@JsonProperty("use")
private String use;


@JsonProperty("n")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String modulus;


@JsonProperty("e") public VerificationKeyResponse(Map<String, Object> json) {
@JsonInclude(JsonInclude.Include.NON_NULL) super(json);
private String exponent;

public String getId() {
return kid;
} }


public void setId(String kid) { @JsonIgnore
this.kid = kid; public String getId() {
} return getKid();

public void setAlgorithm(String algorithm) {
this.algorithm = algorithm;
} }


@JsonIgnore
public String getAlgorithm() { public String getAlgorithm() {
return algorithm; return (String) getKeyProperties().get("alg");
}

public void setKey(String key) {
this.key = key;
} }


@JsonIgnore
public String getKey() { public String getKey() {
return key; return (String) getKeyProperties().get("value");
}

public void setType(String type) {
this.type = type;
} }


@JsonIgnore
public String getType() { public String getType() {
return type; return getKty().name();
}

public void setUse(String use) {
this.use = use;
}

public String getUse() {
return use;
} }


public void setModulus(String modulus) { @JsonIgnore
this.modulus = modulus; public String getKeyUse() {
return getUse().name();
} }


@JsonIgnore
public String getModulus() { public String getModulus() {
return modulus; return (String) getKeyProperties().get("n");
}

public void setExponent(String exponent) {
this.exponent = exponent;
} }


@JsonIgnore
public String getExponent() { public String getExponent() {
return exponent; return (String) getKeyProperties().get("e");
} }


} }
Expand Down
@@ -1,35 +1,30 @@
/* /*
* ****************************************************************************** * ****************************************************************************
* Cloud Foundry Copyright (c) [2009-2015] Pivotal Software, Inc. All Rights Reserved. * Cloud Foundry
* Copyright (c) [2009-2016] Pivotal Software, Inc. All Rights Reserved.
* *
* This product is licensed to you under the Apache License, Version 2.0 (the "License"). * This product is licensed to you under the Apache License, Version 2.0 (the "License").
* You may not use this product except in compliance with the License. * You may not use this product except in compliance with the License.
* *
* This product includes a number of subcomponents with * This product includes a number of subcomponents with
* separate copyright notices and license terms. Your use of these * separate copyright notices and license terms. Your use of these
* subcomponents is subject to the terms and conditions of the * subcomponents is subject to the terms and conditions of the
* subcomponent's license, as noted in the LICENSE file. * subcomponent's license, as noted in the LICENSE file.
* ****************************************************************************** * ****************************************************************************
*/ */


package org.cloudfoundry.identity.uaa.oauth.token; package org.cloudfoundry.identity.uaa.oauth.token;


import com.fasterxml.jackson.annotation.JsonAutoDetect; import org.cloudfoundry.identity.uaa.oauth.jwk.JsonWebKeySet;


import java.util.List; import java.util.List;


@Deprecated
/** /**
* Created by pivotal on 11/18/15. * Use {@link JsonWebKeySet}
*/ */
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE) public class VerificationKeysListResponse extends JsonWebKeySet<VerificationKeyResponse> {
public class VerificationKeysListResponse { public VerificationKeysListResponse(List<VerificationKeyResponse> keys) {
private List<VerificationKeyResponse> keys; super(keys);

public List<VerificationKeyResponse> getKeys() {
return keys;
}

public void setKeys(List<VerificationKeyResponse> keys) {
this.keys = keys;
} }
} }

0 comments on commit c752a72

Please sign in to comment.