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