001/* 002 * oauth2-oidc-sdk 003 * 004 * Copyright 2012-2020, 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; 019 020 021import java.util.*; 022 023import net.jcip.annotations.Immutable; 024import net.minidev.json.JSONArray; 025import net.minidev.json.JSONAware; 026import net.minidev.json.JSONObject; 027 028import com.nimbusds.oauth2.sdk.ParseException; 029import com.nimbusds.oauth2.sdk.ResponseType; 030import com.nimbusds.oauth2.sdk.Scope; 031import com.nimbusds.oauth2.sdk.util.JSONArrayUtils; 032import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 033import com.nimbusds.openid.connect.sdk.assurance.claims.VerifiedClaimsSetRequest; 034import com.nimbusds.openid.connect.sdk.claims.ClaimRequirement; 035import com.nimbusds.openid.connect.sdk.claims.ClaimsSetRequest; 036 037 038/** 039 * Specifies individual OpenID claims to return from the UserInfo endpoint and 040 * / or in the ID Token. Replaces the deprecated {@link ClaimsRequest} class. 041 * 042 * <p>Example: 043 * 044 * <pre> 045 * { 046 * "userinfo": 047 * { 048 * "given_name": {"essential": true}, 049 * "nickname": null, 050 * "email": {"essential": true}, 051 * "email_verified": {"essential": true}, 052 * "picture": null, 053 * "http://example.info/claims/groups": null 054 * }, 055 * "id_token": 056 * { 057 * "auth_time": {"essential": true}, 058 * "acr": {"values": ["urn:mace:incommon:iap:silver"] } 059 * } 060 * } 061 * </pre> 062 * 063 * <p>Related specifications: 064 * 065 * <ul> 066 * <li>OpenID Connect Core 1.0, section 5.5. 067 * <li>OpenID Connect for Identity Assurance 1.0. 068 * </ul> 069 */ 070@Immutable 071public class OIDCClaimsRequest implements JSONAware { 072 073 074 /** 075 * Claims requested in the ID token, {@code null} if not specified. 076 */ 077 private final ClaimsSetRequest idToken; 078 079 080 /** 081 * Claims requested at the UserInfo endpoint, {@code null} if not 082 * specified. 083 */ 084 private final ClaimsSetRequest userInfo; 085 086 087 /** 088 * Verified claims requested in the ID token, empty list if not 089 * specified. 090 */ 091 private final List<VerifiedClaimsSetRequest> idTokenVerified; 092 093 094 /** 095 * Verified claims requested at the UserInfo endpoint, empty list if 096 * not specified. 097 */ 098 private final List<VerifiedClaimsSetRequest> userInfoVerified; 099 100 101 /** 102 * Creates a new empty OpenID claims request. 103 */ 104 public OIDCClaimsRequest() { 105 this(null, null, Collections.<VerifiedClaimsSetRequest>emptyList(), Collections.<VerifiedClaimsSetRequest>emptyList()); 106 } 107 108 109 private OIDCClaimsRequest(final ClaimsSetRequest idToken, 110 final ClaimsSetRequest userInfo, 111 final List<VerifiedClaimsSetRequest> idTokenVerified, 112 final List<VerifiedClaimsSetRequest> userInfoVerified) { 113 114 this.idToken = idToken; 115 116 this.userInfo = userInfo; 117 118 if (idTokenVerified == null) { 119 throw new IllegalArgumentException("The ID token verified claims set request list must not be null"); 120 } 121 this.idTokenVerified = Collections.unmodifiableList(idTokenVerified); 122 123 if (userInfoVerified == null) { 124 throw new IllegalArgumentException("The UserInfo verified claims set request list must not be null"); 125 } 126 this.userInfoVerified = Collections.unmodifiableList(userInfoVerified); 127 } 128 129 130 /** 131 * Adds the entries from the specified other OpenID claims request. 132 * 133 * @param other The other OpenID claims request. If {@code null} no 134 * claims request entries will be added to this claims 135 * request. 136 * 137 * @return The updated OpenID claims request. 138 */ 139 public OIDCClaimsRequest add(final OIDCClaimsRequest other) { 140 141 if (other == null) 142 return this; 143 144 // Regular id_token 145 Collection<ClaimsSetRequest.Entry> idTokenEntries = new LinkedList<>(); 146 if (idToken != null) { 147 idTokenEntries.addAll(idToken.getEntries()); 148 } 149 if (other.getIDTokenClaimsRequest() != null) { 150 idTokenEntries.addAll(other.getIDTokenClaimsRequest().getEntries()); 151 } 152 153 // Regular userinfo 154 Collection<ClaimsSetRequest.Entry> userInfoEntries = new LinkedList<>(); 155 if (userInfo != null) { 156 userInfoEntries.addAll(userInfo.getEntries()); 157 } 158 if (other.getUserInfoClaimsRequest() != null) { 159 userInfoEntries.addAll(other.getUserInfoClaimsRequest().getEntries()); 160 } 161 162 // Verified id_token 163 List<VerifiedClaimsSetRequest> idTokenVerifiedList = new LinkedList<>(idTokenVerified); 164 idTokenVerifiedList.addAll(other.getIDTokenVerifiedClaimsRequestList()); 165 166 // Verified userinfo 167 List<VerifiedClaimsSetRequest> userInfoVerifiedList = new LinkedList<>(userInfoVerified); 168 userInfoVerifiedList.addAll(other.getUserInfoVerifiedClaimsRequestList()); 169 170 return new OIDCClaimsRequest( 171 idTokenEntries.isEmpty() ? null : new ClaimsSetRequest(idTokenEntries), 172 userInfoEntries.isEmpty() ? null : new ClaimsSetRequest(userInfoEntries), 173 idTokenVerifiedList, 174 userInfoVerifiedList 175 ); 176 } 177 178 179 /** 180 * Returns the claims requested in the ID token. 181 * 182 * @return The ID token claims request, {@code null} if not specified. 183 */ 184 public ClaimsSetRequest getIDTokenClaimsRequest() { 185 return idToken; 186 } 187 188 189 /** 190 * Sets the claims requested in the ID token. 191 * 192 * @param idToken The ID token claims request, {@code null} if not 193 * specified. 194 * 195 * @return The updated OpenID claims request. 196 */ 197 public OIDCClaimsRequest withIDTokenClaimsRequest(final ClaimsSetRequest idToken) { 198 return new OIDCClaimsRequest( 199 idToken, 200 getUserInfoClaimsRequest(), 201 getIDTokenVerifiedClaimsRequestList(), 202 getUserInfoVerifiedClaimsRequestList()); 203 } 204 205 206 /** 207 * Returns the claims requested at the UserInfo endpoint. 208 * 209 * @return The UserInfo claims request, {@code null} if not specified. 210 */ 211 public ClaimsSetRequest getUserInfoClaimsRequest() { 212 return userInfo; 213 } 214 215 216 /** 217 * Sets the claims requested at the UserInfo endpoint. 218 * 219 * @param userInfo The UserInfo claims request, {@code null} if not 220 * specified. 221 * 222 * @return The updated OpenID claims request. 223 */ 224 public OIDCClaimsRequest withUserInfoClaimsRequest(final ClaimsSetRequest userInfo) { 225 return new OIDCClaimsRequest( 226 getIDTokenClaimsRequest(), 227 userInfo, 228 getIDTokenVerifiedClaimsRequestList(), 229 getUserInfoVerifiedClaimsRequestList()); 230 } 231 232 233 /** 234 * Returns the list of verified claims sets requested in the ID token. 235 * 236 * @return The ID token verified claims request list, empty list if not 237 * specified. 238 */ 239 public List<VerifiedClaimsSetRequest> getIDTokenVerifiedClaimsRequestList() { 240 return idTokenVerified; 241 } 242 243 244 /** 245 * Sets the list of verified claims sets requested in the ID token. 246 * 247 * @param idTokenVerifiedList One or more ID token verified claims 248 * requests, empty list if not specified. 249 * 250 * @return The updated OpenID claims request. 251 */ 252 public OIDCClaimsRequest withIDTokenVerifiedClaimsRequestList(final List<VerifiedClaimsSetRequest> idTokenVerifiedList) { 253 return new OIDCClaimsRequest( 254 getIDTokenClaimsRequest(), 255 getUserInfoClaimsRequest(), 256 idTokenVerifiedList != null ? idTokenVerifiedList : Collections.<VerifiedClaimsSetRequest>emptyList(), 257 getUserInfoVerifiedClaimsRequestList()); 258 } 259 260 261 /** 262 * Sets a single verified claims set requested in the ID token. 263 * 264 * @param idTokenVerified The ID token verified claims request, 265 * {@code null} if not specified. 266 * 267 * @return The updated OpenID claims request. 268 */ 269 public OIDCClaimsRequest withIDTokenVerifiedClaimsRequest(final VerifiedClaimsSetRequest idTokenVerified) { 270 return new OIDCClaimsRequest( 271 getIDTokenClaimsRequest(), 272 getUserInfoClaimsRequest(), 273 idTokenVerified != null ? Collections.singletonList(idTokenVerified) : Collections.<VerifiedClaimsSetRequest>emptyList(), 274 getUserInfoVerifiedClaimsRequestList()); 275 } 276 277 278 /** 279 * Returns the list of verified claims sets requested at the UserInfo 280 * endpoint. 281 * 282 * @return The UserInfo verified claims request list, empty list if not 283 * specified. 284 */ 285 public List<VerifiedClaimsSetRequest> getUserInfoVerifiedClaimsRequestList() { 286 return userInfoVerified; 287 } 288 289 290 /** 291 * Sets the list of verified claims sets requested at the UserInfo 292 * endpoint. 293 * 294 * @param userInfoVerifiedList One or more UserInfo verified claims 295 * requests, empty list if not specified. 296 * 297 * @return The updated OpenID claims request. 298 */ 299 public OIDCClaimsRequest withUserInfoVerifiedClaimsRequestList(final List<VerifiedClaimsSetRequest> userInfoVerifiedList) { 300 return new OIDCClaimsRequest( 301 getIDTokenClaimsRequest(), 302 getUserInfoClaimsRequest(), 303 getIDTokenVerifiedClaimsRequestList(), 304 userInfoVerifiedList != null ? userInfoVerifiedList : Collections.<VerifiedClaimsSetRequest>emptyList()); 305 } 306 307 308 /** 309 * Sets a single verified claims set requested at the UserInfo 310 * endpoint. 311 * 312 * @param userInfoVerified The UserInfo verified claims request, 313 * {@code null} if not specified. 314 * 315 * @return The updated OpenID claims request. 316 */ 317 public OIDCClaimsRequest withUserInfoVerifiedClaimsRequest(final VerifiedClaimsSetRequest userInfoVerified) { 318 return new OIDCClaimsRequest( 319 getIDTokenClaimsRequest(), 320 getUserInfoClaimsRequest(), 321 getIDTokenVerifiedClaimsRequestList(), 322 userInfoVerified != null ? Collections.singletonList(userInfoVerified) : Collections.<VerifiedClaimsSetRequest>emptyList()); 323 } 324 325 326 private static JSONObject addVerified(final List<VerifiedClaimsSetRequest> verified, 327 final JSONObject containingJSONObject) { 328 329 if (verified != null) { 330 331 if (verified.size() == 1 && verified.get(0) != null) { 332 JSONObject out = new JSONObject(); 333 if (containingJSONObject != null) { 334 out.putAll(containingJSONObject); 335 } 336 out.put("verified_claims", verified.get(0).toJSONObject()); 337 return out; 338 } else if (verified.size() > 1) { 339 JSONObject out = new JSONObject(); 340 if (containingJSONObject != null) { 341 out.putAll(containingJSONObject); 342 } 343 JSONArray jsonArray = new JSONArray(); 344 for (VerifiedClaimsSetRequest verifiedClaims: verified) { 345 jsonArray.add(verifiedClaims.toJSONObject()); 346 } 347 out.put("verified_claims", jsonArray); 348 return out; 349 } 350 } 351 return containingJSONObject; 352 } 353 354 355 /** 356 * Returns the JSON object representation of this OpenID claims 357 * request. 358 * 359 * <p>Example: 360 * 361 * <pre> 362 * { 363 * "userinfo": 364 * { 365 * "given_name": {"essential": true}, 366 * "nickname": null, 367 * "email": {"essential": true}, 368 * "email_verified": {"essential": true}, 369 * "picture": null, 370 * "http://example.info/claims/groups": null 371 * }, 372 * "id_token": 373 * { 374 * "auth_time": {"essential": true}, 375 * "acr": {"values": ["urn:mace:incommon:iap:silver"] } 376 * } 377 * } 378 * </pre> 379 * 380 * @return The JSON object, empty if no ID token and UserInfo claims 381 * are specified. 382 */ 383 public JSONObject toJSONObject() { 384 385 JSONObject o = new JSONObject(); 386 387 // id_token 388 JSONObject idTokenJSONObject = null; 389 if (idToken != null) { 390 idTokenJSONObject = idToken.toJSONObject(); 391 } 392 idTokenJSONObject = addVerified(idTokenVerified, idTokenJSONObject); 393 if (idTokenJSONObject != null && ! idTokenJSONObject.isEmpty()) { 394 o.put("id_token", idTokenJSONObject); 395 } 396 397 // userinfo 398 JSONObject userInfoJSONObject = null; 399 if (userInfo != null) { 400 userInfoJSONObject = userInfo.toJSONObject(); 401 } 402 userInfoJSONObject = addVerified(userInfoVerified, userInfoJSONObject); 403 if (userInfoJSONObject != null && ! userInfoJSONObject.isEmpty()) { 404 o.put("userinfo", userInfoJSONObject); 405 } 406 407 return o; 408 } 409 410 411 @Override 412 public String toJSONString() { 413 return toJSONObject().toJSONString(); 414 } 415 416 417 @Override 418 public String toString() { 419 420 return toJSONString(); 421 } 422 423 424 /** 425 * Resolves the OpenID claims request for the specified response type 426 * and scope. The scope values that are {@link OIDCScopeValue standard 427 * OpenID scope values} are resolved to their respective individual 428 * claims requests, any other scope values are ignored. 429 * 430 * @param responseType The response type. Must not be {@code null}. 431 * @param scope The scope, {@code null} if not specified (for a 432 * plain OAuth 2.0 authorisation request with no 433 * scope explicitly specified). 434 * 435 * @return The OpenID claims request. 436 */ 437 public static OIDCClaimsRequest resolve(final ResponseType responseType, final Scope scope) { 438 439 return resolve(responseType, scope, Collections.<Scope.Value, Set<String>>emptyMap()); 440 } 441 442 443 /** 444 * Resolves the OpenID claims request for the specified response type 445 * and scope. The scope values that are {@link OIDCScopeValue standard 446 * OpenID scope values} are resolved to their respective individual 447 * claims requests, any other scope values are checked in the specified 448 * custom claims map and resolved accordingly. 449 * 450 * @param responseType The response type. Must not be {@code null}. 451 * @param scope The scope, {@code null} if not specified (for a 452 * plain OAuth 2.0 authorisation request with no 453 * scope explicitly specified). 454 * @param customClaims Custom scope value to set of claim names map, 455 * {@code null} if not specified. 456 * 457 * @return The OpenID claims request. 458 */ 459 public static OIDCClaimsRequest resolve(final ResponseType responseType, 460 final Scope scope, 461 final Map<Scope.Value, Set<String>> customClaims) { 462 463 OIDCClaimsRequest claimsRequest = new OIDCClaimsRequest(); 464 465 if (scope == null) { 466 // Plain OAuth 2.0 mode 467 return claimsRequest; 468 } 469 470 List<ClaimsSetRequest.Entry> entries = new LinkedList<>(); 471 for (Scope.Value value : scope) { 472 473 if (value.equals(OIDCScopeValue.PROFILE)) { 474 475 entries.addAll(OIDCScopeValue.PROFILE.toClaimsSetRequestEntries()); 476 477 } else if (value.equals(OIDCScopeValue.EMAIL)) { 478 479 entries.addAll(OIDCScopeValue.EMAIL.toClaimsSetRequestEntries()); 480 481 } else if (value.equals(OIDCScopeValue.PHONE)) { 482 483 entries.addAll(OIDCScopeValue.PHONE.toClaimsSetRequestEntries()); 484 485 } else if (value.equals(OIDCScopeValue.ADDRESS)) { 486 487 entries.addAll(OIDCScopeValue.ADDRESS.toClaimsSetRequestEntries()); 488 489 } else if (customClaims != null && customClaims.containsKey(value)) { 490 491 // Process custom scope value -> claim names expansion, e.g. 492 // "corp_profile" -> ["employeeNumber", "dept", "ext"] 493 Set<String> claimNames = customClaims.get(value); 494 495 if (claimNames == null || claimNames.isEmpty()) { 496 continue; // skip 497 } 498 499 for (String claimName : claimNames) { 500 entries.add(new ClaimsSetRequest.Entry(claimName).withClaimRequirement(ClaimRequirement.VOLUNTARY)); 501 } 502 503 } 504 } 505 506 if (entries.isEmpty()) { 507 return claimsRequest; 508 } 509 510 ClaimsSetRequest claimsSetRequest = new ClaimsSetRequest(entries); 511 512 // Determine the claims target (ID token or UserInfo) 513 final boolean switchToIDToken = 514 responseType.contains(OIDCResponseTypeValue.ID_TOKEN) && 515 !responseType.contains(ResponseType.Value.CODE) && 516 !responseType.contains(ResponseType.Value.TOKEN); 517 518 if (switchToIDToken) { 519 return claimsRequest.withIDTokenClaimsRequest(claimsSetRequest); 520 } else { 521 return claimsRequest.withUserInfoClaimsRequest(claimsSetRequest); 522 } 523 } 524 525 526 /** 527 * Resolves the merged OpenID claims request from the specified OpenID 528 * authentication request parameters. The scope values that are {@link 529 * OIDCScopeValue standard OpenID scope values} are resolved to their 530 * respective individual claims requests, any other scope values are 531 * ignored. 532 * 533 * @param responseType The response type. Must not be {@code null}. 534 * @param scope The scope, {@code null} if not specified (for a 535 * plain OAuth 2.0 authorisation request with no 536 * scope explicitly specified). 537 * @param claimsRequest The OpenID claims request, corresponding to the 538 * optional {@code claims} OpenID authentication 539 * request parameter, {@code null} if not 540 * specified. 541 * 542 * @return The merged OpenID claims request. 543 */ 544 public static OIDCClaimsRequest resolve(final ResponseType responseType, 545 final Scope scope, 546 final OIDCClaimsRequest claimsRequest) { 547 548 return resolve(responseType, scope, claimsRequest, Collections.<Scope.Value, Set<String>>emptyMap()); 549 } 550 551 552 /** 553 * Resolves the merged OpenID claims request from the specified OpenID 554 * authentication request parameters. The scope values that are {@link 555 * OIDCScopeValue standard OpenID scope values} are resolved to their 556 * respective individual claims requests, any other scope values are 557 * checked in the specified custom claims map and resolved accordingly. 558 * 559 * @param responseType The response type. Must not be {@code null}. 560 * @param scope The scope, {@code null} if not specified (for a 561 * plain OAuth 2.0 authorisation request with no 562 * scope explicitly specified). 563 * @param claimsRequest The OpenID claims request, corresponding to the 564 * optional {@code claims} OpenID authentication 565 * request parameter, {@code null} if not 566 * specified. 567 * @param customClaims Custom scope value to set of claim names map, 568 * {@code null} if not specified. 569 * 570 * @return The merged OpenID claims request. 571 */ 572 public static OIDCClaimsRequest resolve(final ResponseType responseType, 573 final Scope scope, 574 final OIDCClaimsRequest claimsRequest, 575 final Map<Scope.Value, Set<String>> customClaims) { 576 577 return resolve(responseType, scope, customClaims).add(claimsRequest); 578 } 579 580 581 /** 582 * Resolves the merged OpenID claims request for the specified OpenID 583 * authentication request. The scope values that are {@link 584 * OIDCScopeValue standard OpenID scope values} are resolved to their 585 * respective individual claims requests, any other scope values are 586 * ignored. 587 * 588 * @param authRequest The OpenID authentication request. Must not be 589 * {@code null}. 590 * 591 * @return The merged OpenID claims request. 592 */ 593 public static OIDCClaimsRequest resolve(final AuthenticationRequest authRequest) { 594 595 return resolve(authRequest.getResponseType(), authRequest.getScope(), authRequest.getOIDCClaims()); 596 } 597 598 599 private static VerifiedClaimsSetRequest parseVerifiedClaimsSetRequest(final JSONObject jsonObject, 600 final int position) 601 throws ParseException { 602 603 try { 604 return VerifiedClaimsSetRequest.parse(jsonObject); 605 } catch (ParseException e) { 606 throw new ParseException("Invalid verified claims request" + 607 (position > -1 ? " at position " + position : "") + 608 ": " + e.getMessage()); 609 } 610 } 611 612 613 private static List<VerifiedClaimsSetRequest> parseVerified(final JSONObject containingJSONObject) 614 throws ParseException { 615 616 if (! containingJSONObject.containsKey("verified_claims")) { 617 // No verified claims 618 return Collections.emptyList(); 619 } 620 621 if (containingJSONObject.get("verified_claims") instanceof JSONObject) { 622 // Single verified claims element 623 JSONObject vo = JSONObjectUtils.getJSONObject(containingJSONObject, "verified_claims"); 624 return Collections.singletonList(parseVerifiedClaimsSetRequest(vo, -1)); 625 626 } else { 627 // Array of one or more verified claims elements 628 JSONArray va = JSONObjectUtils.getJSONArray(containingJSONObject, "verified_claims"); 629 List<VerifiedClaimsSetRequest> out = new LinkedList<>(); 630 int pos = 0; 631 for (JSONObject vo: JSONArrayUtils.toJSONObjectList(va)) { 632 out.add(parseVerifiedClaimsSetRequest(vo, pos++)); 633 } 634 return out; 635 } 636 } 637 638 639 /** 640 * Parses an OpenID claims request from the specified JSON object 641 * representation. 642 * 643 * <p>Example: 644 * 645 * <pre> 646 * { 647 * "userinfo": 648 * { 649 * "given_name": {"essential": true}, 650 * "nickname": null, 651 * "email": {"essential": true}, 652 * "email_verified": {"essential": true}, 653 * "picture": null, 654 * "http://example.info/claims/groups": null 655 * }, 656 * "id_token": 657 * { 658 * "auth_time": {"essential": true}, 659 * "acr": {"values": ["urn:mace:incommon:iap:silver"] } 660 * } 661 * } 662 * </pre> 663 * 664 * @param jsonObject The JSON object to parse. Must not be 665 * {@code null}. 666 * 667 * @return The OpenID claims request. 668 * 669 * @throws ParseException If parsing failed. 670 */ 671 public static OIDCClaimsRequest parse(final JSONObject jsonObject) 672 throws ParseException { 673 674 OIDCClaimsRequest claimsRequest = new OIDCClaimsRequest(); 675 676 JSONObject idTokenObject = JSONObjectUtils.getJSONObject(jsonObject, "id_token", null); 677 678 if (idTokenObject != null) { 679 ClaimsSetRequest csr = ClaimsSetRequest.parse(idTokenObject); 680 if (! csr.getEntries().isEmpty()) { 681 claimsRequest = claimsRequest.withIDTokenClaimsRequest(csr); 682 } 683 claimsRequest = claimsRequest.withIDTokenVerifiedClaimsRequestList(parseVerified(idTokenObject)); 684 } 685 686 JSONObject userInfoObject = JSONObjectUtils.getJSONObject(jsonObject, "userinfo", null); 687 688 if (userInfoObject != null) { 689 ClaimsSetRequest csr = ClaimsSetRequest.parse(userInfoObject); 690 if (! csr.getEntries().isEmpty()) { 691 claimsRequest = claimsRequest.withUserInfoClaimsRequest(ClaimsSetRequest.parse(userInfoObject)); 692 } 693 claimsRequest = claimsRequest.withUserInfoVerifiedClaimsRequestList(parseVerified(userInfoObject)); 694 } 695 696 return claimsRequest; 697 } 698 699 700 /** 701 * Parses an OpenID claims request from the specified JSON object 702 * string representation. 703 * 704 * <p>Example: 705 * 706 * <pre> 707 * { 708 * "userinfo": 709 * { 710 * "given_name": {"essential": true}, 711 * "nickname": null, 712 * "email": {"essential": true}, 713 * "email_verified": {"essential": true}, 714 * "picture": null, 715 * "http://example.info/claims/groups": null 716 * }, 717 * "id_token": 718 * { 719 * "auth_time": {"essential": true}, 720 * "acr": {"values": ["urn:mace:incommon:iap:silver"] } 721 * } 722 * } 723 * </pre> 724 * 725 * @param json The JSON object string to parse. Must not be 726 * {@code null}. 727 * 728 * @return The OpenID claims request. 729 * 730 * @throws ParseException If parsing failed. 731 */ 732 public static OIDCClaimsRequest parse(final String json) 733 throws ParseException { 734 735 return parse(JSONObjectUtils.parse(json)); 736 } 737}