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