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