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.openid.connect.sdk; 019 020 021import java.net.URI; 022import java.util.*; 023 024import net.jcip.annotations.Immutable; 025 026import com.nimbusds.jwt.JWT; 027import com.nimbusds.jwt.JWTClaimsSet; 028import com.nimbusds.jwt.JWTParser; 029import com.nimbusds.langtag.LangTag; 030import com.nimbusds.langtag.LangTagException; 031import com.nimbusds.langtag.LangTagUtils; 032import com.nimbusds.oauth2.sdk.*; 033import com.nimbusds.oauth2.sdk.dpop.JWKThumbprintConfirmation; 034import com.nimbusds.oauth2.sdk.http.HTTPRequest; 035import com.nimbusds.oauth2.sdk.id.ClientID; 036import com.nimbusds.oauth2.sdk.id.State; 037import com.nimbusds.oauth2.sdk.pkce.CodeChallenge; 038import com.nimbusds.oauth2.sdk.pkce.CodeChallengeMethod; 039import com.nimbusds.oauth2.sdk.pkce.CodeVerifier; 040import com.nimbusds.oauth2.sdk.util.*; 041import com.nimbusds.openid.connect.sdk.claims.ACR; 042import com.nimbusds.openid.connect.sdk.federation.trust.TrustChain; 043 044 045/** 046 * OpenID Connect authentication request. Intended to authenticate an end-user 047 * and request the end-user's authorisation to release information to the 048 * client. Supports custom request parameters. 049 * 050 * <p>Example HTTP request (code flow): 051 * 052 * <pre> 053 * https://server.example.com/op/authorize? 054 * response_type=code%20id_token 055 * &client_id=s6BhdRkqt3 056 * &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb 057 * &scope=openid 058 * &nonce=n-0S6_WzA2Mj 059 * &state=af0ifjsldkj 060 * </pre> 061 * 062 * <p>Related specifications: 063 * 064 * <ul> 065 * <li>OpenID Connect Core 1.0, section 3.1.2.1. 066 * <li>Proof Key for Code Exchange by OAuth Public Clients (RFC 7636). 067 * <li>Resource Indicators for OAuth 2.0 (RFC 8707) 068 * <li>The OAuth 2.0 Authorization Framework: JWT Secured Authorization 069 * Request (JAR) (RFC 9101) 070 * <li>Financial-grade API: JWT Secured Authorization Response Mode for 071 * OAuth 2.0 (JARM) 072 * <li>OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer 073 * (DPoP) (draft-ietf-oauth-dpop-11). 074 * <li>OpenID Connect Federation 1.0, section 10.1. 075 * <li>OpenID Connect for Identity Assurance 1.0, section 8. 076 * </ul> 077 */ 078@Immutable 079public class AuthenticationRequest extends AuthorizationRequest { 080 081 082 /** 083 * The purpose string parameter minimal length. 084 */ 085 public static final int PURPOSE_MIN_LENGTH = 3; 086 087 088 /** 089 * The purpose string parameter maximum length. 090 */ 091 public static final int PURPOSE_MAX_LENGTH = 300; 092 093 094 /** 095 * The registered parameter names. 096 */ 097 private static final Set<String> REGISTERED_PARAMETER_NAMES; 098 099 100 static { 101 102 Set<String> p = new HashSet<>(AuthorizationRequest.getRegisteredParameterNames()); 103 104 p.add("nonce"); 105 p.add("display"); 106 p.add("max_age"); 107 p.add("ui_locales"); 108 p.add("claims_locales"); 109 p.add("id_token_hint"); 110 p.add("login_hint"); 111 p.add("acr_values"); 112 p.add("claims"); 113 p.add("purpose"); 114 115 REGISTERED_PARAMETER_NAMES = Collections.unmodifiableSet(p); 116 } 117 118 119 /** 120 * The nonce (required for implicit flow (unless in JAR), optional for 121 * code flow). 122 */ 123 private final Nonce nonce; 124 125 126 /** 127 * The requested display type (optional). 128 */ 129 private final Display display; 130 131 132 /** 133 * The required maximum authentication age, in seconds, -1 if not 134 * specified, zero implies prompt=login (optional). 135 */ 136 private final int maxAge; 137 138 139 /** 140 * The end-user's preferred languages and scripts for the user 141 * interface (optional). 142 */ 143 private final List<LangTag> uiLocales; 144 145 146 /** 147 * The end-user's preferred languages and scripts for claims being 148 * returned (optional). 149 */ 150 private final List<LangTag> claimsLocales; 151 152 153 /** 154 * Previously issued ID Token passed to the authorisation server as a 155 * hint about the end-user's current or past authenticated session with 156 * the client (optional). Should be present when {@code prompt=none} is 157 * used. 158 */ 159 private final JWT idTokenHint; 160 161 162 /** 163 * Hint to the authorisation server about the login identifier the 164 * end-user may use to log in (optional). 165 */ 166 private final String loginHint; 167 168 169 /** 170 * Requested Authentication Context Class Reference values (optional). 171 */ 172 private final List<ACR> acrValues; 173 174 175 /** 176 * Individual claims to be returned (optional). 177 */ 178 private final OIDCClaimsRequest claims; 179 180 181 /** 182 * The transaction specific purpose, for use in OpenID Connect Identity 183 * Assurance. 184 */ 185 private final String purpose; 186 187 188 /** 189 * Builder for constructing OpenID Connect authentication requests. 190 */ 191 public static class Builder { 192 193 194 /** 195 * The endpoint URI (optional). 196 */ 197 private URI uri; 198 199 200 /** 201 * The response type (required unless in JAR). 202 */ 203 private ResponseType rt; 204 205 206 /** 207 * The client identifier (required unless in JAR). 208 */ 209 private final ClientID clientID; 210 211 212 /** 213 * The redirection URI where the response will be sent 214 * (required unless in JAR). 215 */ 216 private URI redirectURI; 217 218 219 /** 220 * The scope (required unless in JAR). 221 */ 222 private Scope scope; 223 224 225 /** 226 * The opaque value to maintain state between the request and 227 * the callback (recommended). 228 */ 229 private State state; 230 231 232 /** 233 * The nonce (required for implicit flow (unless in JAR), 234 * optional for code flow). 235 */ 236 private Nonce nonce; 237 238 239 /** 240 * The requested display type (optional). 241 */ 242 private Display display; 243 244 245 /** 246 * The requested prompt (optional). 247 */ 248 private Prompt prompt; 249 250 251 /** 252 * The DPoP JWK SHA-256 thumbprint (optional). 253 */ 254 private JWKThumbprintConfirmation dpopJKT; 255 256 257 /** 258 * The OpenID Connect Federation 1.0 trust chain (optional). 259 */ 260 private TrustChain trustChain; 261 262 263 /** 264 * The required maximum authentication age, in seconds, -1 if 265 * not specified, zero implies prompt=login (optional). 266 */ 267 private int maxAge = -1; 268 269 270 /** 271 * The end-user's preferred languages and scripts for the user 272 * interface (optional). 273 */ 274 private List<LangTag> uiLocales; 275 276 277 /** 278 * The end-user's preferred languages and scripts for claims 279 * being returned (optional). 280 */ 281 private List<LangTag> claimsLocales; 282 283 284 /** 285 * Previously issued ID Token passed to the authorisation 286 * server as a hint about the end-user's current or past 287 * authenticated session with the client (optional). Should be 288 * present when {@code prompt=none} is used. 289 */ 290 private JWT idTokenHint; 291 292 293 /** 294 * Hint to the authorisation server about the login identifier 295 * the end-user may use to log in (optional). 296 */ 297 private String loginHint; 298 299 300 /** 301 * Requested Authentication Context Class Reference values 302 * (optional). 303 */ 304 private List<ACR> acrValues; 305 306 307 /** 308 * Individual claims to be returned (optional). 309 */ 310 private OIDCClaimsRequest claims; 311 312 313 /** 314 * The transaction specific purpose (optional). 315 */ 316 private String purpose; 317 318 319 /** 320 * Request object (optional). 321 */ 322 private JWT requestObject; 323 324 325 /** 326 * Request object URI (optional). 327 */ 328 private URI requestURI; 329 330 331 /** 332 * The response mode (optional). 333 */ 334 private ResponseMode rm; 335 336 337 /** 338 * The authorisation code challenge for PKCE (optional). 339 */ 340 private CodeChallenge codeChallenge; 341 342 343 /** 344 * The authorisation code challenge method for PKCE (optional). 345 */ 346 private CodeChallengeMethod codeChallengeMethod; 347 348 349 /** 350 * The resource URI(s) (optional). 351 */ 352 private List<URI> resources; 353 354 355 /** 356 * Indicates incremental authorisation (optional). 357 */ 358 private boolean includeGrantedScopes; 359 360 361 /** 362 * Custom parameters. 363 */ 364 private final Map<String,List<String>> customParams = new HashMap<>(); 365 366 367 /** 368 * Creates a new OpenID Connect authentication request builder. 369 * 370 * @param rt The response type. Corresponds to the 371 * {@code response_type} parameter. Must 372 * specify a valid OpenID Connect response 373 * type. Must not be {@code null}. 374 * @param scope The request scope. Corresponds to the 375 * {@code scope} parameter. Must contain an 376 * {@link OIDCScopeValue#OPENID openid 377 * value}. Must not be {@code null}. 378 * @param clientID The client identifier. Corresponds to the 379 * {@code client_id} parameter. Must not be 380 * {@code null}. 381 * @param redirectURI The redirection URI. Corresponds to the 382 * {@code redirect_uri} parameter. Must not 383 * be {@code null} unless set by means of 384 * the optional {@code request_object} / 385 * {@code request_uri} parameter. 386 */ 387 public Builder(final ResponseType rt, 388 final Scope scope, 389 final ClientID clientID, 390 final URI redirectURI) { 391 392 if (rt == null) 393 throw new IllegalArgumentException("The response type must not be null"); 394 395 OIDCResponseTypeValidator.validate(rt); 396 397 this.rt = rt; 398 399 if (scope == null) 400 throw new IllegalArgumentException("The scope must not be null"); 401 402 if (! scope.contains(OIDCScopeValue.OPENID)) 403 throw new IllegalArgumentException("The scope must include an \"openid\" value"); 404 405 this.scope = scope; 406 407 if (clientID == null) 408 throw new IllegalArgumentException("The client ID must not be null"); 409 410 this.clientID = clientID; 411 412 // Check presence at build time 413 this.redirectURI = redirectURI; 414 } 415 416 417 /** 418 * Creates a new JWT secured OpenID Connect authentication 419 * request (JAR) builder. 420 * 421 * @param requestObject The request object. Must not be 422 * {@code null}. 423 * @param clientID The client ID. Must not be 424 * {@code null}. 425 */ 426 public Builder(final JWT requestObject, final ClientID clientID) { 427 428 if (requestObject == null) 429 throw new IllegalArgumentException("The request object must not be null"); 430 431 this.requestObject = requestObject; 432 433 if (clientID == null) 434 throw new IllegalArgumentException("The client ID must not be null"); 435 436 this.clientID = clientID; 437 } 438 439 440 /** 441 * Creates a new JWT secured OpenID Connect authentication 442 * request (JAR) builder. 443 * 444 * @param requestURI The request object URI. Must not be 445 * {@code null}. 446 * @param clientID The client ID. Must not be {@code null}. 447 */ 448 public Builder(final URI requestURI, final ClientID clientID) { 449 450 if (requestURI == null) 451 throw new IllegalArgumentException("The request URI must not be null"); 452 453 this.requestURI = requestURI; 454 455 if (clientID == null) 456 throw new IllegalArgumentException("The client ID must not be null"); 457 458 this.clientID = clientID; 459 } 460 461 462 /** 463 * Creates a new OpenID Connect authentication request builder 464 * from the specified request. 465 * 466 * @param request The OpenID Connect authentication request. 467 * Must not be {@code null}. 468 */ 469 public Builder(final AuthenticationRequest request) { 470 uri = request.getEndpointURI(); 471 rt = request.getResponseType(); 472 clientID = request.getClientID(); 473 redirectURI = request.getRedirectionURI(); 474 scope = request.getScope(); 475 state = request.getState(); 476 nonce = request.getNonce(); 477 display = request.getDisplay(); 478 prompt = request.getPrompt(); 479 dpopJKT = request.getDPoPJWKThumbprintConfirmation(); 480 trustChain = request.getTrustChain(); 481 maxAge = request.getMaxAge(); 482 uiLocales = request.getUILocales(); 483 claimsLocales = request.getClaimsLocales(); 484 idTokenHint = request.getIDTokenHint(); 485 loginHint = request.getLoginHint(); 486 acrValues = request.getACRValues(); 487 claims = request.getOIDCClaims(); 488 purpose = request.getPurpose(); 489 requestObject = request.getRequestObject(); 490 requestURI = request.getRequestURI(); 491 rm = request.getResponseMode(); 492 codeChallenge = request.getCodeChallenge(); 493 codeChallengeMethod = request.getCodeChallengeMethod(); 494 resources = request.getResources(); 495 includeGrantedScopes = request.includeGrantedScopes(); 496 customParams.putAll(request.getCustomParameters()); 497 } 498 499 500 /** 501 * Sets the response type. Corresponds to the 502 * {@code response_type} parameter. 503 * 504 * @param rt The response type. Must not be {@code null}. 505 * 506 * @return This builder. 507 */ 508 public Builder responseType(final ResponseType rt) { 509 510 if (rt == null) 511 throw new IllegalArgumentException("The response type must not be null"); 512 513 this.rt = rt; 514 return this; 515 } 516 517 518 /** 519 * Sets the scope. Corresponds to the {@code scope} parameter. 520 * 521 * @param scope The scope. Must not be {@code null}. 522 * 523 * @return This builder. 524 */ 525 public Builder scope(final Scope scope) { 526 527 if (scope == null) 528 throw new IllegalArgumentException("The scope must not be null"); 529 530 if (! scope.contains(OIDCScopeValue.OPENID)) 531 throw new IllegalArgumentException("The scope must include an openid value"); 532 533 this.scope = scope; 534 return this; 535 } 536 537 538 /** 539 * Sets the redirection URI. Corresponds to the 540 * {@code redirection_uri} parameter. 541 * 542 * @param redirectURI The redirection URI. Must not be 543 * {@code null}. 544 * 545 * @return This builder. 546 */ 547 public Builder redirectionURI(final URI redirectURI) { 548 549 if (redirectURI == null) 550 throw new IllegalArgumentException("The redirection URI must not be null"); 551 552 this.redirectURI = redirectURI; 553 return this; 554 } 555 556 557 /** 558 * Sets the state. Corresponds to the recommended {@code state} 559 * parameter. 560 * 561 * @param state The state, {@code null} if not specified. 562 * 563 * @return This builder. 564 */ 565 public Builder state(final State state) { 566 this.state = state; 567 return this; 568 } 569 570 571 /** 572 * Sets the URI of the endpoint (HTTP or HTTPS) for which the 573 * request is intended. 574 * 575 * @param uri The endpoint URI, {@code null} if not specified. 576 * 577 * @return This builder. 578 */ 579 public Builder endpointURI(final URI uri) { 580 this.uri = uri; 581 return this; 582 } 583 584 585 /** 586 * Sets the nonce. Corresponds to the conditionally optional 587 * {@code nonce} parameter. 588 * 589 * @param nonce The nonce, {@code null} if not specified. 590 * 591 * @return This builder. 592 */ 593 public Builder nonce(final Nonce nonce) { 594 this.nonce = nonce; 595 return this; 596 } 597 598 599 /** 600 * Sets the requested display type. Corresponds to the optional 601 * {@code display} parameter. 602 * 603 * @param display The requested display type, {@code null} if 604 * not specified. 605 * 606 * @return This builder. 607 */ 608 public Builder display(final Display display) { 609 this.display = display; 610 return this; 611 } 612 613 614 /** 615 * Sets the requested prompt. Corresponds to the optional 616 * {@code prompt} parameter. 617 * 618 * @param prompt The requested prompt, {@code null} if not 619 * specified. 620 * 621 * @return This builder. 622 */ 623 public Builder prompt(final Prompt prompt) { 624 this.prompt = prompt; 625 return this; 626 } 627 628 629 /** 630 * Sets the requested prompt. Corresponds to the optional 631 * {@code prompt} parameter. 632 * 633 * @param promptType The requested prompt types, {@code null} 634 * if not specified. 635 * 636 * @return This builder. 637 */ 638 public Builder prompt(final Prompt.Type ... promptType) { 639 if (promptType.length == 1 && promptType[0] == null) { 640 return prompt((Prompt)null); 641 } else { 642 return prompt(new Prompt(promptType)); 643 } 644 } 645 646 647 /** 648 * Sets the DPoP JWK SHA-256 thumbprint. Corresponds to the 649 * optional {@code dpop_jkt} parameter. 650 * 651 * @param dpopJKT DPoP JWK SHA-256 thumbprint, {@code null} if 652 * not specified. 653 * 654 * @return This builder. 655 */ 656 public Builder dPoPJWKThumbprintConfirmation(final JWKThumbprintConfirmation dpopJKT) { 657 this.dpopJKT = dpopJKT; 658 return this; 659 } 660 661 662 /** 663 * Sets the OpenID Connect Federation 1.0 trust chain. 664 * Corresponds to the optional {@code trust_chain} parameter. 665 * 666 * @param trustChain The trust chain, {@code null} if not 667 * specified. 668 * 669 * @return This builder. 670 */ 671 public Builder trustChain(final TrustChain trustChain) { 672 this.trustChain = trustChain; 673 return this; 674 } 675 676 677 /** 678 * Sets the required maximum authentication age. Corresponds to 679 * the optional {@code max_age} parameter. 680 * 681 * @param maxAge The maximum authentication age, in seconds; 0 682 * if not specified. 683 * 684 * @return This builder. 685 */ 686 public Builder maxAge(final int maxAge) { 687 this.maxAge = maxAge; 688 return this; 689 } 690 691 692 /** 693 * Sets the end-user's preferred languages and scripts for the 694 * user interface, ordered by preference. Corresponds to the 695 * optional {@code ui_locales} parameter. 696 * 697 * @param uiLocales The preferred UI locales, {@code null} if 698 * not specified. 699 * 700 * @return This builder. 701 */ 702 public Builder uiLocales(final List<LangTag> uiLocales) { 703 this.uiLocales = uiLocales; 704 return this; 705 } 706 707 708 /** 709 * Sets the end-user's preferred languages and scripts for the 710 * claims being returned, ordered by preference. Corresponds to 711 * the optional {@code claims_locales} parameter. 712 * 713 * @param claimsLocales The preferred claims locales, 714 * {@code null} if not specified. 715 * 716 * @return This builder. 717 */ 718 public Builder claimsLocales(final List<LangTag> claimsLocales) { 719 this.claimsLocales = claimsLocales; 720 return this; 721 } 722 723 724 /** 725 * Sets the ID Token hint. Corresponds to the conditionally 726 * optional {@code id_token_hint} parameter. 727 * 728 * @param idTokenHint The ID Token hint, {@code null} if not 729 * specified. 730 * 731 * @return This builder. 732 */ 733 public Builder idTokenHint(final JWT idTokenHint) { 734 this.idTokenHint = idTokenHint; 735 return this; 736 } 737 738 739 /** 740 * Sets the login hint. Corresponds to the optional 741 * {@code login_hint} parameter. 742 * 743 * @param loginHint The login hint, {@code null} if not 744 * specified. 745 * 746 * @return This builder. 747 */ 748 public Builder loginHint(final String loginHint) { 749 this.loginHint = loginHint; 750 return this; 751 } 752 753 754 /** 755 * Sets the requested Authentication Context Class Reference 756 * values. Corresponds to the optional {@code acr_values} 757 * parameter. 758 * 759 * @param acrValues The requested ACR values, {@code null} if 760 * not specified. 761 * 762 * @return This builder. 763 */ 764 public Builder acrValues(final List<ACR> acrValues) { 765 this.acrValues = acrValues; 766 return this; 767 } 768 769 770 /** 771 * Sets the individual claims to be returned. Corresponds to 772 * the optional {@code claims} parameter. 773 * 774 * @see #claims(OIDCClaimsRequest) 775 * 776 * @param claims The individual claims to be returned, 777 * {@code null} if not specified. 778 * 779 * @return This builder. 780 */ 781 @Deprecated 782 public Builder claims(final ClaimsRequest claims) { 783 784 if (claims == null) { 785 this.claims = null; 786 } else { 787 try { 788 this.claims = OIDCClaimsRequest.parse(claims.toJSONObject()); 789 } catch (ParseException e) { 790 // Should never happen 791 throw new IllegalArgumentException("Invalid claims: " + e.getMessage(), e); 792 } 793 } 794 return this; 795 } 796 797 798 /** 799 * Sets the individual OpenID claims to be returned. 800 * Corresponds to the optional {@code claims} parameter. 801 * 802 * @param claims The individual OpenID claims to be returned, 803 * {@code null} if not specified. 804 * 805 * @return This builder. 806 */ 807 public Builder claims(final OIDCClaimsRequest claims) { 808 this.claims = claims; 809 return this; 810 } 811 812 813 /** 814 * Sets the transaction specific purpose. Corresponds to the 815 * optional {@code purpose} parameter. 816 * 817 * @param purpose The purpose, {@code null} if not specified. 818 * 819 * @return This builder. 820 */ 821 public Builder purpose(final String purpose) { 822 this.purpose = purpose; 823 return this; 824 } 825 826 827 /** 828 * Sets the request object. Corresponds to the optional 829 * {@code request} parameter. Must not be specified together 830 * with a request object URI. 831 * 832 * @param requestObject The request object, {@code null} if not 833 * specified. 834 * 835 * @return This builder. 836 */ 837 public Builder requestObject(final JWT requestObject) { 838 this.requestObject = requestObject; 839 return this; 840 } 841 842 843 /** 844 * Sets the request object URI. Corresponds to the optional 845 * {@code request_uri} parameter. Must not be specified 846 * together with a request object. 847 * 848 * @param requestURI The request object URI, {@code null} if 849 * not specified. 850 * 851 * @return This builder. 852 */ 853 public Builder requestURI(final URI requestURI) { 854 this.requestURI = requestURI; 855 return this; 856 } 857 858 859 /** 860 * Sets the response mode. Corresponds to the optional 861 * {@code response_mode} parameter. Use of this parameter is 862 * not recommended unless a non-default response mode is 863 * requested (e.g. form_post). 864 * 865 * @param rm The response mode, {@code null} if not specified. 866 * 867 * @return This builder. 868 */ 869 public Builder responseMode(final ResponseMode rm) { 870 this.rm = rm; 871 return this; 872 } 873 874 875 /** 876 * Sets the code challenge for Proof Key for Code Exchange 877 * (PKCE) by public OAuth clients. 878 * 879 * @param codeChallenge The code challenge, {@code null} 880 * if not specified. 881 * @param codeChallengeMethod The code challenge method, 882 * {@code null} if not specified. 883 * 884 * @return This builder. 885 */ 886 @Deprecated 887 public Builder codeChallenge(final CodeChallenge codeChallenge, final CodeChallengeMethod codeChallengeMethod) { 888 this.codeChallenge = codeChallenge; 889 this.codeChallengeMethod = codeChallengeMethod; 890 return this; 891 } 892 893 894 /** 895 * Sets the code challenge for Proof Key for Code Exchange 896 * (PKCE) by public OAuth clients. 897 * 898 * @param codeVerifier The code verifier to use to 899 * compute the code challenge, 900 * {@code null} if PKCE is not 901 * specified. 902 * @param codeChallengeMethod The code challenge method, 903 * {@code null} if not specified. 904 * Defaults to 905 * {@link CodeChallengeMethod#PLAIN} 906 * if a code verifier is specified. 907 * 908 * @return This builder. 909 */ 910 public Builder codeChallenge(final CodeVerifier codeVerifier, final CodeChallengeMethod codeChallengeMethod) { 911 if (codeVerifier != null) { 912 CodeChallengeMethod method = codeChallengeMethod != null ? codeChallengeMethod : CodeChallengeMethod.getDefault(); 913 this.codeChallenge = CodeChallenge.compute(method, codeVerifier); 914 this.codeChallengeMethod = method; 915 } else { 916 this.codeChallenge = null; 917 this.codeChallengeMethod = null; 918 } 919 return this; 920 } 921 922 923 /** 924 * Sets the resource server URI. 925 * 926 * @param resource The resource URI, {@code null} if not 927 * specified. 928 * 929 * @return This builder. 930 */ 931 public Builder resource(final URI resource) { 932 if (resource != null) { 933 this.resources = Collections.singletonList(resource); 934 } else { 935 this.resources = null; 936 } 937 return this; 938 } 939 940 941 /** 942 * Sets the resource server URI(s). 943 * 944 * @param resources The resource URI(s), {@code null} if not 945 * specified. 946 * 947 * @return This builder. 948 */ 949 public Builder resources(final URI ... resources) { 950 if (resources != null) { 951 this.resources = Arrays.asList(resources); 952 } else { 953 this.resources = null; 954 } 955 return this; 956 } 957 958 959 /** 960 * Requests incremental authorisation. 961 * 962 * @param includeGrantedScopes {@code true} to request 963 * incremental authorisation. 964 * 965 * @return This builder. 966 */ 967 public Builder includeGrantedScopes(final boolean includeGrantedScopes) { 968 this.includeGrantedScopes = includeGrantedScopes; 969 return this; 970 } 971 972 973 /** 974 * Sets a custom parameter. 975 * 976 * @param name The parameter name. Must not be {@code null}. 977 * @param values The parameter values, {@code null} if not 978 * specified. 979 * 980 * @return This builder. 981 */ 982 public Builder customParameter(final String name, final String ... values) { 983 if (values == null || values.length == 0) { 984 customParams.remove(name); 985 } else { 986 customParams.put(name, Arrays.asList(values)); 987 } 988 return this; 989 } 990 991 992 /** 993 * Builds a new authentication request. 994 * 995 * @return The authentication request. 996 */ 997 public AuthenticationRequest build() { 998 999 try { 1000 return new AuthenticationRequest( 1001 uri, rt, rm, scope, clientID, redirectURI, state, nonce, 1002 display, prompt, dpopJKT, trustChain, maxAge, uiLocales, claimsLocales, 1003 idTokenHint, loginHint, acrValues, claims, 1004 purpose, 1005 requestObject, requestURI, 1006 codeChallenge, codeChallengeMethod, 1007 resources, 1008 includeGrantedScopes, 1009 customParams); 1010 1011 } catch (IllegalArgumentException e) { 1012 throw new IllegalStateException(e.getMessage(), e); 1013 } 1014 } 1015 } 1016 1017 1018 /** 1019 * Creates a new minimal OpenID Connect authentication request. 1020 * 1021 * @param uri The URI of the OAuth 2.0 authorisation endpoint. 1022 * May be {@code null} if the {@link #toHTTPRequest} 1023 * method will not be used. 1024 * @param rt The response type. Corresponds to the 1025 * {@code response_type} parameter. Must specify a 1026 * valid OpenID Connect response type. Must not be 1027 * {@code null}. 1028 * @param scope The request scope. Corresponds to the 1029 * {@code scope} parameter. Must contain an 1030 * {@link OIDCScopeValue#OPENID openid value}. Must 1031 * not be {@code null}. 1032 * @param clientID The client identifier. Corresponds to the 1033 * {@code client_id} parameter. Must not be 1034 * {@code null}. 1035 * @param redirectURI The redirection URI. Corresponds to the 1036 * {@code redirect_uri} parameter. Must not be 1037 * {@code null}. 1038 * @param state The state. Corresponds to the {@code state} 1039 * parameter. May be {@code null}. 1040 * @param nonce The nonce. Corresponds to the {@code nonce} 1041 * parameter. May be {@code null} for code flow. 1042 */ 1043 public AuthenticationRequest(final URI uri, 1044 final ResponseType rt, 1045 final Scope scope, 1046 final ClientID clientID, 1047 final URI redirectURI, 1048 final State state, 1049 final Nonce nonce) { 1050 1051 // Not specified: display, prompt, maxAge, uiLocales, claimsLocales, 1052 // idTokenHint, loginHint, acrValues, claims, purpose 1053 // codeChallenge, codeChallengeMethod 1054 this(uri, rt, null, scope, clientID, redirectURI, state, nonce, 1055 null, null, -1, null, null, 1056 null, null, null, (OIDCClaimsRequest) null, null, 1057 null, null, 1058 null, null, 1059 null, false, null); 1060 } 1061 1062 1063 /** 1064 * Creates a new OpenID Connect authentication request with extension 1065 * and custom parameters. 1066 * 1067 * @param uri The URI of the OAuth 2.0 authorisation 1068 * endpoint. May be {@code null} if the 1069 * {@link #toHTTPRequest} method will not 1070 * be used. 1071 * @param rt The response type set. Corresponds to 1072 * the {@code response_type} parameter. 1073 * Must specify a valid OpenID Connect 1074 * response type. Must not be {@code null}. 1075 * @param rm The response mode. Corresponds to the 1076 * optional {@code response_mode} 1077 * parameter. Use of this parameter is not 1078 * recommended unless a non-default 1079 * response mode is requested (e.g. 1080 * form_post). 1081 * @param scope The request scope. Corresponds to the 1082 * {@code scope} parameter. Must contain an 1083 * {@link OIDCScopeValue#OPENID openid 1084 * value}. Must not be {@code null}. 1085 * @param clientID The client identifier. Corresponds to 1086 * the {@code client_id} parameter. Must 1087 * not be {@code null}. 1088 * @param redirectURI The redirection URI. Corresponds to the 1089 * {@code redirect_uri} parameter. Must not 1090 * be {@code null} unless set by means of 1091 * the optional {@code request_object} / 1092 * {@code request_uri} parameter. 1093 * @param state The state. Corresponds to the 1094 * recommended {@code state} parameter. 1095 * {@code null} if not specified. 1096 * @param nonce The nonce. Corresponds to the 1097 * {@code nonce} parameter. May be 1098 * {@code null} for code flow. 1099 * @param display The requested display type. Corresponds 1100 * to the optional {@code display} 1101 * parameter. 1102 * {@code null} if not specified. 1103 * @param prompt The requested prompt. Corresponds to the 1104 * optional {@code prompt} parameter. 1105 * {@code null} if not specified. 1106 * @param maxAge The required maximum authentication age, 1107 * in seconds. Corresponds to the optional 1108 * {@code max_age} parameter. -1 if not 1109 * specified, zero implies 1110 * {@code prompt=login}. 1111 * @param uiLocales The preferred languages and scripts for 1112 * the user interface. Corresponds to the 1113 * optional {@code ui_locales} parameter. 1114 * {@code null} if not specified. 1115 * @param claimsLocales The preferred languages and scripts for 1116 * claims being returned. Corresponds to 1117 * the optional {@code claims_locales} 1118 * parameter. {@code null} if not 1119 * specified. 1120 * @param idTokenHint The ID Token hint. Corresponds to the 1121 * optional {@code id_token_hint} 1122 * parameter. {@code null} if not 1123 * specified. 1124 * @param loginHint The login hint. Corresponds to the 1125 * optional {@code login_hint} parameter. 1126 * {@code null} if not specified. 1127 * @param acrValues The requested Authentication Context 1128 * Class Reference values. Corresponds to 1129 * the optional {@code acr_values} 1130 * parameter. {@code null} if not 1131 * specified. 1132 * @param claims The individual claims to be returned. 1133 * Corresponds to the optional 1134 * {@code claims} parameter. {@code null} 1135 * if not specified. 1136 * @param purpose The transaction specific purpose, 1137 * {@code null} if not specified. 1138 * @param requestObject The request object. Corresponds to the 1139 * optional {@code request} parameter. Must 1140 * not be specified together with a request 1141 * object URI. {@code null} if not 1142 * specified. 1143 * @param requestURI The request object URI. Corresponds to 1144 * the optional {@code request_uri} 1145 * parameter. Must not be specified 1146 * together with a request object. 1147 * {@code null} if not specified. 1148 * @param codeChallenge The code challenge for PKCE, 1149 * {@code null} if not specified. 1150 * @param codeChallengeMethod The code challenge method for PKCE, 1151 * {@code null} if not specified. 1152 * @param resources The resource URI(s), {@code null} if not 1153 * specified. 1154 * @param includeGrantedScopes {@code true} to request incremental 1155 * authorisation. 1156 * @param customParams Additional custom parameters, empty map 1157 * or {@code null} if none. 1158 */ 1159 @Deprecated 1160 public AuthenticationRequest(final URI uri, 1161 final ResponseType rt, 1162 final ResponseMode rm, 1163 final Scope scope, 1164 final ClientID clientID, 1165 final URI redirectURI, 1166 final State state, 1167 final Nonce nonce, 1168 final Display display, 1169 final Prompt prompt, 1170 final int maxAge, 1171 final List<LangTag> uiLocales, 1172 final List<LangTag> claimsLocales, 1173 final JWT idTokenHint, 1174 final String loginHint, 1175 final List<ACR> acrValues, 1176 final ClaimsRequest claims, 1177 final String purpose, 1178 final JWT requestObject, 1179 final URI requestURI, 1180 final CodeChallenge codeChallenge, 1181 final CodeChallengeMethod codeChallengeMethod, 1182 final List<URI> resources, 1183 final boolean includeGrantedScopes, 1184 final Map<String,List<String>> customParams) { 1185 1186 this(uri, rt, rm, scope, clientID, redirectURI, state, nonce, 1187 display, prompt, maxAge, uiLocales, claimsLocales, 1188 idTokenHint, loginHint, acrValues, toOIDCClaimsRequestWithSilentFail(claims), purpose, 1189 requestObject, requestURI, 1190 codeChallenge, codeChallengeMethod, 1191 resources, includeGrantedScopes, customParams); 1192 } 1193 1194 1195 /** 1196 * Creates a new OpenID Connect authentication request with extension 1197 * and custom parameters. 1198 * 1199 * @param uri The URI of the OAuth 2.0 authorisation 1200 * endpoint. May be {@code null} if the 1201 * {@link #toHTTPRequest} method will not 1202 * be used. 1203 * @param rt The response type set. Corresponds to 1204 * the {@code response_type} parameter. 1205 * Must specify a valid OpenID Connect 1206 * response type. Must not be {@code null}. 1207 * @param rm The response mode. Corresponds to the 1208 * optional {@code response_mode} 1209 * parameter. Use of this parameter is not 1210 * recommended unless a non-default 1211 * response mode is requested (e.g. 1212 * form_post). 1213 * @param scope The request scope. Corresponds to the 1214 * {@code scope} parameter. Must contain an 1215 * {@link OIDCScopeValue#OPENID openid 1216 * value}. Must not be {@code null}. 1217 * @param clientID The client identifier. Corresponds to 1218 * the {@code client_id} parameter. Must 1219 * not be {@code null}. 1220 * @param redirectURI The redirection URI. Corresponds to the 1221 * {@code redirect_uri} parameter. Must not 1222 * be {@code null} unless set by means of 1223 * the optional {@code request_object} / 1224 * {@code request_uri} parameter. 1225 * @param state The state. Corresponds to the 1226 * recommended {@code state} parameter. 1227 * {@code null} if not specified. 1228 * @param nonce The nonce. Corresponds to the 1229 * {@code nonce} parameter. May be 1230 * {@code null} for code flow. 1231 * @param display The requested display type. Corresponds 1232 * to the optional {@code display} 1233 * parameter. 1234 * {@code null} if not specified. 1235 * @param prompt The requested prompt. Corresponds to the 1236 * optional {@code prompt} parameter. 1237 * {@code null} if not specified. 1238 * @param maxAge The required maximum authentication age, 1239 * in seconds. Corresponds to the optional 1240 * {@code max_age} parameter. -1 if not 1241 * specified, zero implies 1242 * {@code prompt=login}. 1243 * @param uiLocales The preferred languages and scripts for 1244 * the user interface. Corresponds to the 1245 * optional {@code ui_locales} parameter. 1246 * {@code null} if not specified. 1247 * @param claimsLocales The preferred languages and scripts for 1248 * claims being returned. Corresponds to 1249 * the optional {@code claims_locales} 1250 * parameter. {@code null} if not 1251 * specified. 1252 * @param idTokenHint The ID Token hint. Corresponds to the 1253 * optional {@code id_token_hint} 1254 * parameter. {@code null} if not 1255 * specified. 1256 * @param loginHint The login hint. Corresponds to the 1257 * optional {@code login_hint} parameter. 1258 * {@code null} if not specified. 1259 * @param acrValues The requested Authentication Context 1260 * Class Reference values. Corresponds to 1261 * the optional {@code acr_values} 1262 * parameter. {@code null} if not 1263 * specified. 1264 * @param claims The individual OpenID claims to be 1265 * returned. Corresponds to the optional 1266 * {@code claims} parameter. {@code null} 1267 * if not specified. 1268 * @param purpose The transaction specific purpose, 1269 * {@code null} if not specified. 1270 * @param requestObject The request object. Corresponds to the 1271 * optional {@code request} parameter. Must 1272 * not be specified together with a request 1273 * object URI. {@code null} if not 1274 * specified. 1275 * @param requestURI The request object URI. Corresponds to 1276 * the optional {@code request_uri} 1277 * parameter. Must not be specified 1278 * together with a request object. 1279 * {@code null} if not specified. 1280 * @param codeChallenge The code challenge for PKCE, 1281 * {@code null} if not specified. 1282 * @param codeChallengeMethod The code challenge method for PKCE, 1283 * {@code null} if not specified. 1284 * @param resources The resource URI(s), {@code null} if not 1285 * specified. 1286 * @param includeGrantedScopes {@code true} to request incremental 1287 * authorisation. 1288 * @param customParams Additional custom parameters, empty map 1289 * or {@code null} if none. 1290 */ 1291 @Deprecated 1292 public AuthenticationRequest(final URI uri, 1293 final ResponseType rt, 1294 final ResponseMode rm, 1295 final Scope scope, 1296 final ClientID clientID, 1297 final URI redirectURI, 1298 final State state, 1299 final Nonce nonce, 1300 final Display display, 1301 final Prompt prompt, 1302 final int maxAge, 1303 final List<LangTag> uiLocales, 1304 final List<LangTag> claimsLocales, 1305 final JWT idTokenHint, 1306 final String loginHint, 1307 final List<ACR> acrValues, 1308 final OIDCClaimsRequest claims, 1309 final String purpose, 1310 final JWT requestObject, 1311 final URI requestURI, 1312 final CodeChallenge codeChallenge, 1313 final CodeChallengeMethod codeChallengeMethod, 1314 final List<URI> resources, 1315 final boolean includeGrantedScopes, 1316 final Map<String,List<String>> customParams) { 1317 1318 this(uri, rt, rm, scope, clientID, redirectURI, state, nonce, display, prompt, null, null, 1319 maxAge, uiLocales, claimsLocales, idTokenHint, loginHint, acrValues, claims, purpose, 1320 requestObject, requestURI, codeChallenge, codeChallengeMethod, 1321 resources, includeGrantedScopes, 1322 customParams); 1323 } 1324 1325 1326 /** 1327 * Creates a new OpenID Connect authentication request with extension 1328 * and custom parameters. 1329 * 1330 * @param uri The URI of the OAuth 2.0 authorisation 1331 * endpoint. May be {@code null} if the 1332 * {@link #toHTTPRequest} method will not 1333 * be used. 1334 * @param rt The response type set. Corresponds to 1335 * the {@code response_type} parameter. 1336 * Must specify a valid OpenID Connect 1337 * response type. Must not be {@code null}. 1338 * @param rm The response mode. Corresponds to the 1339 * optional {@code response_mode} 1340 * parameter. Use of this parameter is not 1341 * recommended unless a non-default 1342 * response mode is requested (e.g. 1343 * form_post). 1344 * @param scope The request scope. Corresponds to the 1345 * {@code scope} parameter. Must contain an 1346 * {@link OIDCScopeValue#OPENID openid 1347 * value}. Must not be {@code null}. 1348 * @param clientID The client identifier. Corresponds to 1349 * the {@code client_id} parameter. Must 1350 * not be {@code null}. 1351 * @param redirectURI The redirection URI. Corresponds to the 1352 * {@code redirect_uri} parameter. Must not 1353 * be {@code null} unless set by means of 1354 * the optional {@code request_object} / 1355 * {@code request_uri} parameter. 1356 * @param state The state. Corresponds to the 1357 * recommended {@code state} parameter. 1358 * {@code null} if not specified. 1359 * @param nonce The nonce. Corresponds to the 1360 * {@code nonce} parameter. May be 1361 * {@code null} for code flow. 1362 * @param display The requested display type. Corresponds 1363 * to the optional {@code display} 1364 * parameter. 1365 * {@code null} if not specified. 1366 * @param prompt The requested prompt. Corresponds to the 1367 * optional {@code prompt} parameter. 1368 * {@code null} if not specified. 1369 * @param dpopJKT The DPoP JWK SHA-256 thumbprint, 1370 * {@code null} if not specified. 1371 * @param maxAge The required maximum authentication age, 1372 * in seconds. Corresponds to the optional 1373 * {@code max_age} parameter. -1 if not 1374 * specified, zero implies 1375 * {@code prompt=login}. 1376 * @param uiLocales The preferred languages and scripts for 1377 * the user interface. Corresponds to the 1378 * optional {@code ui_locales} parameter. 1379 * {@code null} if not specified. 1380 * @param claimsLocales The preferred languages and scripts for 1381 * claims being returned. Corresponds to 1382 * the optional {@code claims_locales} 1383 * parameter. {@code null} if not 1384 * specified. 1385 * @param idTokenHint The ID Token hint. Corresponds to the 1386 * optional {@code id_token_hint} 1387 * parameter. {@code null} if not 1388 * specified. 1389 * @param loginHint The login hint. Corresponds to the 1390 * optional {@code login_hint} parameter. 1391 * {@code null} if not specified. 1392 * @param acrValues The requested Authentication Context 1393 * Class Reference values. Corresponds to 1394 * the optional {@code acr_values} 1395 * parameter. {@code null} if not 1396 * specified. 1397 * @param claims The individual OpenID claims to be 1398 * returned. Corresponds to the optional 1399 * {@code claims} parameter. {@code null} 1400 * if not specified. 1401 * @param purpose The transaction specific purpose, 1402 * {@code null} if not specified. 1403 * @param requestObject The request object. Corresponds to the 1404 * optional {@code request} parameter. Must 1405 * not be specified together with a request 1406 * object URI. {@code null} if not 1407 * specified. 1408 * @param requestURI The request object URI. Corresponds to 1409 * the optional {@code request_uri} 1410 * parameter. Must not be specified 1411 * together with a request object. 1412 * {@code null} if not specified. 1413 * @param codeChallenge The code challenge for PKCE, 1414 * {@code null} if not specified. 1415 * @param codeChallengeMethod The code challenge method for PKCE, 1416 * {@code null} if not specified. 1417 * @param resources The resource URI(s), {@code null} if not 1418 * specified. 1419 * @param includeGrantedScopes {@code true} to request incremental 1420 * authorisation. 1421 * @param customParams Additional custom parameters, empty map 1422 * or {@code null} if none. 1423 */ 1424 @Deprecated 1425 public AuthenticationRequest(final URI uri, 1426 final ResponseType rt, 1427 final ResponseMode rm, 1428 final Scope scope, 1429 final ClientID clientID, 1430 final URI redirectURI, 1431 final State state, 1432 final Nonce nonce, 1433 final Display display, 1434 final Prompt prompt, 1435 final JWKThumbprintConfirmation dpopJKT, 1436 final int maxAge, 1437 final List<LangTag> uiLocales, 1438 final List<LangTag> claimsLocales, 1439 final JWT idTokenHint, 1440 final String loginHint, 1441 final List<ACR> acrValues, 1442 final OIDCClaimsRequest claims, 1443 final String purpose, 1444 final JWT requestObject, 1445 final URI requestURI, 1446 final CodeChallenge codeChallenge, 1447 final CodeChallengeMethod codeChallengeMethod, 1448 final List<URI> resources, 1449 final boolean includeGrantedScopes, 1450 final Map<String,List<String>> customParams) { 1451 1452 this(uri, rt, rm, scope, clientID, redirectURI, state, nonce, display, prompt, dpopJKT, null, 1453 maxAge, uiLocales, claimsLocales, idTokenHint, loginHint, acrValues, claims, purpose, 1454 requestObject, requestURI, codeChallenge, codeChallengeMethod, 1455 resources, includeGrantedScopes, 1456 customParams); 1457 } 1458 1459 1460 /** 1461 * Creates a new OpenID Connect authentication request with extension 1462 * and custom parameters. 1463 * 1464 * @param uri The URI of the OAuth 2.0 authorisation 1465 * endpoint. May be {@code null} if the 1466 * {@link #toHTTPRequest} method will not 1467 * be used. 1468 * @param rt The response type set. Corresponds to 1469 * the {@code response_type} parameter. 1470 * Must specify a valid OpenID Connect 1471 * response type. Must not be {@code null}. 1472 * @param rm The response mode. Corresponds to the 1473 * optional {@code response_mode} 1474 * parameter. Use of this parameter is not 1475 * recommended unless a non-default 1476 * response mode is requested (e.g. 1477 * form_post). 1478 * @param scope The request scope. Corresponds to the 1479 * {@code scope} parameter. Must contain an 1480 * {@link OIDCScopeValue#OPENID openid 1481 * value}. Must not be {@code null}. 1482 * @param clientID The client identifier. Corresponds to 1483 * the {@code client_id} parameter. Must 1484 * not be {@code null}. 1485 * @param redirectURI The redirection URI. Corresponds to the 1486 * {@code redirect_uri} parameter. Must not 1487 * be {@code null} unless set by means of 1488 * the optional {@code request_object} / 1489 * {@code request_uri} parameter. 1490 * @param state The state. Corresponds to the 1491 * recommended {@code state} parameter. 1492 * {@code null} if not specified. 1493 * @param nonce The nonce. Corresponds to the 1494 * {@code nonce} parameter. May be 1495 * {@code null} for code flow. 1496 * @param display The requested display type. Corresponds 1497 * to the optional {@code display} 1498 * parameter. 1499 * {@code null} if not specified. 1500 * @param prompt The requested prompt. Corresponds to the 1501 * optional {@code prompt} parameter. 1502 * {@code null} if not specified. 1503 * @param dpopJKT The DPoP JWK SHA-256 thumbprint, 1504 * {@code null} if not specified. 1505 * @param trustChain The OpenID Connect Federation 1.0 trust 1506 * chain, {@code null} if not specified. 1507 * @param maxAge The required maximum authentication age, 1508 * in seconds. Corresponds to the optional 1509 * {@code max_age} parameter. -1 if not 1510 * specified, zero implies 1511 * {@code prompt=login}. 1512 * @param uiLocales The preferred languages and scripts for 1513 * the user interface. Corresponds to the 1514 * optional {@code ui_locales} parameter. 1515 * {@code null} if not specified. 1516 * @param claimsLocales The preferred languages and scripts for 1517 * claims being returned. Corresponds to 1518 * the optional {@code claims_locales} 1519 * parameter. {@code null} if not 1520 * specified. 1521 * @param idTokenHint The ID Token hint. Corresponds to the 1522 * optional {@code id_token_hint} 1523 * parameter. {@code null} if not 1524 * specified. 1525 * @param loginHint The login hint. Corresponds to the 1526 * optional {@code login_hint} parameter. 1527 * {@code null} if not specified. 1528 * @param acrValues The requested Authentication Context 1529 * Class Reference values. Corresponds to 1530 * the optional {@code acr_values} 1531 * parameter. {@code null} if not 1532 * specified. 1533 * @param claims The individual OpenID claims to be 1534 * returned. Corresponds to the optional 1535 * {@code claims} parameter. {@code null} 1536 * if not specified. 1537 * @param purpose The transaction specific purpose, 1538 * {@code null} if not specified. 1539 * @param requestObject The request object. Corresponds to the 1540 * optional {@code request} parameter. Must 1541 * not be specified together with a request 1542 * object URI. {@code null} if not 1543 * specified. 1544 * @param requestURI The request object URI. Corresponds to 1545 * the optional {@code request_uri} 1546 * parameter. Must not be specified 1547 * together with a request object. 1548 * {@code null} if not specified. 1549 * @param codeChallenge The code challenge for PKCE, 1550 * {@code null} if not specified. 1551 * @param codeChallengeMethod The code challenge method for PKCE, 1552 * {@code null} if not specified. 1553 * @param resources The resource URI(s), {@code null} if not 1554 * specified. 1555 * @param includeGrantedScopes {@code true} to request incremental 1556 * authorisation. 1557 * @param customParams Additional custom parameters, empty map 1558 * or {@code null} if none. 1559 */ 1560 public AuthenticationRequest(final URI uri, 1561 final ResponseType rt, 1562 final ResponseMode rm, 1563 final Scope scope, 1564 final ClientID clientID, 1565 final URI redirectURI, 1566 final State state, 1567 final Nonce nonce, 1568 final Display display, 1569 final Prompt prompt, 1570 final JWKThumbprintConfirmation dpopJKT, 1571 final TrustChain trustChain, 1572 final int maxAge, 1573 final List<LangTag> uiLocales, 1574 final List<LangTag> claimsLocales, 1575 final JWT idTokenHint, 1576 final String loginHint, 1577 final List<ACR> acrValues, 1578 final OIDCClaimsRequest claims, 1579 final String purpose, 1580 final JWT requestObject, 1581 final URI requestURI, 1582 final CodeChallenge codeChallenge, 1583 final CodeChallengeMethod codeChallengeMethod, 1584 final List<URI> resources, 1585 final boolean includeGrantedScopes, 1586 final Map<String,List<String>> customParams) { 1587 1588 super(uri, rt, rm, clientID, redirectURI, scope, state, codeChallenge, codeChallengeMethod, resources, includeGrantedScopes, requestObject, requestURI, prompt, dpopJKT, trustChain, customParams); 1589 1590 if (! specifiesRequestObject()) { 1591 1592 // Check parameters required by OpenID Connect if no JAR 1593 1594 if (redirectURI == null) 1595 throw new IllegalArgumentException("The redirection URI must not be null"); 1596 1597 OIDCResponseTypeValidator.validate(rt); 1598 1599 if (scope == null) 1600 throw new IllegalArgumentException("The scope must not be null"); 1601 1602 if (!scope.contains(OIDCScopeValue.OPENID)) 1603 throw new IllegalArgumentException("The scope must include an \"openid\" value"); 1604 1605 // Check nonce requirement 1606 if (nonce == null && Nonce.isRequired(rt)) { 1607 throw new IllegalArgumentException("Nonce required for response_type=" + rt); 1608 } 1609 } 1610 1611 this.nonce = nonce; 1612 1613 // Optional parameters 1614 this.display = display; 1615 this.maxAge = maxAge; 1616 1617 if (uiLocales != null) 1618 this.uiLocales = Collections.unmodifiableList(uiLocales); 1619 else 1620 this.uiLocales = null; 1621 1622 if (claimsLocales != null) 1623 this.claimsLocales = Collections.unmodifiableList(claimsLocales); 1624 else 1625 this.claimsLocales = null; 1626 1627 this.idTokenHint = idTokenHint; 1628 this.loginHint = loginHint; 1629 1630 if (acrValues != null) 1631 this.acrValues = Collections.unmodifiableList(acrValues); 1632 else 1633 this.acrValues = null; 1634 1635 this.claims = claims; 1636 1637 if (purpose != null) { 1638 if (purpose.length() < PURPOSE_MIN_LENGTH) { 1639 throw new IllegalArgumentException("The purpose must not be shorter than " + PURPOSE_MIN_LENGTH + " characters"); 1640 } 1641 if (purpose.length() > PURPOSE_MAX_LENGTH) { 1642 throw new IllegalArgumentException("The purpose must not be longer than " + PURPOSE_MAX_LENGTH +" characters"); 1643 } 1644 } 1645 1646 this.purpose = purpose; 1647 } 1648 1649 1650 /** 1651 * Returns the registered (standard) OpenID Connect authentication 1652 * request parameter names. 1653 * 1654 * @return The registered OpenID Connect authentication request 1655 * parameter names, as a unmodifiable set. 1656 */ 1657 public static Set<String> getRegisteredParameterNames() { 1658 1659 return REGISTERED_PARAMETER_NAMES; 1660 } 1661 1662 1663 /** 1664 * Returns the nonce. Corresponds to the conditionally optional 1665 * {@code nonce} parameter. 1666 * 1667 * @return The nonce, {@code null} if not specified. 1668 */ 1669 public Nonce getNonce() { 1670 1671 return nonce; 1672 } 1673 1674 1675 /** 1676 * Returns the requested display type. Corresponds to the optional 1677 * {@code display} parameter. 1678 * 1679 * @return The requested display type, {@code null} if not specified. 1680 */ 1681 public Display getDisplay() { 1682 1683 return display; 1684 } 1685 1686 1687 /** 1688 * Returns the required maximum authentication age. Corresponds to the 1689 * optional {@code max_age} parameter. 1690 * 1691 * @return The maximum authentication age, in seconds; -1 if not 1692 * specified, zero implies {@code prompt=login}. 1693 */ 1694 public int getMaxAge() { 1695 1696 return maxAge; 1697 } 1698 1699 1700 /** 1701 * Returns the end-user's preferred languages and scripts for the user 1702 * interface, ordered by preference. Corresponds to the optional 1703 * {@code ui_locales} parameter. 1704 * 1705 * @return The preferred UI locales, {@code null} if not specified. 1706 */ 1707 public List<LangTag> getUILocales() { 1708 1709 return uiLocales; 1710 } 1711 1712 1713 /** 1714 * Returns the end-user's preferred languages and scripts for the 1715 * claims being returned, ordered by preference. Corresponds to the 1716 * optional {@code claims_locales} parameter. 1717 * 1718 * @return The preferred claims locales, {@code null} if not specified. 1719 */ 1720 public List<LangTag> getClaimsLocales() { 1721 1722 return claimsLocales; 1723 } 1724 1725 1726 /** 1727 * Returns the ID Token hint. Corresponds to the conditionally optional 1728 * {@code id_token_hint} parameter. 1729 * 1730 * @return The ID Token hint, {@code null} if not specified. 1731 */ 1732 public JWT getIDTokenHint() { 1733 1734 return idTokenHint; 1735 } 1736 1737 1738 /** 1739 * Returns the login hint. Corresponds to the optional {@code login_hint} 1740 * parameter. 1741 * 1742 * @return The login hint, {@code null} if not specified. 1743 */ 1744 public String getLoginHint() { 1745 1746 return loginHint; 1747 } 1748 1749 1750 /** 1751 * Returns the requested Authentication Context Class Reference values. 1752 * Corresponds to the optional {@code acr_values} parameter. 1753 * 1754 * @return The requested ACR values, {@code null} if not specified. 1755 */ 1756 public List<ACR> getACRValues() { 1757 1758 return acrValues; 1759 } 1760 1761 1762 /** 1763 * Returns the individual claims to be returned. Corresponds to the 1764 * optional {@code claims} parameter. 1765 * 1766 * @see #getOIDCClaims() 1767 * 1768 * @return The individual claims to be returned, {@code null} if not 1769 * specified. 1770 */ 1771 @Deprecated 1772 public ClaimsRequest getClaims() { 1773 1774 return toClaimsRequestWithSilentFail(claims); 1775 } 1776 1777 1778 private static OIDCClaimsRequest toOIDCClaimsRequestWithSilentFail(final ClaimsRequest claims) { 1779 if (claims == null) { 1780 return null; 1781 } 1782 try { 1783 return OIDCClaimsRequest.parse(claims.toJSONObject()); 1784 } catch (ParseException e) { 1785 return null; 1786 } 1787 } 1788 1789 1790 private static ClaimsRequest toClaimsRequestWithSilentFail(final OIDCClaimsRequest claims) { 1791 if (claims == null) { 1792 return null; 1793 } 1794 try { 1795 return ClaimsRequest.parse(claims.toJSONObject()); 1796 } catch (ParseException e) { 1797 return null; 1798 } 1799 } 1800 1801 1802 /** 1803 * Returns the individual OpenID claims to be returned. Corresponds to 1804 * the optional {@code claims} parameter. 1805 * 1806 * @return The individual claims to be returned, {@code null} if not 1807 * specified. 1808 */ 1809 public OIDCClaimsRequest getOIDCClaims() { 1810 1811 return claims; 1812 } 1813 1814 1815 /** 1816 * Returns the transaction specific purpose. Corresponds to the 1817 * optional {@code purpose} parameter. 1818 * 1819 * @return The purpose, {@code null} if not specified. 1820 */ 1821 public String getPurpose() { 1822 1823 return purpose; 1824 } 1825 1826 1827 @Override 1828 public Map<String,List<String>> toParameters() { 1829 1830 Map <String,List<String>> params = super.toParameters(); 1831 1832 if (nonce != null) 1833 params.put("nonce", Collections.singletonList(nonce.toString())); 1834 1835 if (display != null) 1836 params.put("display", Collections.singletonList(display.toString())); 1837 1838 if (maxAge >= 0) 1839 params.put("max_age", Collections.singletonList("" + maxAge)); 1840 1841 if (uiLocales != null) { 1842 params.put("ui_locales", Collections.singletonList(LangTagUtils.concat(uiLocales))); 1843 } 1844 1845 if (CollectionUtils.isNotEmpty(claimsLocales)) { 1846 params.put("claims_locales", Collections.singletonList(LangTagUtils.concat(claimsLocales))); 1847 } 1848 1849 if (idTokenHint != null) { 1850 1851 try { 1852 params.put("id_token_hint", Collections.singletonList(idTokenHint.serialize())); 1853 1854 } catch (IllegalStateException e) { 1855 1856 throw new SerializeException("Couldn't serialize ID token hint: " + e.getMessage(), e); 1857 } 1858 } 1859 1860 if (loginHint != null) 1861 params.put("login_hint", Collections.singletonList(loginHint)); 1862 1863 if (acrValues != null) { 1864 1865 StringBuilder sb = new StringBuilder(); 1866 1867 for (ACR acr: acrValues) { 1868 1869 if (sb.length() > 0) 1870 sb.append(' '); 1871 1872 sb.append(acr.toString()); 1873 } 1874 1875 params.put("acr_values", Collections.singletonList(sb.toString())); 1876 } 1877 1878 1879 if (claims != null) 1880 params.put("claims", Collections.singletonList(claims.toJSONObject().toString())); 1881 1882 if (purpose != null) 1883 params.put("purpose", Collections.singletonList(purpose)); 1884 1885 return params; 1886 } 1887 1888 1889 @Override 1890 public JWTClaimsSet toJWTClaimsSet() { 1891 1892 JWTClaimsSet jwtClaimsSet = super.toJWTClaimsSet(); 1893 1894 if (jwtClaimsSet.getClaim("max_age") != null) { 1895 // Convert max_age to number in JSON object 1896 try { 1897 String maxAgeString = jwtClaimsSet.getStringClaim("max_age"); 1898 JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder(jwtClaimsSet); 1899 builder.claim("max_age", Integer.parseInt(maxAgeString)); 1900 return builder.build(); 1901 } catch (java.text.ParseException e) { 1902 throw new SerializeException(e.getMessage()); 1903 } 1904 } 1905 1906 return jwtClaimsSet; 1907 } 1908 1909 1910 /** 1911 * Parses an OpenID Connect authentication request from the specified 1912 * URI query parameters. 1913 * 1914 * <p>Example parameters: 1915 * 1916 * <pre> 1917 * response_type = token id_token 1918 * client_id = s6BhdRkqt3 1919 * redirect_uri = https://client.example.com/cb 1920 * scope = openid profile 1921 * state = af0ifjsldkj 1922 * nonce = -0S6_WzA2Mj 1923 * </pre> 1924 * 1925 * @param params The parameters. Must not be {@code null}. 1926 * 1927 * @return The OpenID Connect authentication request. 1928 * 1929 * @throws ParseException If the parameters couldn't be parsed to an 1930 * OpenID Connect authentication request. 1931 */ 1932 public static AuthenticationRequest parse(final Map<String,List<String>> params) 1933 throws ParseException { 1934 1935 return parse(null, params); 1936 } 1937 1938 1939 /** 1940 * Parses an OpenID Connect authentication request from the specified 1941 * URI and query parameters. 1942 * 1943 * <p>Example parameters: 1944 * 1945 * <pre> 1946 * response_type = token id_token 1947 * client_id = s6BhdRkqt3 1948 * redirect_uri = https://client.example.com/cb 1949 * scope = openid profile 1950 * state = af0ifjsldkj 1951 * nonce = -0S6_WzA2Mj 1952 * </pre> 1953 * 1954 * @param uri The URI of the OAuth 2.0 authorisation endpoint. May 1955 * be {@code null} if the {@link #toHTTPRequest} method 1956 * will not be used. 1957 * @param params The parameters. Must not be {@code null}. 1958 * 1959 * @return The OpenID Connect authentication request. 1960 * 1961 * @throws ParseException If the parameters couldn't be parsed to an 1962 * OpenID Connect authentication request. 1963 */ 1964 public static AuthenticationRequest parse(final URI uri, final Map<String,List<String>> params) 1965 throws ParseException { 1966 1967 // Parse and validate the core OAuth 2.0 autz request params in 1968 // the context of OIDC 1969 AuthorizationRequest ar = AuthorizationRequest.parse(uri, params); 1970 1971 Nonce nonce = Nonce.parse(MultivaluedMapUtils.getFirstValue(params, "nonce")); 1972 1973 if (! ar.specifiesRequestObject()) { 1974 1975 // Required params if no JAR is present 1976 1977 if (ar.getRedirectionURI() == null) { 1978 String msg = "Missing redirect_uri parameter"; 1979 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 1980 ar.getClientID(), null, ar.impliedResponseMode(), ar.getState()); 1981 } 1982 1983 if (ar.getScope() == null) { 1984 String msg = "Missing scope parameter"; 1985 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 1986 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState()); 1987 } 1988 1989 // Check nonce requirement 1990 if (nonce == null && Nonce.isRequired(ar.getResponseType())) { 1991 String msg = "Missing nonce parameter: Required for response_type=" + ar.getResponseType(); 1992 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 1993 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState()); 1994 } 1995 } 1996 1997 // Check if present (not in JAR) 1998 if (ar.getResponseType() != null) { 1999 try { 2000 OIDCResponseTypeValidator.validate(ar.getResponseType()); 2001 } catch (IllegalArgumentException e) { 2002 String msg = "Unsupported response_type parameter: " + e.getMessage(); 2003 throw new ParseException(msg, OAuth2Error.UNSUPPORTED_RESPONSE_TYPE.appendDescription(": " + msg), 2004 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState()); 2005 } 2006 } 2007 2008 // Check if present (not in JAR) 2009 if (ar.getScope() != null && ! ar.getScope().contains(OIDCScopeValue.OPENID)) { 2010 String msg = "The scope must include an openid value"; 2011 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 2012 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState()); 2013 } 2014 2015 Display display = null; 2016 2017 if (params.containsKey("display")) { 2018 try { 2019 display = Display.parse(MultivaluedMapUtils.getFirstValue(params, "display")); 2020 2021 } catch (ParseException e) { 2022 String msg = "Invalid display parameter: " + e.getMessage(); 2023 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 2024 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState(), e); 2025 } 2026 } 2027 2028 2029 String v = MultivaluedMapUtils.getFirstValue(params, "max_age"); 2030 2031 int maxAge = -1; 2032 2033 if (StringUtils.isNotBlank(v)) { 2034 2035 try { 2036 maxAge = Integer.parseInt(v); 2037 2038 } catch (NumberFormatException e) { 2039 String msg = "Invalid max_age parameter: " + v; 2040 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 2041 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState(), e); 2042 } 2043 } 2044 2045 2046 List<LangTag> uiLocales; 2047 try { 2048 uiLocales = LangTagUtils.parseLangTagList(MultivaluedMapUtils.getFirstValue(params, "ui_locales")); 2049 } catch (LangTagException e) { 2050 String msg = "Invalid ui_locales parameter: " + e.getMessage(); 2051 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 2052 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState(), e); 2053 } 2054 2055 2056 List<LangTag> claimsLocales; 2057 try { 2058 claimsLocales = LangTagUtils.parseLangTagList(MultivaluedMapUtils.getFirstValue(params, "claims_locales")); 2059 2060 } catch (LangTagException e) { 2061 String msg = "Invalid claims_locales parameter: " + e.getMessage(); 2062 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 2063 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState(), e); 2064 } 2065 2066 2067 v = MultivaluedMapUtils.getFirstValue(params, "id_token_hint"); 2068 2069 JWT idTokenHint = null; 2070 2071 if (StringUtils.isNotBlank(v)) { 2072 2073 try { 2074 idTokenHint = JWTParser.parse(v); 2075 2076 } catch (java.text.ParseException e) { 2077 String msg = "Invalid id_token_hint parameter: " + e.getMessage(); 2078 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 2079 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState(), e); 2080 } 2081 } 2082 2083 String loginHint = MultivaluedMapUtils.getFirstValue(params, "login_hint"); 2084 2085 2086 v = MultivaluedMapUtils.getFirstValue(params, "acr_values"); 2087 2088 List<ACR> acrValues = null; 2089 2090 if (StringUtils.isNotBlank(v)) { 2091 2092 acrValues = new LinkedList<>(); 2093 2094 StringTokenizer st = new StringTokenizer(v, " "); 2095 2096 while (st.hasMoreTokens()) { 2097 2098 acrValues.add(new ACR(st.nextToken())); 2099 } 2100 } 2101 2102 2103 v = MultivaluedMapUtils.getFirstValue(params, "claims"); 2104 2105 OIDCClaimsRequest claims = null; 2106 2107 if (StringUtils.isNotBlank(v)) { 2108 try { 2109 claims = OIDCClaimsRequest.parse(v); 2110 } catch (ParseException e) { 2111 String msg = "Invalid claims parameter: " + e.getMessage(); 2112 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 2113 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState(), e); 2114 } 2115 } 2116 2117 String purpose = MultivaluedMapUtils.getFirstValue(params, "purpose"); 2118 2119 if (purpose != null && (purpose.length() < PURPOSE_MIN_LENGTH || purpose.length() > PURPOSE_MAX_LENGTH)) { 2120 String msg = "Invalid purpose parameter: Must not be shorter than " + PURPOSE_MIN_LENGTH + " and longer than " + PURPOSE_MAX_LENGTH + " characters"; 2121 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 2122 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState()); 2123 } 2124 2125 2126 // Parse additional custom parameters 2127 Map<String,List<String>> customParams = null; 2128 2129 for (Map.Entry<String,List<String>> p: params.entrySet()) { 2130 2131 if (! REGISTERED_PARAMETER_NAMES.contains(p.getKey())) { 2132 // We have a custom parameter 2133 if (customParams == null) { 2134 customParams = new HashMap<>(); 2135 } 2136 customParams.put(p.getKey(), p.getValue()); 2137 } 2138 } 2139 2140 2141 return new AuthenticationRequest( 2142 uri, ar.getResponseType(), ar.getResponseMode(), ar.getScope(), ar.getClientID(), ar.getRedirectionURI(), ar.getState(), nonce, 2143 display, ar.getPrompt(), ar.getDPoPJWKThumbprintConfirmation(), ar.getTrustChain(), maxAge, uiLocales, claimsLocales, 2144 idTokenHint, loginHint, acrValues, claims, purpose, 2145 ar.getRequestObject(), ar.getRequestURI(), 2146 ar.getCodeChallenge(), ar.getCodeChallengeMethod(), 2147 ar.getResources(), 2148 ar.includeGrantedScopes(), 2149 customParams); 2150 } 2151 2152 2153 /** 2154 * Parses an OpenID Connect authentication request from the specified 2155 * URI query string. 2156 * 2157 * <p>Example URI query string: 2158 * 2159 * <pre> 2160 * response_type=token%20id_token 2161 * &client_id=s6BhdRkqt3 2162 * &redirect_uri=https%3A%2F%2Fclient.example.com%2Fcb 2163 * &scope=openid%20profile 2164 * &state=af0ifjsldkj 2165 * &nonce=n-0S6_WzA2Mj 2166 * </pre> 2167 * 2168 * @param query The URI query string. Must not be {@code null}. 2169 * 2170 * @return The OpenID Connect authentication request. 2171 * 2172 * @throws ParseException If the query string couldn't be parsed to an 2173 * OpenID Connect authentication request. 2174 */ 2175 public static AuthenticationRequest parse(final String query) 2176 throws ParseException { 2177 2178 return parse(null, URLUtils.parseParameters(query)); 2179 } 2180 2181 2182 /** 2183 * Parses an OpenID Connect authentication request from the specified 2184 * URI query string. 2185 * 2186 * <p>Example URI query string: 2187 * 2188 * <pre> 2189 * response_type=token%20id_token 2190 * &client_id=s6BhdRkqt3 2191 * &redirect_uri=https%3A%2F%2Fclient.example.com%2Fcb 2192 * &scope=openid%20profile 2193 * &state=af0ifjsldkj 2194 * &nonce=n-0S6_WzA2Mj 2195 * </pre> 2196 * 2197 * @param uri The URI of the OAuth 2.0 authorisation endpoint. May be 2198 * {@code null} if the {@link #toHTTPRequest} method will 2199 * not be used. 2200 * @param query The URI query string. Must not be {@code null}. 2201 * 2202 * @return The OpenID Connect authentication request. 2203 * 2204 * @throws ParseException If the query string couldn't be parsed to an 2205 * OpenID Connect authentication request. 2206 */ 2207 public static AuthenticationRequest parse(final URI uri, final String query) 2208 throws ParseException { 2209 2210 return parse(uri, URLUtils.parseParameters(query)); 2211 } 2212 2213 2214 /** 2215 * Parses an OpenID Connect authentication request from the specified 2216 * URI. 2217 * 2218 * <p>Example URI: 2219 * 2220 * <pre> 2221 * https://server.example.com/authorize? 2222 * response_type=token%20id_token 2223 * &client_id=s6BhdRkqt3 2224 * &redirect_uri=https%3A%2F%2Fclient.example.com%2Fcb 2225 * &scope=openid%20profile 2226 * &state=af0ifjsldkj 2227 * &nonce=n-0S6_WzA2Mj 2228 * </pre> 2229 * 2230 * @param uri The URI. Must not be {@code null}. 2231 * 2232 * @return The OpenID Connect authentication request. 2233 * 2234 * @throws ParseException If the query string couldn't be parsed to an 2235 * OpenID Connect authentication request. 2236 */ 2237 public static AuthenticationRequest parse(final URI uri) 2238 throws ParseException { 2239 2240 return parse(URIUtils.getBaseURI(uri), URLUtils.parseParameters(uri.getRawQuery())); 2241 } 2242 2243 2244 /** 2245 * Parses an authentication request from the specified HTTP GET or HTTP 2246 * POST request. 2247 * 2248 * <p>Example HTTP request (GET): 2249 * 2250 * <pre> 2251 * https://server.example.com/op/authorize? 2252 * response_type=code%20id_token 2253 * &client_id=s6BhdRkqt3 2254 * &redirect_uri=https%3A%2F%2Fclient.example.com%2Fcb 2255 * &scope=openid 2256 * &nonce=n-0S6_WzA2Mj 2257 * &state=af0ifjsldkj 2258 * </pre> 2259 * 2260 * @param httpRequest The HTTP request. Must not be {@code null}. 2261 * 2262 * @return The OpenID Connect authentication request. 2263 * 2264 * @throws ParseException If the HTTP request couldn't be parsed to an 2265 * OpenID Connect authentication request. 2266 */ 2267 public static AuthenticationRequest parse(final HTTPRequest httpRequest) 2268 throws ParseException { 2269 2270 String query = httpRequest.getQuery(); 2271 2272 if (query == null) 2273 throw new ParseException("Missing URI query string"); 2274 2275 URI endpointURI = httpRequest.getURI(); 2276 2277 return parse(endpointURI, query); 2278 } 2279}