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