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) (RFC 9449). 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 The authorisation details, 1718 * {@code null} if not specified. 1719 * @param resources The resource URI(s), {@code null} if not 1720 * specified. 1721 * @param includeGrantedScopes {@code true} to request incremental 1722 * authorisation. 1723 * @param customParams Additional custom parameters, empty map 1724 * or {@code null} if none. 1725 */ 1726 public AuthenticationRequest(final URI uri, 1727 final ResponseType rt, 1728 final ResponseMode rm, 1729 final Scope scope, 1730 final ClientID clientID, 1731 final URI redirectURI, 1732 final State state, 1733 final Nonce nonce, 1734 final Display display, 1735 final Prompt prompt, 1736 final JWKThumbprintConfirmation dpopJKT, 1737 final TrustChain trustChain, 1738 final int maxAge, 1739 final List<LangTag> uiLocales, 1740 final List<LangTag> claimsLocales, 1741 final JWT idTokenHint, 1742 final String loginHint, 1743 final List<ACR> acrValues, 1744 final OIDCClaimsRequest claims, 1745 final String purpose, 1746 final JWT requestObject, 1747 final URI requestURI, 1748 final CodeChallenge codeChallenge, 1749 final CodeChallengeMethod codeChallengeMethod, 1750 final List<AuthorizationDetail> authorizationDetails, 1751 final List<URI> resources, 1752 final boolean includeGrantedScopes, 1753 final Map<String,List<String>> customParams) { 1754 1755 super(uri, rt, rm, clientID, redirectURI, scope, state, 1756 codeChallenge, codeChallengeMethod, 1757 authorizationDetails, resources, includeGrantedScopes, 1758 requestObject, requestURI, prompt, dpopJKT, trustChain, customParams); 1759 1760 if (! specifiesRequestObject()) { 1761 1762 // Check parameters required by OpenID Connect if no JAR 1763 1764 if (redirectURI == null) 1765 throw new IllegalArgumentException("The redirection URI must not be null"); 1766 1767 OIDCResponseTypeValidator.validate(rt); 1768 1769 if (scope == null) 1770 throw new IllegalArgumentException("The scope must not be null"); 1771 1772 if (!scope.contains(OIDCScopeValue.OPENID)) 1773 throw new IllegalArgumentException("The scope must include an \"openid\" value"); 1774 1775 // Check nonce requirement 1776 if (nonce == null && Nonce.isRequired(rt)) { 1777 throw new IllegalArgumentException("Nonce required for response_type=" + rt); 1778 } 1779 } 1780 1781 this.nonce = nonce; 1782 1783 // Optional parameters 1784 this.display = display; 1785 this.maxAge = maxAge; 1786 1787 if (uiLocales != null) 1788 this.uiLocales = Collections.unmodifiableList(uiLocales); 1789 else 1790 this.uiLocales = null; 1791 1792 if (claimsLocales != null) 1793 this.claimsLocales = Collections.unmodifiableList(claimsLocales); 1794 else 1795 this.claimsLocales = null; 1796 1797 this.idTokenHint = idTokenHint; 1798 this.loginHint = loginHint; 1799 1800 if (acrValues != null) 1801 this.acrValues = Collections.unmodifiableList(acrValues); 1802 else 1803 this.acrValues = null; 1804 1805 this.claims = claims; 1806 1807 if (purpose != null) { 1808 if (purpose.length() < PURPOSE_MIN_LENGTH) { 1809 throw new IllegalArgumentException("The purpose must not be shorter than " + PURPOSE_MIN_LENGTH + " characters"); 1810 } 1811 if (purpose.length() > PURPOSE_MAX_LENGTH) { 1812 throw new IllegalArgumentException("The purpose must not be longer than " + PURPOSE_MAX_LENGTH +" characters"); 1813 } 1814 } 1815 1816 this.purpose = purpose; 1817 } 1818 1819 1820 /** 1821 * Returns the registered (standard) OpenID Connect authentication 1822 * request parameter names. 1823 * 1824 * @return The registered OpenID Connect authentication request 1825 * parameter names, as a unmodifiable set. 1826 */ 1827 public static Set<String> getRegisteredParameterNames() { 1828 1829 return REGISTERED_PARAMETER_NAMES; 1830 } 1831 1832 1833 /** 1834 * Returns the nonce. Corresponds to the conditionally optional 1835 * {@code nonce} parameter. 1836 * 1837 * @return The nonce, {@code null} if not specified. 1838 */ 1839 public Nonce getNonce() { 1840 1841 return nonce; 1842 } 1843 1844 1845 /** 1846 * Returns the requested display type. Corresponds to the optional 1847 * {@code display} parameter. 1848 * 1849 * @return The requested display type, {@code null} if not specified. 1850 */ 1851 public Display getDisplay() { 1852 1853 return display; 1854 } 1855 1856 1857 /** 1858 * Returns the required maximum authentication age. Corresponds to the 1859 * optional {@code max_age} parameter. 1860 * 1861 * @return The maximum authentication age, in seconds; -1 if not 1862 * specified, zero implies {@code prompt=login}. 1863 */ 1864 public int getMaxAge() { 1865 1866 return maxAge; 1867 } 1868 1869 1870 /** 1871 * Returns the end-user's preferred languages and scripts for the user 1872 * interface, ordered by preference. Corresponds to the optional 1873 * {@code ui_locales} parameter. 1874 * 1875 * @return The preferred UI locales, {@code null} if not specified. 1876 */ 1877 public List<LangTag> getUILocales() { 1878 1879 return uiLocales; 1880 } 1881 1882 1883 /** 1884 * Returns the end-user's preferred languages and scripts for the 1885 * claims being returned, ordered by preference. Corresponds to the 1886 * optional {@code claims_locales} parameter. 1887 * 1888 * @return The preferred claims locales, {@code null} if not specified. 1889 */ 1890 public List<LangTag> getClaimsLocales() { 1891 1892 return claimsLocales; 1893 } 1894 1895 1896 /** 1897 * Returns the ID Token hint. Corresponds to the conditionally optional 1898 * {@code id_token_hint} parameter. 1899 * 1900 * @return The ID Token hint, {@code null} if not specified. 1901 */ 1902 public JWT getIDTokenHint() { 1903 1904 return idTokenHint; 1905 } 1906 1907 1908 /** 1909 * Returns the login hint. Corresponds to the optional {@code login_hint} 1910 * parameter. 1911 * 1912 * @return The login hint, {@code null} if not specified. 1913 */ 1914 public String getLoginHint() { 1915 1916 return loginHint; 1917 } 1918 1919 1920 /** 1921 * Returns the requested Authentication Context Class Reference values. 1922 * Corresponds to the optional {@code acr_values} parameter. 1923 * 1924 * @return The requested ACR values, {@code null} if not specified. 1925 */ 1926 public List<ACR> getACRValues() { 1927 1928 return acrValues; 1929 } 1930 1931 1932 /** 1933 * Returns the individual claims to be returned. Corresponds to the 1934 * optional {@code claims} parameter. 1935 * 1936 * @see #getOIDCClaims() 1937 * 1938 * @return The individual claims to be returned, {@code null} if not 1939 * specified. 1940 */ 1941 @Deprecated 1942 public ClaimsRequest getClaims() { 1943 1944 return toClaimsRequestWithSilentFail(claims); 1945 } 1946 1947 1948 private static OIDCClaimsRequest toOIDCClaimsRequestWithSilentFail(final ClaimsRequest claims) { 1949 if (claims == null) { 1950 return null; 1951 } 1952 try { 1953 return OIDCClaimsRequest.parse(claims.toJSONObject()); 1954 } catch (ParseException e) { 1955 return null; 1956 } 1957 } 1958 1959 1960 private static ClaimsRequest toClaimsRequestWithSilentFail(final OIDCClaimsRequest claims) { 1961 if (claims == null) { 1962 return null; 1963 } 1964 try { 1965 return ClaimsRequest.parse(claims.toJSONObject()); 1966 } catch (ParseException e) { 1967 return null; 1968 } 1969 } 1970 1971 1972 /** 1973 * Returns the individual OpenID claims to be returned. Corresponds to 1974 * the optional {@code claims} parameter. 1975 * 1976 * @return The individual claims to be returned, {@code null} if not 1977 * specified. 1978 */ 1979 public OIDCClaimsRequest getOIDCClaims() { 1980 1981 return claims; 1982 } 1983 1984 1985 /** 1986 * Returns the transaction specific purpose. Corresponds to the 1987 * optional {@code purpose} parameter. 1988 * 1989 * @return The purpose, {@code null} if not specified. 1990 */ 1991 public String getPurpose() { 1992 1993 return purpose; 1994 } 1995 1996 1997 @Override 1998 public Map<String,List<String>> toParameters() { 1999 2000 Map <String,List<String>> params = super.toParameters(); 2001 2002 if (nonce != null) 2003 params.put("nonce", Collections.singletonList(nonce.toString())); 2004 2005 if (display != null) 2006 params.put("display", Collections.singletonList(display.toString())); 2007 2008 if (maxAge >= 0) 2009 params.put("max_age", Collections.singletonList("" + maxAge)); 2010 2011 if (uiLocales != null) { 2012 params.put("ui_locales", Collections.singletonList(LangTagUtils.concat(uiLocales))); 2013 } 2014 2015 if (CollectionUtils.isNotEmpty(claimsLocales)) { 2016 params.put("claims_locales", Collections.singletonList(LangTagUtils.concat(claimsLocales))); 2017 } 2018 2019 if (idTokenHint != null) { 2020 2021 try { 2022 params.put("id_token_hint", Collections.singletonList(idTokenHint.serialize())); 2023 2024 } catch (IllegalStateException e) { 2025 2026 throw new SerializeException("Couldn't serialize ID token hint: " + e.getMessage(), e); 2027 } 2028 } 2029 2030 if (loginHint != null) 2031 params.put("login_hint", Collections.singletonList(loginHint)); 2032 2033 if (acrValues != null) { 2034 2035 StringBuilder sb = new StringBuilder(); 2036 2037 for (ACR acr: acrValues) { 2038 2039 if (sb.length() > 0) 2040 sb.append(' '); 2041 2042 sb.append(acr.toString()); 2043 } 2044 2045 params.put("acr_values", Collections.singletonList(sb.toString())); 2046 } 2047 2048 2049 if (claims != null) 2050 params.put("claims", Collections.singletonList(claims.toJSONObject().toString())); 2051 2052 if (purpose != null) 2053 params.put("purpose", Collections.singletonList(purpose)); 2054 2055 return params; 2056 } 2057 2058 2059 @Override 2060 public JWTClaimsSet toJWTClaimsSet() { 2061 2062 JWTClaimsSet jwtClaimsSet = super.toJWTClaimsSet(); 2063 2064 if (jwtClaimsSet.getClaim("max_age") != null) { 2065 // Convert max_age to number in JSON object 2066 try { 2067 String maxAgeString = jwtClaimsSet.getStringClaim("max_age"); 2068 JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder(jwtClaimsSet); 2069 builder.claim("max_age", Integer.parseInt(maxAgeString)); 2070 return builder.build(); 2071 } catch (java.text.ParseException e) { 2072 throw new SerializeException(e.getMessage()); 2073 } 2074 } 2075 2076 return jwtClaimsSet; 2077 } 2078 2079 2080 /** 2081 * Parses an OpenID Connect authentication request from the specified 2082 * URI query parameters. 2083 * 2084 * <p>Example parameters: 2085 * 2086 * <pre> 2087 * response_type = token id_token 2088 * client_id = s6BhdRkqt3 2089 * redirect_uri = https://client.example.com/cb 2090 * scope = openid profile 2091 * state = af0ifjsldkj 2092 * nonce = -0S6_WzA2Mj 2093 * </pre> 2094 * 2095 * @param params The parameters. Must not be {@code null}. 2096 * 2097 * @return The OpenID Connect authentication request. 2098 * 2099 * @throws ParseException If the parameters couldn't be parsed to an 2100 * OpenID Connect authentication request. 2101 */ 2102 public static AuthenticationRequest parse(final Map<String,List<String>> params) 2103 throws ParseException { 2104 2105 return parse(null, params); 2106 } 2107 2108 2109 /** 2110 * Parses an OpenID Connect authentication request from the specified 2111 * URI and query parameters. 2112 * 2113 * <p>Example parameters: 2114 * 2115 * <pre> 2116 * response_type = token id_token 2117 * client_id = s6BhdRkqt3 2118 * redirect_uri = https://client.example.com/cb 2119 * scope = openid profile 2120 * state = af0ifjsldkj 2121 * nonce = -0S6_WzA2Mj 2122 * </pre> 2123 * 2124 * @param uri The URI of the OAuth 2.0 authorisation endpoint. May 2125 * be {@code null} if the {@link #toHTTPRequest} method 2126 * will not be used. 2127 * @param params The parameters. Must not be {@code null}. 2128 * 2129 * @return The OpenID Connect authentication request. 2130 * 2131 * @throws ParseException If the parameters couldn't be parsed to an 2132 * OpenID Connect authentication request. 2133 */ 2134 public static AuthenticationRequest parse(final URI uri, final Map<String,List<String>> params) 2135 throws ParseException { 2136 2137 // Parse and validate the core OAuth 2.0 autz request params in 2138 // the context of OIDC 2139 AuthorizationRequest ar = AuthorizationRequest.parse(uri, params); 2140 2141 Nonce nonce = Nonce.parse(MultivaluedMapUtils.getFirstValue(params, "nonce")); 2142 2143 if (! ar.specifiesRequestObject()) { 2144 2145 // Required params if no JAR is present 2146 2147 if (ar.getRedirectionURI() == null) { 2148 String msg = "Missing redirect_uri parameter"; 2149 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 2150 ar.getClientID(), null, ar.impliedResponseMode(), ar.getState()); 2151 } 2152 2153 if (ar.getScope() == null) { 2154 String msg = "Missing scope parameter"; 2155 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 2156 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState()); 2157 } 2158 2159 // Check nonce requirement 2160 if (nonce == null && Nonce.isRequired(ar.getResponseType())) { 2161 String msg = "Missing nonce parameter: Required for response_type=" + ar.getResponseType(); 2162 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 2163 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState()); 2164 } 2165 } 2166 2167 // Check if present (not in JAR) 2168 if (ar.getResponseType() != null) { 2169 try { 2170 OIDCResponseTypeValidator.validate(ar.getResponseType()); 2171 } catch (IllegalArgumentException e) { 2172 String msg = "Unsupported response_type parameter: " + e.getMessage(); 2173 throw new ParseException(msg, OAuth2Error.UNSUPPORTED_RESPONSE_TYPE.appendDescription(": " + msg), 2174 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState()); 2175 } 2176 } 2177 2178 // Check if present (not in JAR) 2179 if (ar.getScope() != null && ! ar.getScope().contains(OIDCScopeValue.OPENID)) { 2180 String msg = "The scope must include an openid value"; 2181 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 2182 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState()); 2183 } 2184 2185 Display display = null; 2186 2187 if (params.containsKey("display")) { 2188 try { 2189 display = Display.parse(MultivaluedMapUtils.getFirstValue(params, "display")); 2190 2191 } catch (ParseException e) { 2192 String msg = "Invalid display parameter: " + e.getMessage(); 2193 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 2194 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState(), e); 2195 } 2196 } 2197 2198 2199 String v = MultivaluedMapUtils.getFirstValue(params, "max_age"); 2200 2201 int maxAge = -1; 2202 2203 if (StringUtils.isNotBlank(v)) { 2204 2205 try { 2206 maxAge = Integer.parseInt(v); 2207 2208 } catch (NumberFormatException e) { 2209 String msg = "Invalid max_age parameter: " + v; 2210 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 2211 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState(), e); 2212 } 2213 } 2214 2215 2216 List<LangTag> uiLocales; 2217 try { 2218 uiLocales = LangTagUtils.parseLangTagList(MultivaluedMapUtils.getFirstValue(params, "ui_locales")); 2219 } catch (LangTagException e) { 2220 String msg = "Invalid ui_locales parameter: " + e.getMessage(); 2221 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 2222 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState(), e); 2223 } 2224 2225 2226 List<LangTag> claimsLocales; 2227 try { 2228 claimsLocales = LangTagUtils.parseLangTagList(MultivaluedMapUtils.getFirstValue(params, "claims_locales")); 2229 2230 } catch (LangTagException e) { 2231 String msg = "Invalid claims_locales parameter: " + e.getMessage(); 2232 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 2233 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState(), e); 2234 } 2235 2236 2237 v = MultivaluedMapUtils.getFirstValue(params, "id_token_hint"); 2238 2239 JWT idTokenHint = null; 2240 2241 if (StringUtils.isNotBlank(v)) { 2242 2243 try { 2244 idTokenHint = JWTParser.parse(v); 2245 2246 } catch (java.text.ParseException e) { 2247 String msg = "Invalid id_token_hint parameter: " + e.getMessage(); 2248 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 2249 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState(), e); 2250 } 2251 } 2252 2253 String loginHint = MultivaluedMapUtils.getFirstValue(params, "login_hint"); 2254 2255 2256 v = MultivaluedMapUtils.getFirstValue(params, "acr_values"); 2257 2258 List<ACR> acrValues = null; 2259 2260 if (StringUtils.isNotBlank(v)) { 2261 2262 acrValues = new LinkedList<>(); 2263 2264 StringTokenizer st = new StringTokenizer(v, " "); 2265 2266 while (st.hasMoreTokens()) { 2267 2268 acrValues.add(new ACR(st.nextToken())); 2269 } 2270 } 2271 2272 2273 v = MultivaluedMapUtils.getFirstValue(params, "claims"); 2274 2275 OIDCClaimsRequest claims = null; 2276 2277 if (StringUtils.isNotBlank(v)) { 2278 try { 2279 claims = OIDCClaimsRequest.parse(v); 2280 } catch (ParseException e) { 2281 String msg = "Invalid claims parameter: " + e.getMessage(); 2282 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 2283 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState(), e); 2284 } 2285 } 2286 2287 String purpose = MultivaluedMapUtils.getFirstValue(params, "purpose"); 2288 2289 if (purpose != null && (purpose.length() < PURPOSE_MIN_LENGTH || purpose.length() > PURPOSE_MAX_LENGTH)) { 2290 String msg = "Invalid purpose parameter: Must not be shorter than " + PURPOSE_MIN_LENGTH + " and longer than " + PURPOSE_MAX_LENGTH + " characters"; 2291 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg), 2292 ar.getClientID(), ar.getRedirectionURI(), ar.impliedResponseMode(), ar.getState()); 2293 } 2294 2295 2296 // Parse additional custom parameters 2297 Map<String,List<String>> customParams = null; 2298 2299 for (Map.Entry<String,List<String>> p: params.entrySet()) { 2300 2301 if (! REGISTERED_PARAMETER_NAMES.contains(p.getKey())) { 2302 // We have a custom parameter 2303 if (customParams == null) { 2304 customParams = new HashMap<>(); 2305 } 2306 customParams.put(p.getKey(), p.getValue()); 2307 } 2308 } 2309 2310 2311 return new AuthenticationRequest( 2312 uri, ar.getResponseType(), ar.getResponseMode(), ar.getScope(), ar.getClientID(), ar.getRedirectionURI(), ar.getState(), nonce, 2313 display, ar.getPrompt(), ar.getDPoPJWKThumbprintConfirmation(), ar.getTrustChain(), maxAge, uiLocales, claimsLocales, 2314 idTokenHint, loginHint, acrValues, claims, purpose, 2315 ar.getRequestObject(), ar.getRequestURI(), 2316 ar.getCodeChallenge(), ar.getCodeChallengeMethod(), 2317 ar.getAuthorizationDetails(), 2318 ar.getResources(), 2319 ar.includeGrantedScopes(), 2320 customParams); 2321 } 2322 2323 2324 /** 2325 * Parses an OpenID Connect authentication request from the specified 2326 * URI query string. 2327 * 2328 * <p>Example URI query string: 2329 * 2330 * <pre> 2331 * response_type=token%20id_token 2332 * &client_id=s6BhdRkqt3 2333 * &redirect_uri=https%3A%2F%2Fclient.example.com%2Fcb 2334 * &scope=openid%20profile 2335 * &state=af0ifjsldkj 2336 * &nonce=n-0S6_WzA2Mj 2337 * </pre> 2338 * 2339 * @param query The URI query string. Must not be {@code null}. 2340 * 2341 * @return The OpenID Connect authentication request. 2342 * 2343 * @throws ParseException If the query string couldn't be parsed to an 2344 * OpenID Connect authentication request. 2345 */ 2346 public static AuthenticationRequest parse(final String query) 2347 throws ParseException { 2348 2349 return parse(null, URLUtils.parseParameters(query)); 2350 } 2351 2352 2353 /** 2354 * Parses an OpenID Connect authentication request from the specified 2355 * URI query string. 2356 * 2357 * <p>Example URI query string: 2358 * 2359 * <pre> 2360 * response_type=token%20id_token 2361 * &client_id=s6BhdRkqt3 2362 * &redirect_uri=https%3A%2F%2Fclient.example.com%2Fcb 2363 * &scope=openid%20profile 2364 * &state=af0ifjsldkj 2365 * &nonce=n-0S6_WzA2Mj 2366 * </pre> 2367 * 2368 * @param uri The URI of the OAuth 2.0 authorisation endpoint. May be 2369 * {@code null} if the {@link #toHTTPRequest} method will 2370 * not be used. 2371 * @param query The URI query string. Must not be {@code null}. 2372 * 2373 * @return The OpenID Connect authentication request. 2374 * 2375 * @throws ParseException If the query string couldn't be parsed to an 2376 * OpenID Connect authentication request. 2377 */ 2378 public static AuthenticationRequest parse(final URI uri, final String query) 2379 throws ParseException { 2380 2381 return parse(uri, URLUtils.parseParameters(query)); 2382 } 2383 2384 2385 /** 2386 * Parses an OpenID Connect authentication request from the specified 2387 * URI. 2388 * 2389 * <p>Example URI: 2390 * 2391 * <pre> 2392 * https://server.example.com/authorize? 2393 * response_type=token%20id_token 2394 * &client_id=s6BhdRkqt3 2395 * &redirect_uri=https%3A%2F%2Fclient.example.com%2Fcb 2396 * &scope=openid%20profile 2397 * &state=af0ifjsldkj 2398 * &nonce=n-0S6_WzA2Mj 2399 * </pre> 2400 * 2401 * @param uri The URI. Must not be {@code null}. 2402 * 2403 * @return The OpenID Connect authentication request. 2404 * 2405 * @throws ParseException If the query string couldn't be parsed to an 2406 * OpenID Connect authentication request. 2407 */ 2408 public static AuthenticationRequest parse(final URI uri) 2409 throws ParseException { 2410 2411 return parse(URIUtils.getBaseURI(uri), URLUtils.parseParameters(uri.getRawQuery())); 2412 } 2413 2414 2415 /** 2416 * Parses an authentication request from the specified HTTP GET or HTTP 2417 * POST request. 2418 * 2419 * <p>Example HTTP request (GET): 2420 * 2421 * <pre> 2422 * https://server.example.com/op/authorize? 2423 * response_type=code%20id_token 2424 * &client_id=s6BhdRkqt3 2425 * &redirect_uri=https%3A%2F%2Fclient.example.com%2Fcb 2426 * &scope=openid 2427 * &nonce=n-0S6_WzA2Mj 2428 * &state=af0ifjsldkj 2429 * </pre> 2430 * 2431 * @param httpRequest The HTTP request. Must not be {@code null}. 2432 * 2433 * @return The OpenID Connect authentication request. 2434 * 2435 * @throws ParseException If the HTTP request couldn't be parsed to an 2436 * OpenID Connect authentication request. 2437 */ 2438 public static AuthenticationRequest parse(final HTTPRequest httpRequest) 2439 throws ParseException { 2440 2441 String query = httpRequest.getQuery(); 2442 2443 if (query == null) 2444 throw new ParseException("Missing URI query string"); 2445 2446 URI endpointURI = httpRequest.getURI(); 2447 2448 return parse(endpointURI, query); 2449 } 2450}