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