View Javadoc
1   /*
2    * The contents of this file are subject to the terms of the Common Development and
3    * Distribution License (the License). You may not use this file except in compliance with the
4    * License.
5    *
6    * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
7    * specific language governing permission and limitations under the License.
8    *
9    * When distributing Covered Software, include this CDDL Header Notice in each file and include
10   * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
11   * Header, with the fields enclosed by brackets [] replaced by your own identifying
12   * information: "Portions Copyrighted [year] [name of copyright owner]".
13   *
14   * Copyright 2013-2016 ForgeRock AS.
15   */
16  
17  package org.forgerock.json.jose.jwk;
18  
19  import java.io.IOException;
20  import java.util.List;
21  import java.util.Map;
22  
23  import org.forgerock.json.JsonException;
24  import org.forgerock.json.JsonValue;
25  import org.forgerock.json.jose.jwt.JWObject;
26  
27  import com.fasterxml.jackson.databind.ObjectMapper;
28  
29  /**
30   * The abstract base class for the 3 implementations of JWK.
31   */
32  public abstract class JWK extends JWObject {
33      /**
34       * The KeyType key.
35       */
36      protected static final String KTY = "kty";
37  
38      /**
39       * The KeyUse key.
40       */
41      protected static final String USE = "use";
42  
43      /**
44       * The Algorithm key.
45       */
46      protected static final String ALG = "alg";
47  
48      /**
49       * The KeyID key.
50       */
51      protected static final String KID = "kid";
52  
53      /**
54       * The X509 URL key.
55       */
56      protected static final String X5U = "x5u";
57  
58      /**
59       * The X509 thumbnail key.
60       */
61      protected static final String X5T = "x5t";
62  
63      /**
64       * The X509 chain key.
65       */
66      protected static final String X5C = "x5c";
67  
68      /**
69       * Creates a JWK given the basic parameters.
70       * @param kty the JWK key type
71       * @param use the JWK use
72       * @param alg the JWK algorithm
73       * @param kid the JWK key id
74       */
75      protected JWK(KeyType kty, KeyUse use, String alg, String kid) {
76          this(kty, use, alg, kid, null, null, null);
77      }
78  
79      /**
80       * Creates a JWK given the basic parameters.
81       * @param kty the JWK key type
82       * @param use the JWK use
83       * @param alg the JWK algorithm
84       * @param kid the JWK key id
85       * @param x5u the x509 url for the key
86       * @param x5t the x509 thumbnail for the key
87       * @param x5c the x509 chain as a list of Base64 encoded strings
88       */
89      protected JWK(KeyType kty, KeyUse use, String alg, String kid, String x5u, String x5t, List<String> x5c) {
90          super();
91          if (kty == null) {
92              new JsonException("kty is a required field");
93          }
94          put(KTY, kty.toString());
95          if (kid == null || kid.isEmpty()) {
96              new JsonException("kid is a required field");
97          }
98          put(KID, kid);
99          if (use != null) {
100             put(USE, use.toString());
101         }
102         if (alg != null && !alg.isEmpty()) {
103             put(ALG, alg);
104         }
105         if (x5c != null && !x5c.isEmpty()) {
106             put(X5C, x5c);
107         }
108         if (x5t != null && !x5t.isEmpty()) {
109             put(X5T, x5t);
110         }
111         if (x5u != null && !x5u.isEmpty()) {
112             put(X5U, x5u);
113         }
114     }
115 
116     /**
117      * Gets the kty parameter of the JWK.
118      * @return A KeyType for the JWK
119      */
120     public KeyType getKeyType() {
121         return KeyType.getKeyType(get(KTY).asString());
122     }
123 
124     /**
125      * Gets the use parameter of the JWK.
126      * @return A String representing the use parameter
127      */
128     public KeyUse getUse() {
129         return KeyUse.getKeyUse(get(USE).asString());
130     }
131 
132     /**
133      * Gets the alg parameter of the JWK.
134      * @return A String representing the alg parameter
135      */
136     public String getAlgorithm() {
137         return get(ALG).asString();
138     }
139 
140     /**
141      * Gets the kid parameter of the JWK.
142      * @return A String representing the kid parameter
143      */
144     public String getKeyId() {
145         return get(KID).asString();
146     }
147 
148     /**
149      * Prints the JWK Object as a json string.
150      * @return A String representing JWK
151      */
152     public String toJsonString() {
153         return toString();
154     }
155 
156     /**
157      * Parses a String into the proper JWK type.
158      *
159      * @param json The json String.
160      * @return A JWK object
161      * @throws org.forgerock.json.JsonException If there is a problem parsing the json String.
162      */
163     public static JWK parse(String json) {
164         JsonValue jwk = new JsonValue(toJsonValue(json));
165         return parse(jwk);
166     }
167 
168     /**
169      * Parses a JsonValue into the proper JWK type.
170      *
171      * @param jwk The JsonValue Object.
172      * @return A JWK object
173      * @throws org.forgerock.json.JsonException If there is a problem parsing the json String.
174      */
175     public static JWK parse(JsonValue jwk) {
176         KeyType kty = KeyType.getKeyType(jwk.get(KTY).asString());
177 
178         if (kty.equals(KeyType.RSA)) {
179             return RsaJWK.parse(jwk);
180         } else if (kty.equals(KeyType.OCT)) {
181             return OctJWK.parse(jwk);
182         } else if (kty.equals(KeyType.EC)) {
183             return EcJWK.parse(jwk);
184         } else {
185             throw new JsonException("Failed to parse json invalid kty parameter");
186         }
187     }
188 
189     /**
190      * Converts a String into a JsonValue.
191      *
192      * @param json The json String.
193      * @return A JsonValue object.
194      * @throws org.forgerock.json.JsonException If there is a problem parsing the json String.
195      */
196     protected static JsonValue toJsonValue(String json) {
197         ObjectMapper mapper = new ObjectMapper();
198         try {
199             return new JsonValue(mapper.readValue(json, Map.class));
200         } catch (IOException e) {
201             throw new JsonException("Failed to parse json", e);
202         }
203     }
204 
205     /**
206      * Gets the X509 URL.
207      * @return the url of the 509 cert header or null
208      */
209     public String getX509URL() {
210         return get(X5U).asString();
211     }
212 
213     /**
214      * Gets the X509 thumbnail.
215      * @return Base64url of the X509 thumbnail
216      */
217     public String getX509Thumbnail() {
218         return get(X5T).asString();
219     }
220 
221     /**
222      * Gets a List of X509 chain certs.
223      * @return X509 Cert Chain as list of encoded strings or null if none are available.
224      */
225     public List<String> getX509Chain() {
226         return get(X5C).asList(String.class);
227     }
228 }