001/* 002 * oauth2-oidc-sdk 003 * 004 * Copyright 2012-2016, 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.oauth2.sdk.as; 019 020import java.io.IOException; 021import java.net.MalformedURLException; 022import java.net.URI; 023import java.net.URISyntaxException; 024import java.net.URL; 025import java.util.*; 026 027import net.minidev.json.JSONObject; 028 029import com.nimbusds.jose.Algorithm; 030import com.nimbusds.jose.EncryptionMethod; 031import com.nimbusds.jose.JWEAlgorithm; 032import com.nimbusds.jose.JWSAlgorithm; 033import com.nimbusds.langtag.LangTag; 034import com.nimbusds.langtag.LangTagException; 035import com.nimbusds.oauth2.sdk.*; 036import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod; 037import com.nimbusds.oauth2.sdk.client.ClientType; 038import com.nimbusds.oauth2.sdk.ciba.BackChannelTokenDeliveryMode; 039import com.nimbusds.oauth2.sdk.http.HTTPRequest; 040import com.nimbusds.oauth2.sdk.http.HTTPResponse; 041import com.nimbusds.oauth2.sdk.id.Issuer; 042import com.nimbusds.oauth2.sdk.pkce.CodeChallengeMethod; 043import com.nimbusds.oauth2.sdk.util.CollectionUtils; 044import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 045import com.nimbusds.oauth2.sdk.util.URIUtils; 046 047/** 048 * OAuth 2.0 Authorisation Server (AS) metadata. 049 * 050 * <p>Related specifications: 051 * 052 * <ul> 053 * <li>OAuth 2.0 Authorization Server Metadata (RFC 8414) 054 * <li>OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound 055 * Access Tokens (RFC 8705) 056 * <li>OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer 057 * (DPoP) (draft-ietf-oauth-dpop-02) 058 * <li>Financial-grade API: JWT Secured Authorization Response Mode for 059 * OAuth 2.0 (JARM) 060 * <li>OAuth 2.0 Authorization Server Issuer Identifier in Authorization 061 * Response (draft-ietf-oauth-iss-auth-resp-00) 062 * <li>Financial-grade API - Part 2: Read and Write API Security Profile 063 * <li>OAuth 2.0 Pushed Authorization Requests (RFC 9126) 064 * <li>OAuth 2.0 Device Authorization Grant (RFC 8628) 065 * <li>OpenID Connect Client Initiated Backchannel Authentication Flow - 066 * Core 1.0 067 * <li>OAuth 2.0 Incremental Authorization 068 * (draft-ietf-oauth-incremental-authz-04) 069 * </ul> 070 */ 071public class AuthorizationServerMetadata extends AuthorizationServerEndpointMetadata implements ReadOnlyAuthorizationServerMetadata { 072 073 /** 074 * The registered parameter names. 075 */ 076 private static final Set<String> REGISTERED_PARAMETER_NAMES; 077 078 static { 079 Set<String> p = new HashSet<>(AuthorizationServerEndpointMetadata.getRegisteredParameterNames()); 080 p.add("issuer"); 081 p.add("jwks_uri"); 082 p.add("scopes_supported"); 083 p.add("response_types_supported"); 084 p.add("response_modes_supported"); 085 p.add("grant_types_supported"); 086 p.add("code_challenge_methods_supported"); 087 p.add("token_endpoint_auth_methods_supported"); 088 p.add("token_endpoint_auth_signing_alg_values_supported"); 089 p.add("request_parameter_supported"); 090 p.add("request_uri_parameter_supported"); 091 p.add("require_request_uri_registration"); 092 p.add("request_object_signing_alg_values_supported"); 093 p.add("request_object_encryption_alg_values_supported"); 094 p.add("request_object_encryption_enc_values_supported"); 095 p.add("ui_locales_supported"); 096 p.add("service_documentation"); 097 p.add("op_policy_uri"); 098 p.add("op_tos_uri"); 099 p.add("introspection_endpoint_auth_methods_supported"); 100 p.add("introspection_endpoint_auth_signing_alg_values_supported"); 101 p.add("revocation_endpoint_auth_methods_supported"); 102 p.add("revocation_endpoint_auth_signing_alg_values_supported"); 103 p.add("mtls_endpoint_aliases"); 104 p.add("tls_client_certificate_bound_access_tokens"); 105 p.add("dpop_signing_alg_values_supported"); 106 p.add("authorization_signing_alg_values_supported"); 107 p.add("authorization_encryption_alg_values_supported"); 108 p.add("authorization_encryption_enc_values_supported"); 109 p.add("require_pushed_authorization_requests"); 110 p.add("incremental_authz_types_supported"); 111 p.add("authorization_response_iss_parameter_supported"); 112 p.add("backchannel_token_delivery_modes_supported"); 113 p.add("backchannel_authentication_request_signing_alg_values_supported"); 114 p.add("backchannel_user_code_parameter_supported"); 115 REGISTERED_PARAMETER_NAMES = Collections.unmodifiableSet(p); 116 } 117 118 119 /** 120 * Gets the registered OpenID Connect provider metadata parameter 121 * names. 122 * 123 * @return The registered OpenID Connect provider metadata parameter 124 * names, as an unmodifiable set. 125 */ 126 public static Set<String> getRegisteredParameterNames() { 127 128 return REGISTERED_PARAMETER_NAMES; 129 } 130 131 132 /** 133 * The issuer. 134 */ 135 private final Issuer issuer; 136 137 138 /** 139 * The JWK set URI. 140 */ 141 private URI jwkSetURI; 142 143 144 /** 145 * The supported scope values. 146 */ 147 private Scope scope; 148 149 150 /** 151 * The supported response types. 152 */ 153 private List<ResponseType> rts; 154 155 156 /** 157 * The supported response modes. 158 */ 159 private List<ResponseMode> rms; 160 161 162 /** 163 * The supported grant types. 164 */ 165 private List<GrantType> gts; 166 167 168 /** 169 * The supported code challenge methods for PKCE. 170 */ 171 private List<CodeChallengeMethod> codeChallengeMethods; 172 173 174 /** 175 * The supported token endpoint authentication methods. 176 */ 177 private List<ClientAuthenticationMethod> tokenEndpointAuthMethods; 178 179 180 /** 181 * The supported JWS algorithms for the {@code private_key_jwt} and 182 * {@code client_secret_jwt} token endpoint authentication methods. 183 */ 184 private List<JWSAlgorithm> tokenEndpointJWSAlgs; 185 186 187 /** 188 * The supported introspection endpoint authentication methods. 189 */ 190 private List<ClientAuthenticationMethod> introspectionEndpointAuthMethods; 191 192 193 /** 194 * The supported JWS algorithms for the {@code private_key_jwt} and 195 * {@code client_secret_jwt} introspection endpoint authentication 196 * methods. 197 */ 198 private List<JWSAlgorithm> introspectionEndpointJWSAlgs; 199 200 201 /** 202 * The supported revocation endpoint authentication methods. 203 */ 204 private List<ClientAuthenticationMethod> revocationEndpointAuthMethods; 205 206 207 /** 208 * The supported JWS algorithms for the {@code private_key_jwt} and 209 * {@code client_secret_jwt} revocation endpoint authentication 210 * methods. 211 */ 212 private List<JWSAlgorithm> revocationEndpointJWSAlgs; 213 214 215 /** 216 * The supported JWS algorithms for request objects. 217 */ 218 private List<JWSAlgorithm> requestObjectJWSAlgs; 219 220 221 /** 222 * The supported JWE algorithms for request objects. 223 */ 224 private List<JWEAlgorithm> requestObjectJWEAlgs; 225 226 227 /** 228 * The supported encryption methods for request objects. 229 */ 230 private List<EncryptionMethod> requestObjectJWEEncs; 231 232 233 /** 234 * If {@code true} the {@code request} parameter is supported, else 235 * not. 236 */ 237 private boolean requestParamSupported = false; 238 239 240 /** 241 * If {@code true} the {@code request_uri} parameter is supported, else 242 * not. 243 */ 244 private boolean requestURIParamSupported = false; 245 246 247 /** 248 * If {@code true} the {@code request_uri} parameters must be 249 * pre-registered with the provider, else not. 250 */ 251 private boolean requireRequestURIReg = false; 252 253 254 /** 255 * If {@code true} the {@code iss} authorisation response is supported, 256 * else not. 257 */ 258 private boolean authzResponseIssParameterSupported = false; 259 260 261 /** 262 * The supported UI locales. 263 */ 264 private List<LangTag> uiLocales; 265 266 267 /** 268 * The service documentation URI. 269 */ 270 private URI serviceDocsURI; 271 272 273 /** 274 * The provider's policy regarding relying party use of data. 275 */ 276 private URI policyURI; 277 278 279 /** 280 * The provider's terms of service. 281 */ 282 private URI tosURI; 283 284 285 /** 286 * Aliases for endpoints with mutial TLS authentication. 287 */ 288 private AuthorizationServerEndpointMetadata mtlsEndpointAliases; 289 290 291 /** 292 * If {@code true} the 293 * {@code tls_client_certificate_bound_access_tokens} if set, else 294 * not. 295 */ 296 private boolean tlsClientCertificateBoundAccessTokens = false; 297 298 299 /** 300 * The supported JWS algorithms for DPoP. 301 */ 302 private List<JWSAlgorithm> dPoPJWSAlgs; 303 304 305 /** 306 * The supported JWS algorithms for JWT-encoded authorisation 307 * responses. 308 */ 309 private List<JWSAlgorithm> authzJWSAlgs; 310 311 312 /** 313 * The supported JWE algorithms for JWT-encoded authorisation 314 * responses. 315 */ 316 private List<JWEAlgorithm> authzJWEAlgs; 317 318 319 /** 320 * The supported encryption methods for JWT-encoded authorisation 321 * responses. 322 */ 323 private List<EncryptionMethod> authzJWEEncs; 324 325 326 /** 327 * If {@code true} PAR is required, else not. 328 */ 329 private boolean requirePAR = false; 330 331 332 /** 333 * The supported OAuth 2.0 client types for incremental authorisation. 334 */ 335 private List<ClientType> incrementalAuthzTypes; 336 337 338 /** 339 * The supported CIBA token delivery modes. 340 */ 341 private List<BackChannelTokenDeliveryMode> backChannelTokenDeliveryModes; 342 343 344 /** 345 * The supported JWS algorithms for CIBA requests. If omitted signed 346 * authentication requests are not supported. 347 */ 348 private List<JWSAlgorithm> backChannelAuthRequestJWSAlgs; 349 350 351 /** 352 * If {@code true} the CIBA {@code user_code} parameter is supported, 353 * else not. 354 */ 355 private boolean backChannelUserCodeSupported = false; 356 357 358 /** 359 * Custom (not-registered) parameters. 360 */ 361 private final JSONObject customParameters = new JSONObject(); 362 363 364 /** 365 * Creates a new OAuth 2.0 Authorisation Server (AS) metadata instance. 366 * 367 * @param issuer The issuer identifier. Must be an URI using the https 368 * scheme with no query or fragment component. Must not 369 * be {@code null}. 370 */ 371 public AuthorizationServerMetadata(final Issuer issuer) { 372 373 URI uri; 374 try { 375 uri = new URI(issuer.getValue()); 376 } catch (URISyntaxException e) { 377 throw new IllegalArgumentException("The issuer identifier must be a URI: " + e.getMessage(), e); 378 } 379 380 if (uri.getRawQuery() != null) 381 throw new IllegalArgumentException("The issuer URI must be without a query component"); 382 383 if (uri.getRawFragment() != null) 384 throw new IllegalArgumentException("The issuer URI must be without a fragment component"); 385 386 this.issuer = issuer; 387 } 388 389 390 @Override 391 public Issuer getIssuer() { 392 393 return issuer; 394 } 395 396 397 @Override 398 public URI getJWKSetURI() { 399 400 return jwkSetURI; 401 } 402 403 404 /** 405 * Sets the JSON Web Key (JWT) set URI. Corresponds to the 406 * {@code jwks_uri} metadata field. 407 * 408 * @param jwkSetURI The JWK set URI, {@code null} if not specified. 409 */ 410 public void setJWKSetURI(final URI jwkSetURI) { 411 412 this.jwkSetURI = jwkSetURI; 413 } 414 415 416 @Override 417 public Scope getScopes() { 418 419 return scope; 420 } 421 422 423 /** 424 * Sets the supported scope values. Corresponds to the 425 * {@code scopes_supported} metadata field. 426 * 427 * @param scope The supported scope values, {@code null} if not 428 * specified. 429 */ 430 public void setScopes(final Scope scope) { 431 432 this.scope = scope; 433 } 434 435 436 @Override 437 public List<ResponseType> getResponseTypes() { 438 439 return rts; 440 } 441 442 443 /** 444 * Sets the supported response type values. Corresponds to the 445 * {@code response_types_supported} metadata field. 446 * 447 * @param rts The supported response type values, {@code null} if not 448 * specified. 449 */ 450 public void setResponseTypes(final List<ResponseType> rts) { 451 452 this.rts = rts; 453 } 454 455 456 @Override 457 public List<ResponseMode> getResponseModes() { 458 459 return rms; 460 } 461 462 463 /** 464 * Sets the supported response mode values. Corresponds to the 465 * {@code response_modes_supported}. 466 * 467 * @param rms The supported response mode values, {@code null} if not 468 * specified. 469 */ 470 public void setResponseModes(final List<ResponseMode> rms) { 471 472 this.rms = rms; 473 } 474 475 476 @Override 477 public List<GrantType> getGrantTypes() { 478 479 return gts; 480 } 481 482 483 /** 484 * Sets the supported OAuth 2.0 grant types. Corresponds to the 485 * {@code grant_types_supported} metadata field. 486 * 487 * @param gts The supported grant types, {@code null} if not specified. 488 */ 489 public void setGrantTypes(final List<GrantType> gts) { 490 491 this.gts = gts; 492 } 493 494 495 @Override 496 public List<CodeChallengeMethod> getCodeChallengeMethods() { 497 498 return codeChallengeMethods; 499 } 500 501 502 /** 503 * Gets the supported authorisation code challenge methods for PKCE. 504 * Corresponds to the {@code code_challenge_methods_supported} metadata 505 * field. 506 * 507 * @param codeChallengeMethods The supported code challenge methods, 508 * {@code null} if not specified. 509 */ 510 public void setCodeChallengeMethods(final List<CodeChallengeMethod> codeChallengeMethods) { 511 512 this.codeChallengeMethods = codeChallengeMethods; 513 } 514 515 516 @Override 517 public List<ClientAuthenticationMethod> getTokenEndpointAuthMethods() { 518 519 return tokenEndpointAuthMethods; 520 } 521 522 523 /** 524 * Sets the supported token endpoint authentication methods. 525 * Corresponds to the {@code token_endpoint_auth_methods_supported} 526 * metadata field. 527 * 528 * @param authMethods The supported token endpoint authentication 529 * methods, {@code null} if not specified. 530 */ 531 public void setTokenEndpointAuthMethods(final List<ClientAuthenticationMethod> authMethods) { 532 533 this.tokenEndpointAuthMethods = authMethods; 534 } 535 536 537 @Override 538 public List<JWSAlgorithm> getTokenEndpointJWSAlgs() { 539 540 return tokenEndpointJWSAlgs; 541 } 542 543 544 /** 545 * Sets the supported JWS algorithms for the {@code private_key_jwt} 546 * and {@code client_secret_jwt} token endpoint authentication methods. 547 * Corresponds to the 548 * {@code token_endpoint_auth_signing_alg_values_supported} metadata 549 * field. 550 * 551 * @param jwsAlgs The supported JWS algorithms, {@code null} if not 552 * specified. Must not contain the {@code none} 553 * algorithm. 554 */ 555 public void setTokenEndpointJWSAlgs(final List<JWSAlgorithm> jwsAlgs) { 556 557 if (jwsAlgs != null && jwsAlgs.contains(Algorithm.NONE)) 558 throw new IllegalArgumentException("The \"none\" algorithm is not accepted"); 559 560 this.tokenEndpointJWSAlgs = jwsAlgs; 561 } 562 563 564 @Override 565 public List<ClientAuthenticationMethod> getIntrospectionEndpointAuthMethods() { 566 return introspectionEndpointAuthMethods; 567 } 568 569 570 /** 571 * Sets the supported introspection endpoint authentication methods. 572 * Corresponds to the 573 * {@code introspection_endpoint_auth_methods_supported} metadata 574 * field. 575 * 576 * @param authMethods The supported introspection endpoint 577 * authentication methods, {@code null} if not 578 * specified. 579 */ 580 public void setIntrospectionEndpointAuthMethods(final List<ClientAuthenticationMethod> authMethods) { 581 582 this.introspectionEndpointAuthMethods = authMethods; 583 } 584 585 586 @Override 587 public List<JWSAlgorithm> getIntrospectionEndpointJWSAlgs() { 588 589 return introspectionEndpointJWSAlgs; 590 } 591 592 593 /** 594 * Sets the supported JWS algorithms for the {@code private_key_jwt} 595 * and {@code client_secret_jwt} introspection endpoint authentication 596 * methods. Corresponds to the 597 * {@code introspection_endpoint_auth_signing_alg_values_supported} 598 * metadata field. 599 * 600 * @param jwsAlgs The supported JWS algorithms, {@code null} if not 601 * specified. Must not contain the {@code none} 602 * algorithm. 603 */ 604 public void setIntrospectionEndpointJWSAlgs(final List<JWSAlgorithm> jwsAlgs) { 605 606 if (jwsAlgs != null && jwsAlgs.contains(Algorithm.NONE)) 607 throw new IllegalArgumentException("The \"none\" algorithm is not accepted"); 608 609 introspectionEndpointJWSAlgs = jwsAlgs; 610 } 611 612 613 @Override 614 public List<ClientAuthenticationMethod> getRevocationEndpointAuthMethods() { 615 616 return revocationEndpointAuthMethods; 617 } 618 619 620 /** 621 * Sets the supported revocation endpoint authentication methods. 622 * Corresponds to the 623 * {@code revocation_endpoint_auth_methods_supported} metadata field. 624 * 625 * @param authMethods The supported revocation endpoint authentication 626 * methods, {@code null} if not specified. 627 */ 628 public void setRevocationEndpointAuthMethods(final List<ClientAuthenticationMethod> authMethods) { 629 630 revocationEndpointAuthMethods = authMethods; 631 } 632 633 634 @Override 635 public List<JWSAlgorithm> getRevocationEndpointJWSAlgs() { 636 637 return revocationEndpointJWSAlgs; 638 } 639 640 641 /** 642 * Sets the supported JWS algorithms for the {@code private_key_jwt} 643 * and {@code client_secret_jwt} revocation endpoint authentication 644 * methods. Corresponds to the 645 * {@code revocation_endpoint_auth_signing_alg_values_supported} 646 * metadata field. 647 * 648 * @param jwsAlgs The supported JWS algorithms, {@code null} if not 649 * specified. Must not contain the {@code none} 650 * algorithm. 651 */ 652 public void setRevocationEndpointJWSAlgs(final List<JWSAlgorithm> jwsAlgs) { 653 654 if (jwsAlgs != null && jwsAlgs.contains(Algorithm.NONE)) 655 throw new IllegalArgumentException("The \"none\" algorithm is not accepted"); 656 657 revocationEndpointJWSAlgs = jwsAlgs; 658 } 659 660 661 @Override 662 public List<JWSAlgorithm> getRequestObjectJWSAlgs() { 663 664 return requestObjectJWSAlgs; 665 } 666 667 668 /** 669 * Sets the supported JWS algorithms for request objects. Corresponds 670 * to the {@code request_object_signing_alg_values_supported} metadata 671 * field. 672 * 673 * @param requestObjectJWSAlgs The supported JWS algorithms, 674 * {@code null} if not specified. 675 */ 676 public void setRequestObjectJWSAlgs(final List<JWSAlgorithm> requestObjectJWSAlgs) { 677 678 this.requestObjectJWSAlgs = requestObjectJWSAlgs; 679 } 680 681 682 @Override 683 public List<JWEAlgorithm> getRequestObjectJWEAlgs() { 684 685 return requestObjectJWEAlgs; 686 } 687 688 689 /** 690 * Sets the supported JWE algorithms for request objects. Corresponds 691 * to the {@code request_object_encryption_alg_values_supported} 692 * metadata field. 693 * 694 * @param requestObjectJWEAlgs The supported JWE algorithms, 695 * {@code null} if not specified. 696 */ 697 public void setRequestObjectJWEAlgs(final List<JWEAlgorithm> requestObjectJWEAlgs) { 698 699 this.requestObjectJWEAlgs = requestObjectJWEAlgs; 700 } 701 702 703 @Override 704 public List<EncryptionMethod> getRequestObjectJWEEncs() { 705 706 return requestObjectJWEEncs; 707 } 708 709 710 /** 711 * Sets the supported encryption methods for request objects. 712 * Corresponds to the 713 * {@code request_object_encryption_enc_values_supported} metadata 714 * field. 715 * 716 * @param requestObjectJWEEncs The supported encryption methods, 717 * {@code null} if not specified. 718 */ 719 public void setRequestObjectJWEEncs(final List<EncryptionMethod> requestObjectJWEEncs) { 720 721 this.requestObjectJWEEncs = requestObjectJWEEncs; 722 } 723 724 725 @Override 726 public boolean supportsRequestParam() { 727 728 return requestParamSupported; 729 } 730 731 732 /** 733 * Sets the support for the {@code request} authorisation request 734 * parameter. Corresponds to the {@code request_parameter_supported} 735 * metadata field. 736 * 737 * @param requestParamSupported {@code true} if the {@code reqeust} 738 * parameter is supported, else 739 * {@code false}. 740 */ 741 public void setSupportsRequestParam(final boolean requestParamSupported) { 742 743 this.requestParamSupported = requestParamSupported; 744 } 745 746 747 @Override 748 public boolean supportsRequestURIParam() { 749 750 return requestURIParamSupported; 751 } 752 753 754 /** 755 * Sets the support for the {@code request_uri} authorisation request 756 * parameter. Corresponds to the 757 * {@code request_uri_parameter_supported} metadata field. 758 * 759 * @param requestURIParamSupported {@code true} if the 760 * {@code request_uri} parameter is 761 * supported, else {@code false}. 762 */ 763 public void setSupportsRequestURIParam(final boolean requestURIParamSupported) { 764 765 this.requestURIParamSupported = requestURIParamSupported; 766 } 767 768 769 @Override 770 public boolean requiresRequestURIRegistration() { 771 772 return requireRequestURIReg; 773 } 774 775 776 /** 777 * Sets the requirement for the {@code request_uri} parameter 778 * pre-registration. Corresponds to the 779 * {@code require_request_uri_registration} metadata field. 780 * 781 * @param requireRequestURIReg {@code true} if the {@code request_uri} 782 * parameter values must be pre-registered, 783 * else {@code false}. 784 */ 785 public void setRequiresRequestURIRegistration(final boolean requireRequestURIReg) { 786 787 this.requireRequestURIReg = requireRequestURIReg; 788 } 789 790 791 @Override 792 public boolean supportsAuthorizationResponseIssuerParam() { 793 794 return authzResponseIssParameterSupported; 795 } 796 797 798 /** 799 * Sets the support for the {@code iss} authorisation response 800 * parameter. Corresponds to the 801 * {@code authorization_response_iss_parameter_supported} metadata 802 * field. 803 * 804 * @param authzResponseIssParameterSupported {@code true} if the 805 * {@code iss} authorisation 806 * response parameter is 807 * provided, else 808 * {@code false}. 809 */ 810 public void setSupportsAuthorizationResponseIssuerParam(final boolean authzResponseIssParameterSupported) { 811 812 this.authzResponseIssParameterSupported = authzResponseIssParameterSupported; 813 } 814 815 816 @Override 817 public List<LangTag> getUILocales() { 818 819 return uiLocales; 820 } 821 822 823 /** 824 * Sets the supported UI locales. Corresponds to the 825 * {@code ui_locales_supported} metadata field. 826 * 827 * @param uiLocales The supported UI locales, {@code null} if not 828 * specified. 829 */ 830 public void setUILocales(final List<LangTag> uiLocales) { 831 832 this.uiLocales = uiLocales; 833 } 834 835 836 @Override 837 public URI getServiceDocsURI() { 838 839 return serviceDocsURI; 840 } 841 842 843 /** 844 * Sets the service documentation URI. Corresponds to the 845 * {@code service_documentation} metadata field. 846 * 847 * @param serviceDocsURI The service documentation URI, {@code null} if 848 * not specified. The URI scheme must be https or 849 * http. 850 */ 851 public void setServiceDocsURI(final URI serviceDocsURI) { 852 853 URIUtils.ensureSchemeIsHTTPSorHTTP(serviceDocsURI); 854 this.serviceDocsURI = serviceDocsURI; 855 } 856 857 858 @Override 859 public URI getPolicyURI() { 860 861 return policyURI; 862 } 863 864 865 /** 866 * Sets the provider's policy regarding relying party use of data. 867 * Corresponds to the {@code op_policy_uri} metadata field. 868 * 869 * @param policyURI The policy URI, {@code null} if not specified. The 870 * URI scheme must be https or http. 871 */ 872 public void setPolicyURI(final URI policyURI) { 873 874 URIUtils.ensureSchemeIsHTTPSorHTTP(policyURI); 875 this.policyURI = policyURI; 876 } 877 878 879 @Override 880 public URI getTermsOfServiceURI() { 881 882 return tosURI; 883 } 884 885 886 /** 887 * Sets the provider's terms of service. Corresponds to the 888 * {@code op_tos_uri} metadata field. 889 * 890 * @param tosURI The terms of service URI, {@code null} if not 891 * specified. The URI scheme must be https or http. 892 */ 893 public void setTermsOfServiceURI(final URI tosURI) { 894 895 URIUtils.ensureSchemeIsHTTPSorHTTP(tosURI); 896 this.tosURI = tosURI; 897 } 898 899 900 @Override 901 public ReadOnlyAuthorizationServerEndpointMetadata getReadOnlyMtlsEndpointAliases() { 902 903 return getMtlsEndpointAliases(); 904 } 905 906 907 /** 908 * Gets the aliases for communication with mutual TLS. Corresponds to 909 * the {@code mtls_endpoint_aliases} metadata field. 910 * 911 * @return The aliases for communication with mutual TLS, {@code null} 912 * when no aliases are defined. 913 */ 914 public AuthorizationServerEndpointMetadata getMtlsEndpointAliases() { 915 916 return mtlsEndpointAliases; 917 } 918 919 920 /** 921 * Sets the aliases for communication with mutual TLS. Corresponds to the 922 * {@code mtls_endpoint_aliases} metadata field. 923 * 924 * @param mtlsEndpointAliases The aliases for communication with mutual 925 * TLS, or {@code null} when no aliases are 926 * defined. 927 */ 928 public void setMtlsEndpointAliases(AuthorizationServerEndpointMetadata mtlsEndpointAliases) { 929 930 this.mtlsEndpointAliases = mtlsEndpointAliases; 931 } 932 933 934 @Override 935 public boolean supportsTLSClientCertificateBoundAccessTokens() { 936 937 return tlsClientCertificateBoundAccessTokens; 938 } 939 940 941 /** 942 * Sets the support for TLS client certificate bound access tokens. 943 * Corresponds to the 944 * {@code tls_client_certificate_bound_access_tokens} metadata field. 945 * 946 * @param tlsClientCertBoundTokens {@code true} if TLS client 947 * certificate bound access tokens are 948 * supported, else {@code false}. 949 */ 950 public void setSupportsTLSClientCertificateBoundAccessTokens(final boolean tlsClientCertBoundTokens) { 951 952 tlsClientCertificateBoundAccessTokens = tlsClientCertBoundTokens; 953 } 954 955 956 @Override 957 @Deprecated 958 public boolean supportsMutualTLSSenderConstrainedAccessTokens() { 959 960 return supportsTLSClientCertificateBoundAccessTokens(); 961 } 962 963 964 /** 965 * Sets the support for TLS client certificate bound access tokens. 966 * Corresponds to the 967 * {@code tls_client_certificate_bound_access_tokens} metadata field. 968 * 969 * @param mutualTLSSenderConstrainedAccessTokens {@code true} if TLS 970 * client certificate 971 * bound access tokens 972 * are supported, else 973 * {@code false}. 974 */ 975 @Deprecated 976 public void setSupportsMutualTLSSenderConstrainedAccessTokens(final boolean mutualTLSSenderConstrainedAccessTokens) { 977 978 setSupportsTLSClientCertificateBoundAccessTokens(mutualTLSSenderConstrainedAccessTokens); 979 } 980 981 982 @Override 983 public List<JWSAlgorithm> getDPoPJWSAlgs() { 984 985 return dPoPJWSAlgs; 986 } 987 988 989 /** 990 * Sets the supported JWS algorithms for Demonstrating 991 * Proof-of-Possession at the Application Layer (DPoP). Corresponds to 992 * the "dpop_signing_alg_values_supported" metadata field. 993 * 994 * @param dPoPJWSAlgs The supported JWS algorithms for DPoP, 995 * {@code null} if none. 996 */ 997 public void setDPoPJWSAlgs(final List<JWSAlgorithm> dPoPJWSAlgs) { 998 999 this.dPoPJWSAlgs = dPoPJWSAlgs; 1000 } 1001 1002 1003 @Override 1004 public List<JWSAlgorithm> getAuthorizationJWSAlgs() { 1005 1006 return authzJWSAlgs; 1007 } 1008 1009 1010 /** 1011 * Sets the supported JWS algorithms for JWT-encoded authorisation 1012 * responses. Corresponds to the 1013 * {@code authorization_signing_alg_values_supported} metadata field. 1014 * 1015 * @param authzJWSAlgs The supported JWS algorithms, {@code null} if 1016 * not specified. 1017 */ 1018 public void setAuthorizationJWSAlgs(final List<JWSAlgorithm> authzJWSAlgs) { 1019 1020 this.authzJWSAlgs = authzJWSAlgs; 1021 } 1022 1023 1024 @Override 1025 public List<JWEAlgorithm> getAuthorizationJWEAlgs() { 1026 1027 return authzJWEAlgs; 1028 } 1029 1030 1031 /** 1032 * Sets the supported JWE algorithms for JWT-encoded authorisation 1033 * responses. Corresponds to the 1034 * {@code authorization_encryption_alg_values_supported} metadata 1035 * field. 1036 * 1037 * @param authzJWEAlgs The supported JWE algorithms, {@code null} if 1038 * not specified. 1039 */ 1040 public void setAuthorizationJWEAlgs(final List<JWEAlgorithm> authzJWEAlgs) { 1041 1042 this.authzJWEAlgs = authzJWEAlgs; 1043 } 1044 1045 1046 @Override 1047 public List<EncryptionMethod> getAuthorizationJWEEncs() { 1048 1049 return authzJWEEncs; 1050 } 1051 1052 1053 /** 1054 * Sets the supported encryption methods for JWT-encoded authorisation 1055 * responses. Corresponds to the 1056 * {@code authorization_encryption_enc_values_supported} metadata 1057 * field. 1058 * 1059 * @param authzJWEEncs The supported encryption methods, {@code null} 1060 * if not specified. 1061 */ 1062 public void setAuthorizationJWEEncs(final List<EncryptionMethod> authzJWEEncs) { 1063 1064 this.authzJWEEncs = authzJWEEncs; 1065 } 1066 1067 1068 @Override 1069 public boolean requiresPushedAuthorizationRequests() { 1070 1071 return requirePAR; 1072 } 1073 1074 1075 /** 1076 * Sets the requirement for pushed authorisation requests (PAR). 1077 * Corresponds to the {@code pushed_authorization_request_endpoint} 1078 * metadata field. 1079 * 1080 * @param requirePAR {@code true} if PAR is required, else 1081 * {@code false}. 1082 */ 1083 public void requiresPushedAuthorizationRequests(final boolean requirePAR) { 1084 1085 this.requirePAR = requirePAR; 1086 } 1087 1088 1089 @Override 1090 public List<ClientType> getIncrementalAuthorizationTypes() { 1091 1092 return incrementalAuthzTypes; 1093 } 1094 1095 1096 /** 1097 * Sets the supported OAuth 2.0 client types for incremental 1098 * authorisation. Corresponds to the 1099 * {@code incremental_authz_types_supported} metadata field. 1100 * 1101 * @param incrementalAuthzTypes The supported client types for 1102 * incremental authorisation, {@code null} 1103 * if not specified. 1104 */ 1105 public void setIncrementalAuthorizationTypes(final List<ClientType> incrementalAuthzTypes) { 1106 1107 this.incrementalAuthzTypes = incrementalAuthzTypes; 1108 } 1109 1110 1111 @Override 1112 public List<BackChannelTokenDeliveryMode> getBackChannelTokenDeliveryModes() { 1113 1114 return backChannelTokenDeliveryModes; 1115 } 1116 1117 1118 /** 1119 * Sets the supported CIBA token delivery modes. Corresponds to the 1120 * {@code backchannel_token_delivery_modes_supported} metadata field. 1121 * 1122 * @param backChannelTokenDeliveryModes The CIBA token delivery modes, 1123 * {@code null} if not specified. 1124 */ 1125 public void setBackChannelTokenDeliveryModes(final List<BackChannelTokenDeliveryMode> backChannelTokenDeliveryModes) { 1126 1127 this.backChannelTokenDeliveryModes = backChannelTokenDeliveryModes; 1128 } 1129 1130 @Override 1131 public List<JWSAlgorithm> getBackChannelAuthenticationRequestJWSAlgs() { 1132 1133 return backChannelAuthRequestJWSAlgs; 1134 } 1135 1136 /** 1137 * Gets the supported JWS algorithms for CIBA requests. Corresponds to 1138 * the {@code backchannel_authentication_request_signing_alg_values_supported} 1139 * metadata field. 1140 * 1141 * @param backChannelAuthRequestJWSAlgs The supported JWS algorithms, 1142 * {@code null} if not specified. 1143 */ 1144 public void setBackChannelAuthenticationRequestJWSAlgs(final List<JWSAlgorithm> backChannelAuthRequestJWSAlgs) { 1145 1146 this.backChannelAuthRequestJWSAlgs = backChannelAuthRequestJWSAlgs; 1147 } 1148 1149 1150 @Override 1151 public boolean supportsBackChannelUserCodeParam() { 1152 1153 return backChannelUserCodeSupported; 1154 } 1155 1156 1157 /** 1158 * Sets the support for the {@code user_code} CIBA request parameter. 1159 * Corresponds to the {@code backchannel_user_code_parameter_supported} 1160 * metadata field. 1161 * 1162 * @param backChannelUserCodeSupported {@code true} if the 1163 * {@code user_code} parameter is 1164 * supported, else {@code false}. 1165 */ 1166 public void setSupportsBackChannelUserCodeParam(final boolean backChannelUserCodeSupported) { 1167 1168 this.backChannelUserCodeSupported = backChannelUserCodeSupported; 1169 } 1170 1171 1172 @Override 1173 public Object getCustomParameter(final String name) { 1174 1175 return customParameters.get(name); 1176 } 1177 1178 1179 @Override 1180 public URI getCustomURIParameter(final String name) { 1181 1182 try { 1183 return JSONObjectUtils.getURI(customParameters, name, null); 1184 } catch (ParseException e) { 1185 return null; 1186 } 1187 } 1188 1189 1190 /** 1191 * Sets the specified custom (not registered) parameter. 1192 * 1193 * @param name The parameter name. Must not be {@code null}. 1194 * @param value The parameter value, {@code null} if not specified. 1195 */ 1196 public void setCustomParameter(final String name, final Object value) { 1197 1198 if (REGISTERED_PARAMETER_NAMES.contains(name)) { 1199 throw new IllegalArgumentException("The " + name + " parameter is registered"); 1200 } 1201 1202 customParameters.put(name, value); 1203 } 1204 1205 1206 @Override 1207 public JSONObject getCustomParameters() { 1208 1209 return customParameters; 1210 } 1211 1212 1213 /** 1214 * Applies the OAuth 2.0 Authorisation Server metadata defaults where 1215 * no values have been specified. 1216 * 1217 * <ul> 1218 * <li>The response modes default to {@code ["query", "fragment"]}. 1219 * <li>The grant types default to {@code ["authorization_code", 1220 * "implicit"]}. 1221 * <li>The token endpoint authentication methods default to 1222 * {@code ["client_secret_basic"]}. 1223 * </ul> 1224 */ 1225 public void applyDefaults() { 1226 1227 if (rms == null) { 1228 rms = new ArrayList<>(2); 1229 rms.add(ResponseMode.QUERY); 1230 rms.add(ResponseMode.FRAGMENT); 1231 } 1232 1233 if (gts == null) { 1234 gts = new ArrayList<>(2); 1235 gts.add(GrantType.AUTHORIZATION_CODE); 1236 gts.add(GrantType.IMPLICIT); 1237 } 1238 1239 if (tokenEndpointAuthMethods == null) { 1240 tokenEndpointAuthMethods = new ArrayList<>(); 1241 tokenEndpointAuthMethods.add(ClientAuthenticationMethod.CLIENT_SECRET_BASIC); 1242 } 1243 } 1244 1245 1246 @Override 1247 public JSONObject toJSONObject() { 1248 JSONObject o = super.toJSONObject(); 1249 1250 // Mandatory fields 1251 o.put("issuer", issuer.getValue()); 1252 1253 1254 // Optional fields 1255 if (jwkSetURI != null) 1256 o.put("jwks_uri", jwkSetURI.toString()); 1257 1258 if (scope != null) 1259 o.put("scopes_supported", scope.toStringList()); 1260 1261 List<String> stringList; 1262 1263 if (rts != null) { 1264 1265 stringList = new ArrayList<>(rts.size()); 1266 1267 for (ResponseType rt: rts) 1268 stringList.add(rt.toString()); 1269 1270 o.put("response_types_supported", stringList); 1271 } 1272 1273 if (rms != null) { 1274 1275 stringList = new ArrayList<>(rms.size()); 1276 1277 for (ResponseMode rm: rms) 1278 stringList.add(rm.getValue()); 1279 1280 o.put("response_modes_supported", stringList); 1281 } 1282 1283 if (gts != null) { 1284 1285 stringList = new ArrayList<>(gts.size()); 1286 1287 for (GrantType gt: gts) 1288 stringList.add(gt.toString()); 1289 1290 o.put("grant_types_supported", stringList); 1291 } 1292 1293 if (codeChallengeMethods != null) { 1294 1295 stringList = new ArrayList<>(codeChallengeMethods.size()); 1296 1297 for (CodeChallengeMethod m: codeChallengeMethods) 1298 stringList.add(m.getValue()); 1299 1300 o.put("code_challenge_methods_supported", stringList); 1301 } 1302 1303 1304 if (tokenEndpointAuthMethods != null) { 1305 1306 stringList = new ArrayList<>(tokenEndpointAuthMethods.size()); 1307 1308 for (ClientAuthenticationMethod m: tokenEndpointAuthMethods) 1309 stringList.add(m.getValue()); 1310 1311 o.put("token_endpoint_auth_methods_supported", stringList); 1312 } 1313 1314 if (tokenEndpointJWSAlgs != null) { 1315 1316 stringList = new ArrayList<>(tokenEndpointJWSAlgs.size()); 1317 1318 for (JWSAlgorithm alg: tokenEndpointJWSAlgs) 1319 stringList.add(alg.getName()); 1320 1321 o.put("token_endpoint_auth_signing_alg_values_supported", stringList); 1322 } 1323 1324 if (introspectionEndpointAuthMethods != null) { 1325 1326 stringList = new ArrayList<>(introspectionEndpointAuthMethods.size()); 1327 1328 for (ClientAuthenticationMethod m: introspectionEndpointAuthMethods) 1329 stringList.add(m.getValue()); 1330 1331 o.put("introspection_endpoint_auth_methods_supported", stringList); 1332 } 1333 1334 if (introspectionEndpointJWSAlgs != null) { 1335 1336 stringList = new ArrayList<>(introspectionEndpointJWSAlgs.size()); 1337 1338 for (JWSAlgorithm alg: introspectionEndpointJWSAlgs) 1339 stringList.add(alg.getName()); 1340 1341 o.put("introspection_endpoint_auth_signing_alg_values_supported", stringList); 1342 } 1343 1344 if (revocationEndpointAuthMethods != null) { 1345 1346 stringList = new ArrayList<>(revocationEndpointAuthMethods.size()); 1347 1348 for (ClientAuthenticationMethod m: revocationEndpointAuthMethods) 1349 stringList.add(m.getValue()); 1350 1351 o.put("revocation_endpoint_auth_methods_supported", stringList); 1352 } 1353 1354 if (revocationEndpointJWSAlgs != null) { 1355 1356 stringList = new ArrayList<>(revocationEndpointJWSAlgs.size()); 1357 1358 for (JWSAlgorithm alg: revocationEndpointJWSAlgs) 1359 stringList.add(alg.getName()); 1360 1361 o.put("revocation_endpoint_auth_signing_alg_values_supported", stringList); 1362 } 1363 1364 if (requestObjectJWSAlgs != null) { 1365 1366 stringList = new ArrayList<>(requestObjectJWSAlgs.size()); 1367 1368 for (JWSAlgorithm alg: requestObjectJWSAlgs) 1369 stringList.add(alg.getName()); 1370 1371 o.put("request_object_signing_alg_values_supported", stringList); 1372 } 1373 1374 if (requestObjectJWEAlgs != null) { 1375 1376 stringList = new ArrayList<>(requestObjectJWEAlgs.size()); 1377 1378 for (JWEAlgorithm alg: requestObjectJWEAlgs) 1379 stringList.add(alg.getName()); 1380 1381 o.put("request_object_encryption_alg_values_supported", stringList); 1382 } 1383 1384 if (requestObjectJWEEncs != null) { 1385 1386 stringList = new ArrayList<>(requestObjectJWEEncs.size()); 1387 1388 for (EncryptionMethod m: requestObjectJWEEncs) 1389 stringList.add(m.getName()); 1390 1391 o.put("request_object_encryption_enc_values_supported", stringList); 1392 } 1393 1394 if (uiLocales != null) { 1395 1396 stringList = new ArrayList<>(uiLocales.size()); 1397 1398 for (LangTag l: uiLocales) 1399 stringList.add(l.toString()); 1400 1401 o.put("ui_locales_supported", stringList); 1402 } 1403 1404 if (serviceDocsURI != null) 1405 o.put("service_documentation", serviceDocsURI.toString()); 1406 1407 if (policyURI != null) 1408 o.put("op_policy_uri", policyURI.toString()); 1409 1410 if (tosURI != null) 1411 o.put("op_tos_uri", tosURI.toString()); 1412 1413 if (requestParamSupported) { 1414 o.put("request_parameter_supported", true); 1415 } 1416 1417 if (requestURIParamSupported) { 1418 o.put("request_uri_parameter_supported", true); 1419 } 1420 1421 if (requireRequestURIReg) { 1422 o.put("require_request_uri_registration", true); 1423 } 1424 1425 if (authzResponseIssParameterSupported) { 1426 o.put("authorization_response_iss_parameter_supported", true); 1427 } 1428 1429 if (mtlsEndpointAliases != null) 1430 o.put("mtls_endpoint_aliases", mtlsEndpointAliases.toJSONObject()); 1431 1432 if (tlsClientCertificateBoundAccessTokens) { 1433 o.put("tls_client_certificate_bound_access_tokens", true); 1434 } 1435 1436 // DPoP 1437 if (dPoPJWSAlgs != null) { 1438 1439 stringList = new ArrayList<>(dPoPJWSAlgs.size()); 1440 1441 for (JWSAlgorithm alg: dPoPJWSAlgs) 1442 stringList.add(alg.getName()); 1443 1444 o.put("dpop_signing_alg_values_supported", stringList); 1445 } 1446 1447 // JARM 1448 if (authzJWSAlgs != null) { 1449 1450 stringList = new ArrayList<>(authzJWSAlgs.size()); 1451 1452 for (JWSAlgorithm alg: authzJWSAlgs) 1453 stringList.add(alg.getName()); 1454 1455 o.put("authorization_signing_alg_values_supported", stringList); 1456 } 1457 1458 if (authzJWEAlgs != null) { 1459 1460 stringList = new ArrayList<>(authzJWEAlgs.size()); 1461 1462 for (JWEAlgorithm alg: authzJWEAlgs) 1463 stringList.add(alg.getName()); 1464 1465 o.put("authorization_encryption_alg_values_supported", stringList); 1466 } 1467 1468 if (authzJWEEncs != null) { 1469 1470 stringList = new ArrayList<>(authzJWEEncs.size()); 1471 1472 for (EncryptionMethod m: authzJWEEncs) 1473 stringList.add(m.getName()); 1474 1475 o.put("authorization_encryption_enc_values_supported", stringList); 1476 } 1477 1478 // PAR 1479 if (requirePAR) { 1480 o.put("require_pushed_authorization_requests", true); 1481 } 1482 1483 // Incremental authz 1484 if (CollectionUtils.isNotEmpty(incrementalAuthzTypes)) { 1485 stringList = new ArrayList<>(incrementalAuthzTypes.size()); 1486 for (ClientType clientType: incrementalAuthzTypes) { 1487 if (clientType != null) { 1488 stringList.add(clientType.name().toLowerCase()); 1489 } 1490 } 1491 o.put("incremental_authz_types_supported", stringList); 1492 } 1493 1494 // CIBA 1495 if (backChannelTokenDeliveryModes != null) { 1496 1497 stringList = new ArrayList<>(backChannelTokenDeliveryModes.size()); 1498 1499 for (BackChannelTokenDeliveryMode mode: backChannelTokenDeliveryModes) { 1500 if (mode != null) { 1501 stringList.add(mode.getValue()); 1502 } 1503 } 1504 1505 o.put("backchannel_token_delivery_modes_supported", stringList); 1506 } 1507 1508 if (backChannelAuthRequestJWSAlgs != null) { 1509 1510 stringList = new ArrayList<>(backChannelAuthRequestJWSAlgs.size()); 1511 1512 for (JWSAlgorithm alg : backChannelAuthRequestJWSAlgs) { 1513 if (alg != null) { 1514 stringList.add(alg.getName()); 1515 } 1516 } 1517 1518 o.put("backchannel_authentication_request_signing_alg_values_supported", stringList); 1519 } 1520 1521 if (backChannelUserCodeSupported) { 1522 o.put("backchannel_user_code_parameter_supported", true); 1523 } 1524 1525 // Append any custom (not registered) parameters 1526 o.putAll(customParameters); 1527 1528 return o; 1529 } 1530 1531 1532 /** 1533 * Parses an OAuth 2.0 Authorisation Server metadata from the specified 1534 * JSON object. 1535 * 1536 * @param jsonObject The JSON object to parse. Must not be 1537 * {@code null}. 1538 * 1539 * @return The OAuth 2.0 Authorisation Server metadata. 1540 * 1541 * @throws ParseException If the JSON object couldn't be parsed to an 1542 * OAuth 2.0 Authorisation Server metadata. 1543 */ 1544 public static AuthorizationServerMetadata parse(final JSONObject jsonObject) 1545 throws ParseException { 1546 1547 // Parse issuer and subject_types_supported first 1548 1549 Issuer issuer = new Issuer(JSONObjectUtils.getURI(jsonObject, "issuer").toString()); 1550 1551 AuthorizationServerEndpointMetadata asEndpoints = AuthorizationServerEndpointMetadata.parse(jsonObject); 1552 1553 AuthorizationServerMetadata as; 1554 1555 try { 1556 as = new AuthorizationServerMetadata(issuer); // validates issuer syntax 1557 } catch (IllegalArgumentException e) { 1558 throw new ParseException(e.getMessage(), e); 1559 } 1560 1561 // Endpoints 1562 as.setAuthorizationEndpointURI(asEndpoints.getAuthorizationEndpointURI()); 1563 as.setTokenEndpointURI(asEndpoints.getTokenEndpointURI()); 1564 as.setRegistrationEndpointURI(asEndpoints.getRegistrationEndpointURI()); 1565 as.setIntrospectionEndpointURI(asEndpoints.getIntrospectionEndpointURI()); 1566 as.setRevocationEndpointURI(asEndpoints.getRevocationEndpointURI()); 1567 as.setRequestObjectEndpoint(asEndpoints.getRequestObjectEndpoint()); 1568 as.setPushedAuthorizationRequestEndpointURI(asEndpoints.getPushedAuthorizationRequestEndpointURI()); 1569 as.setDeviceAuthorizationEndpointURI(asEndpoints.getDeviceAuthorizationEndpointURI()); 1570 as.setBackChannelAuthenticationEndpointURI(asEndpoints.getBackChannelAuthenticationEndpointURI()); 1571 as.jwkSetURI = JSONObjectUtils.getURI(jsonObject, "jwks_uri", null); 1572 1573 // AS capabilities 1574 if (jsonObject.get("scopes_supported") != null) { 1575 1576 as.scope = new Scope(); 1577 1578 for (String v: JSONObjectUtils.getStringArray(jsonObject, "scopes_supported")) { 1579 1580 if (v != null) 1581 as.scope.add(new Scope.Value(v)); 1582 } 1583 } 1584 1585 if (jsonObject.get("response_types_supported") != null) { 1586 1587 as.rts = new ArrayList<>(); 1588 1589 for (String v: JSONObjectUtils.getStringArray(jsonObject, "response_types_supported")) { 1590 1591 if (v != null) 1592 as.rts.add(ResponseType.parse(v)); 1593 } 1594 } 1595 1596 if (jsonObject.get("response_modes_supported") != null) { 1597 1598 as.rms = new ArrayList<>(); 1599 1600 for (String v: JSONObjectUtils.getStringArray(jsonObject, "response_modes_supported")) { 1601 1602 if (v != null) 1603 as.rms.add(new ResponseMode(v)); 1604 } 1605 } 1606 1607 if (jsonObject.get("grant_types_supported") != null) { 1608 1609 as.gts = new ArrayList<>(); 1610 1611 for (String v: JSONObjectUtils.getStringArray(jsonObject, "grant_types_supported")) { 1612 1613 if (v != null) 1614 as.gts.add(GrantType.parse(v)); 1615 } 1616 } 1617 1618 if (jsonObject.get("code_challenge_methods_supported") != null) { 1619 1620 as.codeChallengeMethods = new ArrayList<>(); 1621 1622 for (String v: JSONObjectUtils.getStringArray(jsonObject, "code_challenge_methods_supported")) { 1623 1624 if (v != null) 1625 as.codeChallengeMethods.add(CodeChallengeMethod.parse(v)); 1626 } 1627 } 1628 1629 if (jsonObject.get("token_endpoint_auth_methods_supported") != null) { 1630 1631 as.tokenEndpointAuthMethods = new ArrayList<>(); 1632 1633 for (String v: JSONObjectUtils.getStringArray(jsonObject, "token_endpoint_auth_methods_supported")) { 1634 1635 if (v != null) 1636 as.tokenEndpointAuthMethods.add(ClientAuthenticationMethod.parse(v)); 1637 } 1638 } 1639 1640 if (jsonObject.get("token_endpoint_auth_signing_alg_values_supported") != null) { 1641 1642 as.tokenEndpointJWSAlgs = new ArrayList<>(); 1643 1644 for (String v: JSONObjectUtils.getStringArray(jsonObject, "token_endpoint_auth_signing_alg_values_supported")) { 1645 1646 if (v != null && v.equals(Algorithm.NONE.getName())) 1647 throw new ParseException("The none algorithm is not accepted"); 1648 1649 if (v != null) 1650 as.tokenEndpointJWSAlgs.add(JWSAlgorithm.parse(v)); 1651 } 1652 } 1653 1654 if (jsonObject.get("introspection_endpoint_auth_methods_supported") != null) { 1655 1656 as.introspectionEndpointAuthMethods = new ArrayList<>(); 1657 1658 for (String v: JSONObjectUtils.getStringArray(jsonObject, "introspection_endpoint_auth_methods_supported")) { 1659 1660 if (v != null) 1661 as.introspectionEndpointAuthMethods.add(ClientAuthenticationMethod.parse(v)); 1662 } 1663 } 1664 1665 if (jsonObject.get("introspection_endpoint_auth_signing_alg_values_supported") != null) { 1666 1667 as.introspectionEndpointJWSAlgs = new ArrayList<>(); 1668 1669 for (String v: JSONObjectUtils.getStringArray(jsonObject, "introspection_endpoint_auth_signing_alg_values_supported")) { 1670 1671 if (v != null && v.equals(Algorithm.NONE.getName())) 1672 throw new ParseException("The none algorithm is not accepted"); 1673 1674 if (v != null) 1675 as.introspectionEndpointJWSAlgs.add(JWSAlgorithm.parse(v)); 1676 } 1677 } 1678 1679 if (jsonObject.get("revocation_endpoint_auth_methods_supported") != null) { 1680 1681 as.revocationEndpointAuthMethods = new ArrayList<>(); 1682 1683 for (String v: JSONObjectUtils.getStringArray(jsonObject, "revocation_endpoint_auth_methods_supported")) { 1684 1685 if (v != null) 1686 as.revocationEndpointAuthMethods.add(ClientAuthenticationMethod.parse(v)); 1687 } 1688 } 1689 1690 if (jsonObject.get("revocation_endpoint_auth_signing_alg_values_supported") != null) { 1691 1692 as.revocationEndpointJWSAlgs = new ArrayList<>(); 1693 1694 for (String v: JSONObjectUtils.getStringArray(jsonObject, "revocation_endpoint_auth_signing_alg_values_supported")) { 1695 1696 if (v != null && v.equals(Algorithm.NONE.getName())) 1697 throw new ParseException("The none algorithm is not accepted"); 1698 1699 if (v != null) 1700 as.revocationEndpointJWSAlgs.add(JWSAlgorithm.parse(v)); 1701 } 1702 } 1703 1704 1705 // Request object 1706 if (jsonObject.get("request_object_signing_alg_values_supported") != null) { 1707 1708 as.requestObjectJWSAlgs = new ArrayList<>(); 1709 1710 for (String v: JSONObjectUtils.getStringArray(jsonObject, "request_object_signing_alg_values_supported")) { 1711 1712 if (v != null) 1713 as.requestObjectJWSAlgs.add(JWSAlgorithm.parse(v)); 1714 } 1715 } 1716 1717 1718 if (jsonObject.get("request_object_encryption_alg_values_supported") != null) { 1719 1720 as.requestObjectJWEAlgs = new ArrayList<>(); 1721 1722 for (String v: JSONObjectUtils.getStringArray(jsonObject, "request_object_encryption_alg_values_supported")) { 1723 1724 if (v != null) 1725 as.requestObjectJWEAlgs.add(JWEAlgorithm.parse(v)); 1726 } 1727 } 1728 1729 1730 if (jsonObject.get("request_object_encryption_enc_values_supported") != null) { 1731 1732 as.requestObjectJWEEncs = new ArrayList<>(); 1733 1734 for (String v: JSONObjectUtils.getStringArray(jsonObject, "request_object_encryption_enc_values_supported")) { 1735 1736 if (v != null) 1737 as.requestObjectJWEEncs.add(EncryptionMethod.parse(v)); 1738 } 1739 } 1740 1741 1742 // Misc 1743 1744 if (jsonObject.get("ui_locales_supported") != null) { 1745 1746 as.uiLocales = new ArrayList<>(); 1747 1748 for (String v : JSONObjectUtils.getStringArray(jsonObject, "ui_locales_supported")) { 1749 1750 if (v != null) { 1751 1752 try { 1753 as.uiLocales.add(LangTag.parse(v)); 1754 1755 } catch (LangTagException e) { 1756 1757 throw new ParseException("Invalid ui_locales_supported field: " + e.getMessage(), e); 1758 } 1759 } 1760 } 1761 } 1762 1763 if (jsonObject.get("service_documentation") != null) { 1764 try { 1765 as.setServiceDocsURI(JSONObjectUtils.getURI(jsonObject, "service_documentation")); 1766 } catch (IllegalArgumentException e) { 1767 throw new ParseException("Illegal service_documentation parameter: " + e.getMessage()); 1768 } 1769 } 1770 1771 if (jsonObject.get("op_policy_uri") != null) { 1772 try { 1773 as.setPolicyURI(JSONObjectUtils.getURI(jsonObject, "op_policy_uri")); 1774 } catch (IllegalArgumentException e) { 1775 throw new ParseException("Illegal op_policy_uri parameter: " + e.getMessage()); 1776 } 1777 } 1778 1779 if (jsonObject.get("op_tos_uri") != null) { 1780 try { 1781 as.setTermsOfServiceURI(JSONObjectUtils.getURI(jsonObject, "op_tos_uri")); 1782 } catch (IllegalArgumentException e) { 1783 throw new ParseException("Illegal op_tos_uri parameter: " + e.getMessage()); 1784 } 1785 } 1786 1787 if (jsonObject.get("request_parameter_supported") != null) 1788 as.requestParamSupported = JSONObjectUtils.getBoolean(jsonObject, "request_parameter_supported"); 1789 1790 if (jsonObject.get("request_uri_parameter_supported") != null) 1791 as.requestURIParamSupported = JSONObjectUtils.getBoolean(jsonObject, "request_uri_parameter_supported"); 1792 1793 if (jsonObject.get("require_request_uri_registration") != null) 1794 as.requireRequestURIReg = JSONObjectUtils.getBoolean(jsonObject, "require_request_uri_registration"); 1795 1796 if (jsonObject.get("authorization_response_iss_parameter_supported") != null) 1797 as.authzResponseIssParameterSupported = JSONObjectUtils.getBoolean(jsonObject, "authorization_response_iss_parameter_supported"); 1798 1799 if (jsonObject.get("mtls_endpoint_aliases") != null) 1800 as.mtlsEndpointAliases = AuthorizationServerEndpointMetadata.parse(JSONObjectUtils.getJSONObject(jsonObject, "mtls_endpoint_aliases")); 1801 1802 if (jsonObject.get("tls_client_certificate_bound_access_tokens") != null) 1803 as.tlsClientCertificateBoundAccessTokens = JSONObjectUtils.getBoolean(jsonObject, "tls_client_certificate_bound_access_tokens"); 1804 1805 // DPoP 1806 if (jsonObject.get("dpop_signing_alg_values_supported") != null) { 1807 1808 as.dPoPJWSAlgs = new ArrayList<>(); 1809 1810 for (String v: JSONObjectUtils.getStringArray(jsonObject, "dpop_signing_alg_values_supported")) { 1811 1812 if (v != null) 1813 as.dPoPJWSAlgs.add(JWSAlgorithm.parse(v)); 1814 } 1815 } 1816 1817 // JARM 1818 if (jsonObject.get("authorization_signing_alg_values_supported") != null) { 1819 1820 as.authzJWSAlgs = new ArrayList<>(); 1821 1822 for (String v: JSONObjectUtils.getStringArray(jsonObject, "authorization_signing_alg_values_supported")) { 1823 1824 if (v != null) 1825 as.authzJWSAlgs.add(JWSAlgorithm.parse(v)); 1826 } 1827 } 1828 1829 1830 if (jsonObject.get("authorization_encryption_alg_values_supported") != null) { 1831 1832 as.authzJWEAlgs = new ArrayList<>(); 1833 1834 for (String v: JSONObjectUtils.getStringArray(jsonObject, "authorization_encryption_alg_values_supported")) { 1835 1836 if (v != null) 1837 as.authzJWEAlgs.add(JWEAlgorithm.parse(v)); 1838 } 1839 } 1840 1841 1842 if (jsonObject.get("authorization_encryption_enc_values_supported") != null) { 1843 1844 as.authzJWEEncs = new ArrayList<>(); 1845 1846 for (String v: JSONObjectUtils.getStringArray(jsonObject, "authorization_encryption_enc_values_supported")) { 1847 1848 if (v != null) 1849 as.authzJWEEncs.add(EncryptionMethod.parse(v)); 1850 } 1851 } 1852 1853 // PAR 1854 if (jsonObject.get("require_pushed_authorization_requests") != null) { 1855 as.requiresPushedAuthorizationRequests(JSONObjectUtils.getBoolean(jsonObject, "require_pushed_authorization_requests")); 1856 } 1857 1858 // Incremental authz 1859 if (jsonObject.get("incremental_authz_types_supported") != null) { 1860 1861 as.incrementalAuthzTypes = new ArrayList<>(); 1862 1863 for (String v: JSONObjectUtils.getStringArray(jsonObject, "incremental_authz_types_supported")) { 1864 1865 if (v != null) { 1866 ClientType clientType; 1867 try { 1868 clientType = ClientType.valueOf(v.toUpperCase()); 1869 } catch (IllegalArgumentException e) { 1870 throw new ParseException("Illegal client type in incremental_authz_types_supported field: " + v); 1871 } 1872 as.incrementalAuthzTypes.add(clientType); 1873 } 1874 } 1875 } 1876 1877 // CIBA 1878 if (jsonObject.get("backchannel_token_delivery_modes_supported") != null) { 1879 1880 as.backChannelTokenDeliveryModes = new ArrayList<>(); 1881 1882 for (String v : JSONObjectUtils.getStringArray(jsonObject, "backchannel_token_delivery_modes_supported")) { 1883 1884 if (v != null) 1885 as.backChannelTokenDeliveryModes.add(BackChannelTokenDeliveryMode.parse(v)); 1886 } 1887 } 1888 1889 if (jsonObject.get("backchannel_authentication_request_signing_alg_values_supported") != null) { 1890 1891 as.backChannelAuthRequestJWSAlgs = new ArrayList<>(); 1892 1893 for (String v : JSONObjectUtils.getStringArray(jsonObject, "backchannel_authentication_request_signing_alg_values_supported")) { 1894 1895 if (v != null) 1896 as.backChannelAuthRequestJWSAlgs.add(JWSAlgorithm.parse(v)); 1897 } 1898 } 1899 1900 if (jsonObject.get("backchannel_user_code_parameter_supported") != null) { 1901 as.backChannelUserCodeSupported = JSONObjectUtils.getBoolean(jsonObject, "backchannel_user_code_parameter_supported"); 1902 } 1903 1904 // Parse custom (not registered) parameters 1905 JSONObject customParams = new JSONObject(jsonObject); 1906 customParams.keySet().removeAll(REGISTERED_PARAMETER_NAMES); 1907 for (Map.Entry<String,Object> customEntry: customParams.entrySet()) { 1908 as.setCustomParameter(customEntry.getKey(), customEntry.getValue()); 1909 } 1910 1911 return as; 1912 } 1913 1914 1915 /** 1916 * Parses an OAuth 2.0 Authorisation Server metadata from the specified 1917 * JSON object string. 1918 * 1919 * @param s The JSON object sting to parse. Must not be {@code null}. 1920 * 1921 * @return The OAuth 2.0 Authorisation Server metadata. 1922 * 1923 * @throws ParseException If the JSON object string couldn't be parsed 1924 * to an OAuth 2.0 Authorisation Server 1925 * metadata. 1926 */ 1927 public static AuthorizationServerMetadata parse(final String s) 1928 throws ParseException { 1929 1930 return parse(JSONObjectUtils.parse(s)); 1931 } 1932 1933 1934 /** 1935 * Resolves OAuth 2.0 authorisation server metadata URL from the 1936 * specified issuer identifier. 1937 * 1938 * @param issuer The issuer identifier. Must represent a valid HTTPS or 1939 * HTTP URL. Must not be {@code null}. 1940 * 1941 * @return The OAuth 2.0 authorisation server metadata URL. 1942 * 1943 * @throws GeneralException If the issuer identifier is invalid. 1944 */ 1945 public static URL resolveURL(final Issuer issuer) 1946 throws GeneralException { 1947 1948 try { 1949 URL issuerURL = new URL(issuer.getValue()); 1950 1951 // Validate but don't insist on HTTPS 1952 if (issuerURL.getQuery() != null && ! issuerURL.getQuery().trim().isEmpty()) { 1953 throw new GeneralException("The issuer identifier must not contain a query component"); 1954 } 1955 1956 if (issuerURL.getPath() != null && issuerURL.getPath().endsWith("/")) { 1957 return new URL(issuerURL + ".well-known/oauth-authorization-server"); 1958 } else { 1959 return new URL(issuerURL + "/.well-known/oauth-authorization-server"); 1960 } 1961 1962 } catch (MalformedURLException e) { 1963 throw new GeneralException("The issuer identifier doesn't represent a valid URL: " + e.getMessage(), e); 1964 } 1965 } 1966 1967 1968 /** 1969 * Resolves OAuth 2.0 authorisation server metadata from the specified 1970 * issuer identifier. The metadata is downloaded by HTTP GET from 1971 * {@code [issuer-url]/.well-known/oauth-authorization-server}. 1972 * 1973 * @param issuer The issuer identifier. Must represent a valid HTTPS or 1974 * HTTP URL. Must not be {@code null}. 1975 * 1976 * @return The OAuth 2.0 authorisation server metadata. 1977 * 1978 * @throws GeneralException If the issuer identifier or the downloaded 1979 * metadata are invalid. 1980 * @throws IOException On a HTTP exception. 1981 */ 1982 public static AuthorizationServerMetadata resolve(final Issuer issuer) 1983 throws GeneralException, IOException { 1984 1985 return resolve(issuer, 0, 0); 1986 } 1987 1988 1989 /** 1990 * Resolves OAuth 2.0 authorisation server metadata from the specified 1991 * issuer identifier. The metadata is downloaded by HTTP GET from 1992 * {@code [issuer-url]/.well-known/oauth-authorization-server}. 1993 * 1994 * @param issuer The issuer identifier. Must represent a valid 1995 * HTTPS or HTTP URL. Must not be {@code null}. 1996 * @param connectTimeout The HTTP connect timeout, in milliseconds. 1997 * Zero implies no timeout. Must not be negative. 1998 * @param readTimeout The HTTP response read timeout, in 1999 * milliseconds. Zero implies no timeout. Must 2000 * not be negative. 2001 * 2002 * @return The OAuth 2.0 authorisation server metadata. 2003 * 2004 * @throws GeneralException If the issuer identifier or the downloaded 2005 * metadata are invalid. 2006 * @throws IOException On a HTTP exception. 2007 */ 2008 public static AuthorizationServerMetadata resolve(final Issuer issuer, 2009 final int connectTimeout, 2010 final int readTimeout) 2011 throws GeneralException, IOException { 2012 2013 URL configURL = resolveURL(issuer); 2014 2015 HTTPRequest httpRequest = new HTTPRequest(HTTPRequest.Method.GET, configURL); 2016 httpRequest.setConnectTimeout(connectTimeout); 2017 httpRequest.setReadTimeout(readTimeout); 2018 2019 HTTPResponse httpResponse = httpRequest.send(); 2020 2021 if (httpResponse.getStatusCode() != 200) { 2022 throw new IOException("Couldn't download OAuth 2.0 Authorization Server metadata from " + configURL + 2023 ": Status code " + httpResponse.getStatusCode()); 2024 } 2025 2026 JSONObject jsonObject = httpResponse.getContentAsJSONObject(); 2027 2028 AuthorizationServerMetadata as = AuthorizationServerMetadata.parse(jsonObject); 2029 2030 if (! issuer.equals(as.issuer)) { 2031 throw new GeneralException("The returned issuer doesn't match the expected: " + as.getIssuer()); 2032 } 2033 2034 return as; 2035 } 2036}