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