001/*******************************************************************************
002 * Copyright 2014 The MITRE Corporation
003 *   and the MIT Kerberos and Internet Trust Consortium
004 * 
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 * 
009 *   http://www.apache.org/licenses/LICENSE-2.0
010 * 
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 ******************************************************************************/
017/**
018 * 
019 */
020package org.mitre.openid.connect;
021
022
023import static org.mitre.discovery.util.JsonUtils.getAsArray;
024import static org.mitre.discovery.util.JsonUtils.getAsDate;
025import static org.mitre.discovery.util.JsonUtils.getAsJweAlgorithm;
026import static org.mitre.discovery.util.JsonUtils.getAsJweEncryptionMethod;
027import static org.mitre.discovery.util.JsonUtils.getAsJwsAlgorithm;
028import static org.mitre.discovery.util.JsonUtils.getAsString;
029import static org.mitre.discovery.util.JsonUtils.getAsStringSet;
030
031import org.mitre.oauth2.model.ClientDetailsEntity;
032import org.mitre.oauth2.model.ClientDetailsEntity.AppType;
033import org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod;
034import org.mitre.oauth2.model.ClientDetailsEntity.SubjectType;
035import org.mitre.oauth2.model.RegisteredClient;
036
037import com.google.common.base.Joiner;
038import com.google.common.base.Splitter;
039import com.google.common.collect.Sets;
040import com.google.gson.JsonElement;
041import com.google.gson.JsonObject;
042import com.google.gson.JsonParser;
043
044/**
045 * @author jricher
046 *
047 */
048public class ClientDetailsEntityJsonProcessor {
049
050        private static JsonParser parser = new JsonParser();
051
052        /**
053         * 
054         * Create an unbound ClientDetailsEntity from the given JSON string.
055         * 
056         * @param jsonString
057         * @return the entity if successful, null otherwise
058         */
059        public static ClientDetailsEntity parse(String jsonString) {
060                JsonElement jsonEl = parser.parse(jsonString);
061                return parse(jsonEl);
062        }
063        
064        public static ClientDetailsEntity parse(JsonElement jsonEl) {
065                if (jsonEl.isJsonObject()) {
066
067                        JsonObject o = jsonEl.getAsJsonObject();
068                        ClientDetailsEntity c = new ClientDetailsEntity();
069
070                        // TODO: make these field names into constants
071
072                        // these two fields should only be sent in the update request, and MUST match existing values
073                        c.setClientId(getAsString(o, "client_id"));
074                        c.setClientSecret(getAsString(o, "client_secret"));
075
076                        // OAuth DynReg
077                        c.setRedirectUris(getAsStringSet(o, "redirect_uris"));
078                        c.setClientName(getAsString(o, "client_name"));
079                        c.setClientUri(getAsString(o, "client_uri"));
080                        c.setLogoUri(getAsString(o, "logo_uri"));
081                        c.setContacts(getAsStringSet(o, "contacts"));
082                        c.setTosUri(getAsString(o, "tos_uri"));
083
084                        String authMethod = getAsString(o, "token_endpoint_auth_method");
085                        if (authMethod != null) {
086                                c.setTokenEndpointAuthMethod(AuthMethod.getByValue(authMethod));
087                        }
088
089                        // scope is a space-separated string
090                        String scope = getAsString(o, "scope");
091                        if (scope != null) {
092                                c.setScope(Sets.newHashSet(Splitter.on(" ").split(scope)));
093                        }
094
095                        c.setGrantTypes(getAsStringSet(o, "grant_types"));
096                        c.setResponseTypes(getAsStringSet(o, "response_types"));
097                        c.setPolicyUri(getAsString(o, "policy_uri"));
098                        c.setJwksUri(getAsString(o, "jwks_uri"));
099
100
101                        // OIDC Additions
102                        String appType = getAsString(o, "application_type");
103                        if (appType != null) {
104                                c.setApplicationType(AppType.getByValue(appType));
105                        }
106
107                        c.setSectorIdentifierUri(getAsString(o, "sector_identifier_uri"));
108
109                        String subjectType = getAsString(o, "subject_type");
110                        if (subjectType != null) {
111                                c.setSubjectType(SubjectType.getByValue(subjectType));
112                        }
113
114                        c.setRequestObjectSigningAlg(getAsJwsAlgorithm(o, "request_object_signing_alg"));
115
116                        c.setUserInfoSignedResponseAlg(getAsJwsAlgorithm(o, "userinfo_signed_response_alg"));
117                        c.setUserInfoEncryptedResponseAlg(getAsJweAlgorithm(o, "userinfo_encrypted_response_alg"));
118                        c.setUserInfoEncryptedResponseEnc(getAsJweEncryptionMethod(o, "userinfo_encrypted_response_enc"));
119
120                        c.setIdTokenSignedResponseAlg(getAsJwsAlgorithm(o, "id_token_signed_response_alg"));
121                        c.setIdTokenEncryptedResponseAlg(getAsJweAlgorithm(o, "id_token_encrypted_response_alg"));
122                        c.setIdTokenEncryptedResponseEnc(getAsJweEncryptionMethod(o, "id_token_encrypted_response_enc"));
123
124                        c.setTokenEndpointAuthSigningAlg(getAsJwsAlgorithm(o, "token_endpoint_auth_signing_alg"));
125
126                        if (o.has("default_max_age")) {
127                                if (o.get("default_max_age").isJsonPrimitive()) {
128                                        c.setDefaultMaxAge(o.get("default_max_age").getAsInt());
129                                }
130                        }
131
132                        if (o.has("require_auth_time")) {
133                                if (o.get("require_auth_time").isJsonPrimitive()) {
134                                        c.setRequireAuthTime(o.get("require_auth_time").getAsBoolean());
135                                }
136                        }
137
138                        c.setDefaultACRvalues(getAsStringSet(o, "default_acr_values"));
139                        c.setInitiateLoginUri(getAsString(o, "initiate_login_uri"));
140                        c.setPostLogoutRedirectUri(getAsString(o, "post_logout_redirect_uri"));
141                        c.setRequestUris(getAsStringSet(o, "request_uris"));
142
143                        return c;
144                } else {
145                        return null;
146                }
147        }
148
149        /**
150         * Parse the JSON as a RegisteredClient (useful in the dynamic client filter)
151         */
152        public static RegisteredClient parseRegistered(String jsonString) {
153
154
155                JsonElement jsonEl = parser.parse(jsonString);
156                return parseRegistered(jsonEl);
157        }
158        
159        public static RegisteredClient parseRegistered(JsonElement jsonEl) {
160                if (jsonEl.isJsonObject()) {
161
162                        JsonObject o = jsonEl.getAsJsonObject();
163                        ClientDetailsEntity c = parse(jsonEl);
164
165                        RegisteredClient rc = new RegisteredClient(c);
166                        // get any fields from the registration
167                        rc.setRegistrationAccessToken(getAsString(o, "registration_access_token"));
168                        rc.setRegistrationClientUri(getAsString(o, "registration_client_uri"));
169                        rc.setClientIdIssuedAt(getAsDate(o, "client_id_issued_at"));
170                        rc.setClientSecretExpiresAt(getAsDate(o, "client_secret_expires_at"));
171
172                        return rc;
173                } else {
174                        return null;
175                }
176        }
177
178        /**
179         * @param c
180         * @param token
181         * @param registrationUri
182         * @return
183         */
184        public static JsonObject serialize(RegisteredClient c) {
185                JsonObject o = new JsonObject();
186
187                o.addProperty("client_id", c.getClientId());
188                if (c.getClientSecret() != null) {
189                        o.addProperty("client_secret", c.getClientSecret());
190
191                        if (c.getClientSecretExpiresAt() == null) {
192                                o.addProperty("client_secret_expires_at", 0); // TODO: do we want to let secrets expire?
193                        } else {
194                                o.addProperty("client_secret_expires_at", c.getClientSecretExpiresAt().getTime() / 1000L);
195                        }
196                }
197
198                if (c.getClientIdIssuedAt() != null) {
199                        o.addProperty("client_id_issued_at", c.getClientIdIssuedAt().getTime() / 1000L);
200                } else if (c.getCreatedAt() != null) {
201                        o.addProperty("client_id_issued_at", c.getCreatedAt().getTime() / 1000L);
202                }
203                if (c.getRegistrationAccessToken() != null) {
204                        o.addProperty("registration_access_token", c.getRegistrationAccessToken());
205                }
206
207                if (c.getRegistrationClientUri() != null) {
208                        o.addProperty("registration_client_uri", c.getRegistrationClientUri());
209                }
210
211
212                // add in all other client properties
213
214                // OAuth DynReg
215                o.add("redirect_uris", getAsArray(c.getRedirectUris()));
216                o.addProperty("client_name", c.getClientName());
217                o.addProperty("client_uri", c.getClientUri());
218                o.addProperty("logo_uri", c.getLogoUri());
219                o.add("contacts", getAsArray(c.getContacts()));
220                o.addProperty("tos_uri", c.getTosUri());
221                o.addProperty("token_endpoint_auth_method", c.getTokenEndpointAuthMethod() != null ? c.getTokenEndpointAuthMethod().getValue() : null);
222                o.addProperty("scope", c.getScope() != null ? Joiner.on(" ").join(c.getScope()) : null);
223                o.add("grant_types", getAsArray(c.getGrantTypes()));
224                o.add("response_types", getAsArray(c.getResponseTypes()));
225                o.addProperty("policy_uri", c.getPolicyUri());
226                o.addProperty("jwks_uri", c.getJwksUri());
227
228                // OIDC Registration
229                o.addProperty("application_type", c.getApplicationType() != null ? c.getApplicationType().getValue() : null);
230                o.addProperty("sector_identifier_uri", c.getSectorIdentifierUri());
231                o.addProperty("subject_type", c.getSubjectType() != null ? c.getSubjectType().getValue() : null);
232                o.addProperty("request_object_signing_alg", c.getRequestObjectSigningAlg() != null ? c.getRequestObjectSigningAlg().getName() : null);
233                o.addProperty("userinfo_signed_response_alg", c.getUserInfoSignedResponseAlg() != null ? c.getUserInfoSignedResponseAlg().getName() : null);
234                o.addProperty("userinfo_encrypted_response_alg", c.getUserInfoEncryptedResponseAlg() != null ? c.getUserInfoEncryptedResponseAlg().getName() : null);
235                o.addProperty("userinfo_encrypted_response_enc", c.getUserInfoEncryptedResponseEnc() != null ? c.getUserInfoEncryptedResponseEnc().getName() : null);
236                o.addProperty("id_token_signed_response_alg", c.getIdTokenSignedResponseAlg() != null ? c.getIdTokenSignedResponseAlg().getName() : null);
237                o.addProperty("id_token_encrypted_response_alg", c.getIdTokenEncryptedResponseAlg() != null ? c.getIdTokenEncryptedResponseAlg().getName() : null);
238                o.addProperty("id_token_encrypted_response_enc", c.getIdTokenEncryptedResponseEnc() != null ? c.getIdTokenEncryptedResponseEnc().getName() : null);
239                o.addProperty("token_endpoint_auth_signing_alg", c.getTokenEndpointAuthSigningAlg() != null ? c.getTokenEndpointAuthSigningAlg().getName() : null);
240                o.addProperty("default_max_age", c.getDefaultMaxAge());
241                o.addProperty("require_auth_time", c.getRequireAuthTime());
242                o.add("default_acr_values", getAsArray(c.getDefaultACRvalues()));
243                o.addProperty("initiate_login_uri", c.getInitiateLoginUri());
244                o.addProperty("post_logout_redirect_uri", c.getPostLogoutRedirectUri());
245                o.add("request_uris", getAsArray(c.getRequestUris()));
246                return o;
247        }
248
249
250}