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}