001/* 002 * oauth2-oidc-sdk 003 * 004 * Copyright 2012-2021, Connect2id Ltd and contributors. 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 007 * this file except in compliance with the License. You may obtain a copy of the 008 * License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software distributed 013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 015 * specific language governing permissions and limitations under the License. 016 */ 017 018package com.nimbusds.openid.connect.sdk.federation.entities; 019 020 021import com.nimbusds.oauth2.sdk.ParseException; 022import com.nimbusds.oauth2.sdk.as.AuthorizationServerMetadata; 023import com.nimbusds.oauth2.sdk.client.ClientMetadata; 024import com.nimbusds.oauth2.sdk.util.JSONArrayUtils; 025import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 026import com.nimbusds.openid.connect.sdk.claims.CommonClaimsSet; 027import com.nimbusds.openid.connect.sdk.federation.trust.marks.TrustMarkEntry; 028import com.nimbusds.openid.connect.sdk.federation.trust.marks.TrustMarkIssuerMetadata; 029import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata; 030import com.nimbusds.openid.connect.sdk.rp.OIDCClientMetadata; 031import net.minidev.json.JSONArray; 032import net.minidev.json.JSONObject; 033 034import java.util.Date; 035import java.util.LinkedList; 036import java.util.List; 037 038 039/** 040 * Common federation claims set. 041 */ 042public abstract class CommonFederationClaimsSet extends CommonClaimsSet { 043 044 045 /** 046 * The expiration time claim name. 047 */ 048 public static final String EXP_CLAIM_NAME = "exp"; 049 050 051 /** 052 * The metadata claim name. 053 */ 054 public static final String METADATA_CLAIM_NAME = "metadata"; 055 056 057 /** 058 * The trust marks claim name. 059 */ 060 public static final String TRUST_MARKS_CLAIM_NAME = "trust_marks"; 061 062 063 /** 064 * Creates a new empty common federation claims set. 065 */ 066 protected CommonFederationClaimsSet() { 067 super(); 068 } 069 070 071 /** 072 * Creates a new common federation claims set from the specified JSON 073 * object. 074 * 075 * @param jsonObject The JSON object. Must not be {@code null}. 076 */ 077 protected CommonFederationClaimsSet(final JSONObject jsonObject) { 078 super(jsonObject); 079 } 080 081 082 /** 083 * Validates this claims set for having all minimum required claims. 084 * 085 * @throws ParseException If the validation failed and a required claim 086 * is missing. 087 */ 088 protected void validateRequiredClaimsPresence() 089 throws ParseException { 090 091 if (getIssuer() == null) { 092 throw new ParseException("Missing iss (issuer) claim"); 093 } 094 095 EntityID.parse(getIssuer()); // ensure URI 096 097 if (getSubject() == null) { 098 throw new ParseException("Missing sub (subject) claim"); 099 } 100 101 EntityID.parse(getSubject()); // ensure URI 102 103 if (getIssueTime() == null) { 104 throw new ParseException("Missing iat (issued-at) claim"); 105 } 106 107 if (getExpirationTime() == null) { 108 throw new ParseException("Missing exp (expiration) claim"); 109 } 110 } 111 112 113 /** 114 * Returns the issuer as entity ID. Corresponds to the {@code iss} 115 * claim. 116 * 117 * @return The issuer as entity ID. 118 */ 119 public EntityID getIssuerEntityID() { 120 121 return new EntityID(getIssuer().getValue()); 122 } 123 124 125 /** 126 * Returns the subject as entity ID. Corresponds to the {@code iss} 127 * claim. 128 * 129 * @return The subject as entity ID. 130 */ 131 public EntityID getSubjectEntityID() { 132 133 return new EntityID(getSubject().getValue()); 134 } 135 136 137 /** 138 * Gets the entity statement expiration time. Corresponds to the 139 * {@code exp} claim. 140 * 141 * @return The expiration time, {@code null} if not specified or 142 * parsing failed. 143 */ 144 public Date getExpirationTime() { 145 146 return getDateClaim(EXP_CLAIM_NAME); 147 } 148 149 150 /** 151 * Gets the metadata for the specified entity type. Use a typed getter, 152 * such as {@link #getRPMetadata}, when available. Corresponds to the 153 * {@code metadata} claim. 154 * 155 * @param type The entity type. Must not be {@code null}. 156 * 157 * @return The metadata, {@code null} if not specified or if parsing 158 * failed. 159 */ 160 public JSONObject getMetadata(final EntityType type) { 161 162 JSONObject o = getJSONObjectClaim(METADATA_CLAIM_NAME); 163 164 if (o == null) { 165 return null; 166 } 167 168 try { 169 return JSONObjectUtils.getJSONObject(o, type.getValue(), null); 170 } catch (ParseException e) { 171 return null; 172 } 173 } 174 175 176 /** 177 * Sets the metadata for the specified entity type. Use a typed setter, 178 * such as {@link #setRPMetadata}, when available. Corresponds to the 179 * {@code metadata} claim. 180 * 181 * @param type The type. Must not be {@code null}. 182 * @param metadata The metadata, {@code null} if not specified. 183 */ 184 public void setMetadata(final EntityType type, final JSONObject metadata) { 185 186 JSONObject o = getJSONObjectClaim(METADATA_CLAIM_NAME); 187 188 if (o == null) { 189 if (metadata == null) { 190 return; // nothing to clear 191 } 192 o = new JSONObject(); 193 } 194 195 o.put(type.getValue(), metadata); 196 197 setClaim(METADATA_CLAIM_NAME, o); 198 } 199 200 201 /** 202 * Gets the OpenID relying party metadata if present for this entity. 203 * Corresponds to the {@code metadata.openid_relying_party} claim. 204 * 205 * @return The RP metadata, {@code null} if not specified or if parsing 206 * failed. 207 */ 208 public OIDCClientMetadata getRPMetadata() { 209 210 JSONObject o = getMetadata(EntityType.OPENID_RELYING_PARTY); 211 212 if (o == null) { 213 return null; 214 } 215 216 try { 217 return OIDCClientMetadata.parse(o); 218 } catch (ParseException e) { 219 return null; 220 } 221 } 222 223 224 /** 225 * Sets the OpenID relying party metadata if present for this entity. 226 * Corresponds to the {@code metadata.openid_relying_party} claim. 227 * 228 * @param rpMetadata The RP metadata, {@code null} if not specified. 229 */ 230 public void setRPMetadata(final OIDCClientMetadata rpMetadata) { 231 232 JSONObject o = rpMetadata != null ? rpMetadata.toJSONObject() : null; 233 setMetadata(EntityType.OPENID_RELYING_PARTY, o); 234 } 235 236 237 /** 238 * Gets the OpenID provider metadata if present for this entity. 239 * Corresponds to the {@code metadata.openid_provider} claim. 240 * 241 * @return The OP metadata, {@code null} if not specified or if parsing 242 * failed. 243 */ 244 public OIDCProviderMetadata getOPMetadata() { 245 246 JSONObject o = getMetadata(EntityType.OPENID_PROVIDER); 247 248 if (o == null) { 249 return null; 250 } 251 252 try { 253 return OIDCProviderMetadata.parse(o); 254 } catch (ParseException e) { 255 return null; 256 } 257 } 258 259 260 /** 261 * Gets the OpenID provider metadata if present for this entity. 262 * Corresponds to the {@code metadata.openid_provider} claim. 263 * 264 * @param opMetadata The OP metadata, {@code null} if not specified. 265 */ 266 public void setOPMetadata(final OIDCProviderMetadata opMetadata) { 267 268 JSONObject o = opMetadata != null ? opMetadata.toJSONObject() : null; 269 setMetadata(EntityType.OPENID_PROVIDER, o); 270 } 271 272 273 /** 274 * Gets the OAuth 2.0 client metadata if present for this entity. 275 * Corresponds to the {@code metadata.oauth_client} claim. 276 * 277 * @return The client metadata, {@code null} if not specified or if 278 * parsing failed. 279 */ 280 public ClientMetadata getOAuthClientMetadata() { 281 282 JSONObject o = getMetadata(EntityType.OAUTH_CLIENT); 283 284 if (o == null) { 285 return null; 286 } 287 288 try { 289 return ClientMetadata.parse(o); 290 } catch (ParseException e) { 291 return null; 292 } 293 } 294 295 296 /** 297 * Sets the OAuth 2.0 client metadata if present for this entity. 298 * Corresponds to the {@code metadata.oauth_client} claim. 299 * 300 * @param clientMetadata The client metadata, {@code null} if not 301 * specified. 302 */ 303 public void setOAuthClientMetadata(final ClientMetadata clientMetadata) { 304 305 JSONObject o = clientMetadata != null ? clientMetadata.toJSONObject() : null; 306 setMetadata(EntityType.OAUTH_CLIENT, o); 307 } 308 309 310 /** 311 * Gets the OAuth 2.0 authorisation server metadata if present for this 312 * entity. Corresponds to the 313 * {@code metadata.oauth_authorization_server} claim. 314 * 315 * @return The AS metadata, {@code null} if not specified or if parsing 316 * failed. 317 */ 318 public AuthorizationServerMetadata getASMetadata() { 319 320 JSONObject o = getMetadata(EntityType.OAUTH_AUTHORIZATION_SERVER); 321 322 if (o == null) { 323 return null; 324 } 325 326 try { 327 return AuthorizationServerMetadata.parse(o); 328 } catch (ParseException e) { 329 return null; 330 } 331 } 332 333 334 /** 335 * Sets the OAuth 2.0 authorisation server metadata if present for this 336 * entity. Corresponds to the 337 * {@code metadata.oauth_authorization_server} claim. 338 * 339 * @param asMetadata The AS metadata, {@code null} if not specified. 340 */ 341 public void setASMetadata(final AuthorizationServerMetadata asMetadata) { 342 343 JSONObject o = asMetadata != null ? asMetadata.toJSONObject() : null; 344 setMetadata(EntityType.OAUTH_AUTHORIZATION_SERVER, o); 345 } 346 347 348 /** 349 * Gets the federation entity metadata if present for this entity. 350 * Corresponds to the {@code metadata.federation_entity} claim. 351 * 352 * @return The federation entity metadata, {@code null} if not 353 * specified or if parsing failed. 354 */ 355 public FederationEntityMetadata getFederationEntityMetadata() { 356 357 JSONObject o = getMetadata(EntityType.FEDERATION_ENTITY); 358 359 if (o == null) { 360 return null; 361 } 362 363 try { 364 return FederationEntityMetadata.parse(o); 365 } catch (ParseException e) { 366 return null; 367 } 368 } 369 370 371 /** 372 * Sets the federation entity metadata if present for this entity. 373 * Corresponds to the {@code metadata.federation_entity} claim. 374 * 375 * @param entityMetadata The federation entity metadata, {@code null} 376 * if not specified. 377 */ 378 public void setFederationEntityMetadata(final FederationEntityMetadata entityMetadata) { 379 380 JSONObject o = entityMetadata != null ? entityMetadata.toJSONObject() : null; 381 setMetadata(EntityType.FEDERATION_ENTITY, o); 382 } 383 384 385 /** 386 * Gets the trust mark issuer metadata if present for this entity. 387 * Corresponds to the {@code metadata.trust_mark_issuer} claim. 388 * 389 * @return The trust mark issuer metadata, {@code null} if not 390 * specified or if parsing failed. 391 */ 392 @Deprecated 393 public TrustMarkIssuerMetadata getTrustMarkIssuerMetadata() { 394 395 JSONObject o = getMetadata(EntityType.TRUST_MARK_ISSUER); 396 397 if (o == null) { 398 return null; 399 } 400 401 try { 402 return TrustMarkIssuerMetadata.parse(o); 403 } catch (ParseException e) { 404 return null; 405 } 406 } 407 408 409 /** 410 * Gets the trust marks. Corresponds to the {@code trust_marks} claim. 411 * 412 * @return The trust marks, {@code null} if not specified or parsing 413 * failed. 414 */ 415 public List<TrustMarkEntry> getTrustMarks() { 416 417 JSONArray array = getJSONArrayClaim(TRUST_MARKS_CLAIM_NAME); 418 419 if (array == null) { 420 return null; 421 } 422 423 List<JSONObject> jsonObjects; 424 try { 425 jsonObjects = JSONArrayUtils.toJSONObjectList(array); 426 } catch (ParseException e) { 427 return null; 428 } 429 430 List<TrustMarkEntry> marks = new LinkedList<>(); 431 432 for (JSONObject o: jsonObjects) { 433 try { 434 marks.add(TrustMarkEntry.parse(o)); 435 } catch (ParseException e) { 436 return null; 437 } 438 } 439 440 return marks; 441 } 442 443 444 /** 445 * Sets the trust marks. Corresponds to the {@code trust_marks} claim. 446 * 447 * @param marks The trust marks, {@code null} if not specified. 448 */ 449 public void setTrustMarks(final List<TrustMarkEntry> marks) { 450 451 if (marks != null) { 452 JSONArray array = new JSONArray(); 453 for (TrustMarkEntry en: marks) { 454 array.add(en.toJSONObject()); 455 } 456 setClaim(TRUST_MARKS_CLAIM_NAME, array); 457 } else { 458 setClaim(TRUST_MARKS_CLAIM_NAME, null); 459 } 460 } 461}