Skip to main content

openidconnect/
client.rs

1use crate::{
2    AccessToken, AdditionalClaims, AdditionalProviderMetadata, AuthDisplay, AuthPrompt, AuthType,
3    AuthUrl, AuthenticationFlow, AuthorizationCode, AuthorizationRequest, ClaimName, ClaimType,
4    ClientAuthMethod, ClientCredentialsTokenRequest, ClientId, ClientSecret, CodeTokenRequest,
5    ConfigurationError, CsrfToken, DeviceAccessTokenRequest, DeviceAuthorizationRequest,
6    DeviceAuthorizationResponse, DeviceAuthorizationUrl, EndpointMaybeSet, EndpointNotSet,
7    EndpointSet, EndpointState, ErrorResponse, ExtraDeviceAuthorizationFields, GenderClaim,
8    GrantType, IdTokenVerifier, IntrospectionRequest, IntrospectionUrl, IssuerUrl, JsonWebKey,
9    JsonWebKeySet, JweContentEncryptionAlgorithm, JweKeyManagementAlgorithm, JwsSigningAlgorithm,
10    Nonce, PasswordTokenRequest, ProviderMetadata, RedirectUrl, RefreshToken, RefreshTokenRequest,
11    ResourceOwnerPassword, ResourceOwnerUsername, ResponseMode, ResponseType, RevocableToken,
12    RevocationRequest, RevocationUrl, Scope, SubjectIdentifier, SubjectIdentifierType,
13    TokenIntrospectionResponse, TokenResponse, TokenUrl, UserInfoRequest, UserInfoUrl,
14};
15
16use std::marker::PhantomData;
17
18const OPENID_SCOPE: &str = "openid";
19
20/// OpenID Connect client.
21///
22/// # Error Types
23///
24/// To enable compile time verification that only the correct and complete set of errors for the `Client` function being
25/// invoked are exposed to the caller, the `Client` type is specialized on multiple implementations of the
26/// [`ErrorResponse`] trait. The exact [`ErrorResponse`] implementation returned varies by the RFC that the invoked
27/// `Client` function implements:
28///
29///   - Generic type `TE` (aka Token Error) for errors defined by [RFC 6749 OAuth 2.0 Authorization Framework](https://tools.ietf.org/html/rfc6749).
30///   - Generic type `TRE` (aka Token Revocation Error) for errors defined by [RFC 7009 OAuth 2.0 Token Revocation](https://tools.ietf.org/html/rfc7009).
31///
32/// For example when revoking a token, error code `unsupported_token_type` (from RFC 7009) may be returned:
33/// ```rust
34/// # use http::status::StatusCode;
35/// # use http::header::{HeaderValue, CONTENT_TYPE};
36/// # use openidconnect::core::CoreClient;
37/// # use openidconnect::{
38/// #     AccessToken,
39/// #     AuthUrl,
40/// #     ClientId,
41/// #     ClientSecret,
42/// #     HttpResponse,
43/// #     IssuerUrl,
44/// #     JsonWebKeySet,
45/// #     RequestTokenError,
46/// #     RevocationErrorResponseType,
47/// #     RevocationUrl,
48/// #     TokenUrl,
49/// # };
50/// # use thiserror::Error;
51/// #
52/// # let client =
53/// #     CoreClient::new(
54/// #         ClientId::new("aaa".to_string()),
55/// #         IssuerUrl::new("https://example".to_string()).unwrap(),
56/// #         JsonWebKeySet::default(),
57/// #     )
58/// #     .set_client_secret(ClientSecret::new("bbb".to_string()))
59/// #     .set_auth_uri(AuthUrl::new("https://example/authorize".to_string()).unwrap())
60/// #     .set_token_uri(TokenUrl::new("https://example/token".to_string()).unwrap())
61/// #     .set_revocation_url(RevocationUrl::new("https://revocation/url".to_string()).unwrap());
62/// #
63/// # #[derive(Debug, Error)]
64/// # enum FakeError {
65/// #     #[error("error")]
66/// #     Err,
67/// # }
68/// #
69/// # let http_client = |_| -> Result<HttpResponse, FakeError> {
70/// #     Ok(http::Response::builder()
71/// #         .status(StatusCode::BAD_REQUEST)
72/// #         .header(CONTENT_TYPE, HeaderValue::from_str("application/json").unwrap())
73/// #         .body(
74/// #             r#"{"error": "unsupported_token_type",
75/// #                 "error_description": "stuff happened",
76/// #                 "error_uri": "https://errors"}"#
77/// #             .to_string()
78/// #             .into_bytes(),
79/// #         )
80/// #         .unwrap())
81/// # };
82/// #
83/// let res = client
84///     .revoke_token(AccessToken::new("some token".to_string()).into())
85///     .unwrap()
86///     .request(&http_client);
87///
88/// assert!(matches!(res, Err(
89///     RequestTokenError::ServerResponse(err)) if matches!(err.error(),
90///         RevocationErrorResponseType::UnsupportedTokenType)));
91/// ```
92#[derive(Clone, Debug)]
93pub struct Client<
94    AC,
95    AD,
96    GC,
97    JE,
98    K,
99    P,
100    TE,
101    TR,
102    TIR,
103    RT,
104    TRE,
105    HasAuthUrl,
106    HasDeviceAuthUrl,
107    HasIntrospectionUrl,
108    HasRevocationUrl,
109    HasTokenUrl,
110    HasUserInfoUrl,
111> where
112    AC: AdditionalClaims,
113    AD: AuthDisplay,
114    GC: GenderClaim,
115    JE: JweContentEncryptionAlgorithm<
116        KeyType = <K::SigningAlgorithm as JwsSigningAlgorithm>::KeyType,
117    >,
118    K: JsonWebKey,
119    P: AuthPrompt,
120    TE: ErrorResponse,
121    TR: TokenResponse<AC, GC, JE, K::SigningAlgorithm>,
122    TIR: TokenIntrospectionResponse,
123    RT: RevocableToken,
124    TRE: ErrorResponse,
125    HasAuthUrl: EndpointState,
126    HasDeviceAuthUrl: EndpointState,
127    HasIntrospectionUrl: EndpointState,
128    HasRevocationUrl: EndpointState,
129    HasTokenUrl: EndpointState,
130    HasUserInfoUrl: EndpointState,
131{
132    oauth2_client: oauth2::Client<
133        TE,
134        TR,
135        TIR,
136        RT,
137        TRE,
138        HasAuthUrl,
139        HasDeviceAuthUrl,
140        HasIntrospectionUrl,
141        HasRevocationUrl,
142        HasTokenUrl,
143    >,
144    pub(crate) client_id: ClientId,
145    client_secret: Option<ClientSecret>,
146    pub(crate) issuer: IssuerUrl,
147    userinfo_endpoint: Option<UserInfoUrl>,
148    pub(crate) jwks: JsonWebKeySet<K>,
149    id_token_signing_algs: Option<Vec<K::SigningAlgorithm>>,
150    use_openid_scope: bool,
151    _phantom: PhantomData<(AC, AD, GC, JE, P, HasUserInfoUrl)>,
152}
153impl<AC, AD, GC, JE, K, P, TE, TR, TIR, RT, TRE>
154    Client<
155        AC,
156        AD,
157        GC,
158        JE,
159        K,
160        P,
161        TE,
162        TR,
163        TIR,
164        RT,
165        TRE,
166        EndpointNotSet,
167        EndpointNotSet,
168        EndpointNotSet,
169        EndpointNotSet,
170        EndpointNotSet,
171        EndpointNotSet,
172    >
173where
174    AC: AdditionalClaims,
175    AD: AuthDisplay,
176    GC: GenderClaim,
177    JE: JweContentEncryptionAlgorithm<
178        KeyType = <K::SigningAlgorithm as JwsSigningAlgorithm>::KeyType,
179    >,
180    K: JsonWebKey,
181    P: AuthPrompt,
182    TE: ErrorResponse + 'static,
183    TR: TokenResponse<AC, GC, JE, K::SigningAlgorithm>,
184    TIR: TokenIntrospectionResponse,
185    RT: RevocableToken,
186    TRE: ErrorResponse + 'static,
187{
188    /// Initialize an OpenID Connect client.
189    pub fn new(client_id: ClientId, issuer: IssuerUrl, jwks: JsonWebKeySet<K>) -> Self {
190        Client {
191            oauth2_client: oauth2::Client::new(client_id.clone()),
192            client_id,
193            client_secret: None,
194            issuer,
195            userinfo_endpoint: None,
196            jwks,
197            id_token_signing_algs: None,
198            use_openid_scope: true,
199            _phantom: PhantomData,
200        }
201    }
202}
203impl<AC, AD, GC, JE, K, P, TE, TR, TIR, RT, TRE>
204    Client<
205        AC,
206        AD,
207        GC,
208        JE,
209        K,
210        P,
211        TE,
212        TR,
213        TIR,
214        RT,
215        TRE,
216        EndpointSet,
217        EndpointNotSet,
218        EndpointNotSet,
219        EndpointNotSet,
220        EndpointMaybeSet,
221        EndpointMaybeSet,
222    >
223where
224    AC: AdditionalClaims,
225    AD: AuthDisplay,
226    GC: GenderClaim,
227    JE: JweContentEncryptionAlgorithm<
228        KeyType = <K::SigningAlgorithm as JwsSigningAlgorithm>::KeyType,
229    >,
230    K: JsonWebKey,
231    P: AuthPrompt,
232    TE: ErrorResponse + 'static,
233    TR: TokenResponse<AC, GC, JE, K::SigningAlgorithm>,
234    TIR: TokenIntrospectionResponse,
235    RT: RevocableToken,
236    TRE: ErrorResponse + 'static,
237{
238    /// Initialize an OpenID Connect client from OpenID Connect Discovery provider metadata.
239    ///
240    /// Use [`ProviderMetadata::discover`] or
241    /// [`ProviderMetadata::discover_async`] to fetch the provider metadata.
242    pub fn from_provider_metadata<A, CA, CN, CT, G, JK, RM, RS, S>(
243        provider_metadata: ProviderMetadata<A, AD, CA, CN, CT, G, JE, JK, K, RM, RS, S>,
244        client_id: ClientId,
245        client_secret: Option<ClientSecret>,
246    ) -> Self
247    where
248        A: AdditionalProviderMetadata,
249        CA: ClientAuthMethod,
250        CN: ClaimName,
251        CT: ClaimType,
252        G: GrantType,
253        JK: JweKeyManagementAlgorithm,
254        RM: ResponseMode,
255        RS: ResponseType,
256        S: SubjectIdentifierType,
257    {
258        let mut oauth2_client = oauth2::Client::new(client_id.clone())
259            .set_auth_uri(provider_metadata.authorization_endpoint().clone())
260            .set_token_uri_option(provider_metadata.token_endpoint().cloned());
261        if let Some(ref client_secret) = client_secret {
262            oauth2_client = oauth2_client.set_client_secret(client_secret.to_owned());
263        }
264
265        Client {
266            oauth2_client,
267            client_id,
268            client_secret,
269            issuer: provider_metadata.issuer().clone(),
270            userinfo_endpoint: provider_metadata.userinfo_endpoint().cloned(),
271            jwks: provider_metadata.jwks().to_owned(),
272            id_token_signing_algs: Some(
273                provider_metadata
274                    .id_token_signing_alg_values_supported()
275                    .to_owned(),
276            ),
277            use_openid_scope: true,
278            _phantom: PhantomData,
279        }
280    }
281}
282impl<
283        AC,
284        AD,
285        GC,
286        JE,
287        K,
288        P,
289        TE,
290        TR,
291        TIR,
292        RT,
293        TRE,
294        HasAuthUrl,
295        HasDeviceAuthUrl,
296        HasIntrospectionUrl,
297        HasRevocationUrl,
298        HasTokenUrl,
299        HasUserInfoUrl,
300    >
301    Client<
302        AC,
303        AD,
304        GC,
305        JE,
306        K,
307        P,
308        TE,
309        TR,
310        TIR,
311        RT,
312        TRE,
313        HasAuthUrl,
314        HasDeviceAuthUrl,
315        HasIntrospectionUrl,
316        HasRevocationUrl,
317        HasTokenUrl,
318        HasUserInfoUrl,
319    >
320where
321    AC: AdditionalClaims,
322    AD: AuthDisplay,
323    GC: GenderClaim,
324    JE: JweContentEncryptionAlgorithm<
325        KeyType = <K::SigningAlgorithm as JwsSigningAlgorithm>::KeyType,
326    >,
327    K: JsonWebKey,
328    P: AuthPrompt,
329    TE: ErrorResponse + 'static,
330    TR: TokenResponse<AC, GC, JE, K::SigningAlgorithm>,
331    TIR: TokenIntrospectionResponse,
332    RT: RevocableToken,
333    TRE: ErrorResponse + 'static,
334    HasAuthUrl: EndpointState,
335    HasDeviceAuthUrl: EndpointState,
336    HasIntrospectionUrl: EndpointState,
337    HasRevocationUrl: EndpointState,
338    HasTokenUrl: EndpointState,
339    HasUserInfoUrl: EndpointState,
340{
341    /// Set the type of client authentication used for communicating with the authorization
342    /// server.
343    ///
344    /// The default is to use HTTP Basic authentication, as recommended in
345    /// [Section 2.3.1 of RFC 6749](https://tools.ietf.org/html/rfc6749#section-2.3.1). Note that
346    /// if a client secret is omitted (i.e., [`set_client_secret()`](Self::set_client_secret) is not
347    /// called), [`AuthType::RequestBody`] is used regardless of the `auth_type` passed to
348    /// this function.
349    pub fn set_auth_type(mut self, auth_type: AuthType) -> Self {
350        self.oauth2_client = self.oauth2_client.set_auth_type(auth_type);
351        self
352    }
353
354    /// Return the type of client authentication used for communicating with the authorization
355    /// server.
356    pub fn auth_type(&self) -> &AuthType {
357        self.oauth2_client.auth_type()
358    }
359
360    /// Set the authorization endpoint.
361    ///
362    /// The client uses the authorization endpoint to obtain authorization from the resource owner
363    /// via user-agent redirection. This URL is used in all standard OAuth2 flows except the
364    /// [Resource Owner Password Credentials Grant](https://tools.ietf.org/html/rfc6749#section-4.3)
365    /// and the [Client Credentials Grant](https://tools.ietf.org/html/rfc6749#section-4.4).
366    pub fn set_auth_uri(
367        self,
368        auth_uri: AuthUrl,
369    ) -> Client<
370        AC,
371        AD,
372        GC,
373        JE,
374        K,
375        P,
376        TE,
377        TR,
378        TIR,
379        RT,
380        TRE,
381        EndpointSet,
382        HasDeviceAuthUrl,
383        HasIntrospectionUrl,
384        HasRevocationUrl,
385        HasTokenUrl,
386        HasUserInfoUrl,
387    > {
388        Client {
389            oauth2_client: self.oauth2_client.set_auth_uri(auth_uri),
390            client_id: self.client_id,
391            client_secret: self.client_secret,
392            issuer: self.issuer,
393            userinfo_endpoint: self.userinfo_endpoint,
394            jwks: self.jwks,
395            id_token_signing_algs: self.id_token_signing_algs,
396            use_openid_scope: self.use_openid_scope,
397            _phantom: PhantomData,
398        }
399    }
400
401    /// Return the Client ID.
402    pub fn client_id(&self) -> &ClientId {
403        &self.client_id
404    }
405
406    /// Set the client secret.
407    ///
408    /// A client secret is generally used for confidential (i.e., server-side) OAuth2 clients and
409    /// omitted from public (browser or native app) OAuth2 clients (see
410    /// [RFC 8252](https://tools.ietf.org/html/rfc8252)).
411    pub fn set_client_secret(mut self, client_secret: ClientSecret) -> Self {
412        self.oauth2_client = self.oauth2_client.set_client_secret(client_secret.clone());
413        self.client_secret = Some(client_secret);
414
415        self
416    }
417
418    /// Set the [RFC 8628](https://tools.ietf.org/html/rfc8628) device authorization endpoint used
419    /// for the Device Authorization Flow.
420    ///
421    /// See [`exchange_device_code()`](Self::exchange_device_code).
422    pub fn set_device_authorization_url(
423        self,
424        device_authorization_url: DeviceAuthorizationUrl,
425    ) -> Client<
426        AC,
427        AD,
428        GC,
429        JE,
430        K,
431        P,
432        TE,
433        TR,
434        TIR,
435        RT,
436        TRE,
437        HasAuthUrl,
438        EndpointSet,
439        HasIntrospectionUrl,
440        HasRevocationUrl,
441        HasTokenUrl,
442        HasUserInfoUrl,
443    > {
444        Client {
445            oauth2_client: self
446                .oauth2_client
447                .set_device_authorization_url(device_authorization_url),
448            client_id: self.client_id,
449            client_secret: self.client_secret,
450            issuer: self.issuer,
451            userinfo_endpoint: self.userinfo_endpoint,
452            jwks: self.jwks,
453            id_token_signing_algs: self.id_token_signing_algs,
454            use_openid_scope: self.use_openid_scope,
455            _phantom: PhantomData,
456        }
457    }
458
459    /// Set the [RFC 7662](https://tools.ietf.org/html/rfc7662) introspection endpoint.
460    ///
461    /// See [`introspect()`](Self::introspect).
462    pub fn set_introspection_url(
463        self,
464        introspection_url: IntrospectionUrl,
465    ) -> Client<
466        AC,
467        AD,
468        GC,
469        JE,
470        K,
471        P,
472        TE,
473        TR,
474        TIR,
475        RT,
476        TRE,
477        HasAuthUrl,
478        HasDeviceAuthUrl,
479        EndpointSet,
480        HasRevocationUrl,
481        HasTokenUrl,
482        HasUserInfoUrl,
483    > {
484        Client {
485            oauth2_client: self.oauth2_client.set_introspection_url(introspection_url),
486            client_id: self.client_id,
487            client_secret: self.client_secret,
488            issuer: self.issuer,
489            userinfo_endpoint: self.userinfo_endpoint,
490            jwks: self.jwks,
491            id_token_signing_algs: self.id_token_signing_algs,
492            use_openid_scope: self.use_openid_scope,
493            _phantom: PhantomData,
494        }
495    }
496
497    /// Set the redirect URL used by the authorization endpoint.
498    pub fn set_redirect_uri(mut self, redirect_url: RedirectUrl) -> Self {
499        self.oauth2_client = self.oauth2_client.set_redirect_uri(redirect_url);
500        self
501    }
502
503    /// Return the redirect URL used by the authorization endpoint.
504    pub fn redirect_uri(&self) -> Option<&RedirectUrl> {
505        self.oauth2_client.redirect_uri()
506    }
507
508    /// Set the [RFC 7009](https://tools.ietf.org/html/rfc7009) revocation endpoint.
509    ///
510    /// See [`revoke_token()`](Self::revoke_token).
511    pub fn set_revocation_url(
512        self,
513        revocation_uri: RevocationUrl,
514    ) -> Client<
515        AC,
516        AD,
517        GC,
518        JE,
519        K,
520        P,
521        TE,
522        TR,
523        TIR,
524        RT,
525        TRE,
526        HasAuthUrl,
527        HasDeviceAuthUrl,
528        HasIntrospectionUrl,
529        EndpointSet,
530        HasTokenUrl,
531        HasUserInfoUrl,
532    > {
533        Client {
534            oauth2_client: self.oauth2_client.set_revocation_url(revocation_uri),
535            client_id: self.client_id,
536            client_secret: self.client_secret,
537            issuer: self.issuer,
538            userinfo_endpoint: self.userinfo_endpoint,
539            jwks: self.jwks,
540            id_token_signing_algs: self.id_token_signing_algs,
541            use_openid_scope: self.use_openid_scope,
542            _phantom: PhantomData,
543        }
544    }
545
546    /// Set the token endpoint.
547    ///
548    /// The client uses the token endpoint to exchange an authorization code for an access token,
549    /// typically with client authentication. This URL is used in
550    /// all standard OAuth2 flows except the
551    /// [Implicit Grant](https://tools.ietf.org/html/rfc6749#section-4.2).
552    pub fn set_token_uri(
553        self,
554        token_uri: TokenUrl,
555    ) -> Client<
556        AC,
557        AD,
558        GC,
559        JE,
560        K,
561        P,
562        TE,
563        TR,
564        TIR,
565        RT,
566        TRE,
567        HasAuthUrl,
568        HasDeviceAuthUrl,
569        HasIntrospectionUrl,
570        HasRevocationUrl,
571        EndpointSet,
572        HasUserInfoUrl,
573    > {
574        Client {
575            oauth2_client: self.oauth2_client.set_token_uri(token_uri),
576            client_id: self.client_id,
577            client_secret: self.client_secret,
578            issuer: self.issuer,
579            userinfo_endpoint: self.userinfo_endpoint,
580            jwks: self.jwks,
581            id_token_signing_algs: self.id_token_signing_algs,
582            use_openid_scope: self.use_openid_scope,
583            _phantom: PhantomData,
584        }
585    }
586
587    /// Set the user info endpoint.
588    ///
589    /// See [`user_info()`](Self::user_info).
590    pub fn set_user_info_url(
591        self,
592        userinfo_endpoint: UserInfoUrl,
593    ) -> Client<
594        AC,
595        AD,
596        GC,
597        JE,
598        K,
599        P,
600        TE,
601        TR,
602        TIR,
603        RT,
604        TRE,
605        HasAuthUrl,
606        HasDeviceAuthUrl,
607        HasIntrospectionUrl,
608        HasRevocationUrl,
609        HasTokenUrl,
610        EndpointSet,
611    > {
612        Client {
613            oauth2_client: self.oauth2_client,
614            client_id: self.client_id,
615            client_secret: self.client_secret,
616            issuer: self.issuer,
617            userinfo_endpoint: Some(userinfo_endpoint),
618            jwks: self.jwks,
619            id_token_signing_algs: self.id_token_signing_algs,
620            use_openid_scope: self.use_openid_scope,
621            _phantom: PhantomData,
622        }
623    }
624
625    /// Enable the `openid` scope to be requested automatically.
626    ///
627    /// This scope is requested by default, so this function is only useful after previous calls to
628    /// [`disable_openid_scope`][Client::disable_openid_scope].
629    pub fn enable_openid_scope(mut self) -> Self {
630        self.use_openid_scope = true;
631        self
632    }
633
634    /// Disable the `openid` scope from being requested automatically.
635    pub fn disable_openid_scope(mut self) -> Self {
636        self.use_openid_scope = false;
637        self
638    }
639
640    /// Return an ID token verifier for use with the [`IdToken::claims`](crate::IdToken::claims)
641    /// method.
642    pub fn id_token_verifier(&self) -> IdTokenVerifier<K> {
643        let verifier = if let Some(ref client_secret) = self.client_secret {
644            IdTokenVerifier::new_confidential_client(
645                self.client_id.clone(),
646                client_secret.clone(),
647                self.issuer.clone(),
648                self.jwks.clone(),
649            )
650        } else {
651            IdTokenVerifier::new_public_client(
652                self.client_id.clone(),
653                self.issuer.clone(),
654                self.jwks.clone(),
655            )
656        };
657
658        if let Some(id_token_signing_algs) = self.id_token_signing_algs.clone() {
659            verifier.set_allowed_algs(id_token_signing_algs)
660        } else {
661            verifier
662        }
663    }
664}
665
666/// Methods requiring an authorization endpoint.
667impl<
668        AC,
669        AD,
670        GC,
671        JE,
672        K,
673        P,
674        TE,
675        TR,
676        TIR,
677        RT,
678        TRE,
679        HasDeviceAuthUrl,
680        HasIntrospectionUrl,
681        HasRevocationUrl,
682        HasTokenUrl,
683        HasUserInfoUrl,
684    >
685    Client<
686        AC,
687        AD,
688        GC,
689        JE,
690        K,
691        P,
692        TE,
693        TR,
694        TIR,
695        RT,
696        TRE,
697        EndpointSet,
698        HasDeviceAuthUrl,
699        HasIntrospectionUrl,
700        HasRevocationUrl,
701        HasTokenUrl,
702        HasUserInfoUrl,
703    >
704where
705    AC: AdditionalClaims,
706    AD: AuthDisplay,
707    GC: GenderClaim,
708    JE: JweContentEncryptionAlgorithm<
709        KeyType = <K::SigningAlgorithm as JwsSigningAlgorithm>::KeyType,
710    >,
711    K: JsonWebKey,
712    P: AuthPrompt,
713    TE: ErrorResponse + 'static,
714    TR: TokenResponse<AC, GC, JE, K::SigningAlgorithm>,
715    TIR: TokenIntrospectionResponse,
716    RT: RevocableToken,
717    TRE: ErrorResponse + 'static,
718    HasDeviceAuthUrl: EndpointState,
719    HasIntrospectionUrl: EndpointState,
720    HasRevocationUrl: EndpointState,
721    HasTokenUrl: EndpointState,
722    HasUserInfoUrl: EndpointState,
723{
724    /// Return the authorization endpoint.
725    pub fn auth_uri(&self) -> &AuthUrl {
726        self.oauth2_client.auth_uri()
727    }
728
729    /// Generate an authorization URL for a new authorization request.
730    ///
731    /// Requires [`set_auth_uri()`](Self::set_auth_uri) to have been previously
732    /// called to set the authorization endpoint.
733    ///
734    /// NOTE: [Passing authorization request parameters as a JSON Web Token
735    /// ](https://openid.net/specs/openid-connect-core-1_0.html#JWTRequests)
736    /// instead of URL query parameters is not currently supported. The
737    /// [`claims` parameter](https://openid.net/specs/openid-connect-core-1_0.html#ClaimsParameter)
738    /// is also not directly supported, although the [`AuthorizationRequest::add_extra_param`]
739    /// method can be used to add custom parameters, including `claims`.
740    ///
741    /// # Arguments
742    ///
743    /// * `authentication_flow` - The authentication flow to use (code, implicit, or hybrid).
744    /// * `state_fn` - A function that returns an opaque value used by the client to maintain state
745    ///   between the request and callback. The authorization server includes this value when
746    ///   redirecting the user-agent back to the client.
747    /// * `nonce_fn` - Similar to `state_fn`, but used to generate an opaque nonce to be used
748    ///   when verifying the ID token returned by the OpenID Connect Provider.
749    ///
750    /// # Security Warning
751    ///
752    /// Callers should use a fresh, unpredictable `state` for each authorization request and verify
753    /// that this value matches the `state` parameter passed by the authorization server to the
754    /// redirect URI. Doing so mitigates
755    /// [Cross-Site Request Forgery](https://tools.ietf.org/html/rfc6749#section-10.12)
756    ///  attacks.
757    ///
758    /// Similarly, callers should use a fresh, unpredictable `nonce` to help protect against ID
759    /// token reuse and forgery.
760    pub fn authorize_url<NF, RS, SF>(
761        &self,
762        authentication_flow: AuthenticationFlow<RS>,
763        state_fn: SF,
764        nonce_fn: NF,
765    ) -> AuthorizationRequest<AD, P, RS>
766    where
767        NF: FnOnce() -> Nonce + 'static,
768        RS: ResponseType,
769        SF: FnOnce() -> CsrfToken + 'static,
770    {
771        let request = AuthorizationRequest {
772            inner: self.oauth2_client.authorize_url(state_fn),
773            acr_values: Vec::new(),
774            authentication_flow,
775            claims_locales: Vec::new(),
776            display: None,
777            id_token_hint: None,
778            login_hint: None,
779            max_age: None,
780            nonce: nonce_fn(),
781            prompts: Vec::new(),
782            ui_locales: Vec::new(),
783        };
784        if self.use_openid_scope {
785            request.add_scope(Scope::new(OPENID_SCOPE.to_string()))
786        } else {
787            request
788        }
789    }
790}
791
792/// Methods requiring a token endpoint.
793impl<
794        AC,
795        AD,
796        GC,
797        JE,
798        K,
799        P,
800        TE,
801        TR,
802        TIR,
803        RT,
804        TRE,
805        HasAuthUrl,
806        HasDeviceAuthUrl,
807        HasIntrospectionUrl,
808        HasRevocationUrl,
809        HasUserInfoUrl,
810    >
811    Client<
812        AC,
813        AD,
814        GC,
815        JE,
816        K,
817        P,
818        TE,
819        TR,
820        TIR,
821        RT,
822        TRE,
823        HasAuthUrl,
824        HasDeviceAuthUrl,
825        HasIntrospectionUrl,
826        HasRevocationUrl,
827        EndpointSet,
828        HasUserInfoUrl,
829    >
830where
831    AC: AdditionalClaims,
832    AD: AuthDisplay,
833    GC: GenderClaim,
834    JE: JweContentEncryptionAlgorithm<
835        KeyType = <K::SigningAlgorithm as JwsSigningAlgorithm>::KeyType,
836    >,
837    K: JsonWebKey,
838    P: AuthPrompt,
839    TE: ErrorResponse + 'static,
840    TR: TokenResponse<AC, GC, JE, K::SigningAlgorithm>,
841    TIR: TokenIntrospectionResponse,
842    RT: RevocableToken,
843    TRE: ErrorResponse + 'static,
844    HasAuthUrl: EndpointState,
845    HasDeviceAuthUrl: EndpointState,
846    HasIntrospectionUrl: EndpointState,
847    HasRevocationUrl: EndpointState,
848    HasUserInfoUrl: EndpointState,
849{
850    /// Request an access token using the
851    /// [Client Credentials Flow](https://datatracker.ietf.org/doc/html/rfc6749#section-4.4).
852    ///
853    /// Requires [`set_token_uri()`](Self::set_token_uri) to have been previously
854    /// called to set the token endpoint.
855    pub fn exchange_client_credentials(&self) -> ClientCredentialsTokenRequest<TE, TR> {
856        self.oauth2_client.exchange_client_credentials()
857    }
858
859    /// Exchange a code returned during the
860    /// [Authorization Code Flow](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1)
861    /// for an access token.
862    ///
863    /// Acquires ownership of the `code` because authorization codes may only be used once to
864    /// retrieve an access token from the authorization server.
865    ///
866    /// Requires [`set_token_uri()`](Self::set_token_uri) to have been previously
867    /// called to set the token endpoint.
868    pub fn exchange_code(&self, code: AuthorizationCode) -> CodeTokenRequest<TE, TR> {
869        self.oauth2_client.exchange_code(code)
870    }
871
872    /// Exchange an [RFC 8628](https://tools.ietf.org/html/rfc8628#section-3.2) Device Authorization
873    /// Response returned by [`exchange_device_code()`](Self::exchange_device_code) for an access
874    /// token.
875    ///
876    /// Requires [`set_token_uri()`](Self::set_token_uri) to have been previously
877    /// called to set the token endpoint.
878    pub fn exchange_device_access_token<'a, EF>(
879        &'a self,
880        auth_response: &'a DeviceAuthorizationResponse<EF>,
881    ) -> DeviceAccessTokenRequest<'a, 'static, TR, EF>
882    where
883        EF: ExtraDeviceAuthorizationFields,
884    {
885        self.oauth2_client
886            .exchange_device_access_token(auth_response)
887    }
888
889    /// Request an access token using the
890    /// [Resource Owner Password Credentials Flow](https://datatracker.ietf.org/doc/html/rfc6749#section-4.3).
891    ///
892    /// Requires
893    /// [`set_token_uri()`](Self::set_token_uri) to have
894    /// been previously called to set the token endpoint.
895    pub fn exchange_password<'a>(
896        &'a self,
897        username: &'a ResourceOwnerUsername,
898        password: &'a ResourceOwnerPassword,
899    ) -> PasswordTokenRequest<'a, TE, TR> {
900        self.oauth2_client.exchange_password(username, password)
901    }
902
903    /// Exchange a refresh token for an access token.
904    ///
905    /// See <https://tools.ietf.org/html/rfc6749#section-6>.
906    ///
907    /// Requires
908    /// [`set_token_uri()`](Self::set_token_uri) to have
909    /// been previously called to set the token endpoint.
910    pub fn exchange_refresh_token<'a>(
911        &'a self,
912        refresh_token: &'a RefreshToken,
913    ) -> RefreshTokenRequest<'a, TE, TR> {
914        self.oauth2_client.exchange_refresh_token(refresh_token)
915    }
916
917    /// Return the token endpoint.
918    pub fn token_uri(&self) -> &TokenUrl {
919        self.oauth2_client.token_uri()
920    }
921}
922
923/// Methods with a possibly-set token endpoint after calling
924/// [`from_provider_metadata()`](Self::from_provider_metadata).
925impl<
926        AC,
927        AD,
928        GC,
929        JE,
930        K,
931        P,
932        TE,
933        TR,
934        TIR,
935        RT,
936        TRE,
937        HasAuthUrl,
938        HasDeviceAuthUrl,
939        HasIntrospectionUrl,
940        HasRevocationUrl,
941        HasUserInfoUrl,
942    >
943    Client<
944        AC,
945        AD,
946        GC,
947        JE,
948        K,
949        P,
950        TE,
951        TR,
952        TIR,
953        RT,
954        TRE,
955        HasAuthUrl,
956        HasDeviceAuthUrl,
957        HasIntrospectionUrl,
958        HasRevocationUrl,
959        EndpointMaybeSet,
960        HasUserInfoUrl,
961    >
962where
963    AC: AdditionalClaims,
964    AD: AuthDisplay,
965    GC: GenderClaim,
966    JE: JweContentEncryptionAlgorithm<
967        KeyType = <K::SigningAlgorithm as JwsSigningAlgorithm>::KeyType,
968    >,
969    K: JsonWebKey,
970    P: AuthPrompt,
971    TE: ErrorResponse + 'static,
972    TR: TokenResponse<AC, GC, JE, K::SigningAlgorithm>,
973    TIR: TokenIntrospectionResponse,
974    RT: RevocableToken,
975    TRE: ErrorResponse + 'static,
976    HasAuthUrl: EndpointState,
977    HasDeviceAuthUrl: EndpointState,
978    HasIntrospectionUrl: EndpointState,
979    HasRevocationUrl: EndpointState,
980    HasUserInfoUrl: EndpointState,
981{
982    /// Request an access token using the
983    /// [Client Credentials Flow](https://datatracker.ietf.org/doc/html/rfc6749#section-4.4).
984    ///
985    /// Requires [`from_provider_metadata()`](Self::from_provider_metadata) to have been previously
986    /// called to construct the client.
987    pub fn exchange_client_credentials(
988        &self,
989    ) -> Result<ClientCredentialsTokenRequest<TE, TR>, ConfigurationError> {
990        self.oauth2_client.exchange_client_credentials()
991    }
992
993    /// Exchange a code returned during the
994    /// [Authorization Code Flow](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1)
995    /// for an access token.
996    ///
997    /// Acquires ownership of the `code` because authorization codes may only be used once to
998    /// retrieve an access token from the authorization server.
999    ///
1000    /// Requires [`from_provider_metadata()`](Self::from_provider_metadata) to have been previously
1001    /// called to construct the client.
1002    pub fn exchange_code(
1003        &self,
1004        code: AuthorizationCode,
1005    ) -> Result<CodeTokenRequest<TE, TR>, ConfigurationError> {
1006        self.oauth2_client.exchange_code(code)
1007    }
1008
1009    /// Exchange an [RFC 8628](https://tools.ietf.org/html/rfc8628#section-3.2) Device Authorization
1010    /// Response returned by [`exchange_device_code()`](Self::exchange_device_code) for an access
1011    /// token.
1012    ///
1013    /// Requires [`from_provider_metadata()`](Self::from_provider_metadata) to have been previously
1014    /// called to construct the client.
1015    pub fn exchange_device_access_token<'a, EF>(
1016        &'a self,
1017        auth_response: &'a DeviceAuthorizationResponse<EF>,
1018    ) -> Result<DeviceAccessTokenRequest<'a, 'static, TR, EF>, ConfigurationError>
1019    where
1020        EF: ExtraDeviceAuthorizationFields,
1021    {
1022        self.oauth2_client
1023            .exchange_device_access_token(auth_response)
1024    }
1025
1026    /// Request an access token using the
1027    /// [Resource Owner Password Credentials Flow](https://datatracker.ietf.org/doc/html/rfc6749#section-4.3).
1028    ///
1029    /// Requires [`from_provider_metadata()`](Self::from_provider_metadata) to have been previously
1030    /// called to construct the client.
1031    pub fn exchange_password<'a>(
1032        &'a self,
1033        username: &'a ResourceOwnerUsername,
1034        password: &'a ResourceOwnerPassword,
1035    ) -> Result<PasswordTokenRequest<'a, TE, TR>, ConfigurationError> {
1036        self.oauth2_client.exchange_password(username, password)
1037    }
1038
1039    /// Exchange a refresh token for an access token.
1040    ///
1041    /// See <https://tools.ietf.org/html/rfc6749#section-6>.
1042    ///
1043    /// Requires [`from_provider_metadata()`](Self::from_provider_metadata) to have been previously
1044    /// called to construct the client.
1045    pub fn exchange_refresh_token<'a>(
1046        &'a self,
1047        refresh_token: &'a RefreshToken,
1048    ) -> Result<RefreshTokenRequest<'a, TE, TR>, ConfigurationError> {
1049        self.oauth2_client.exchange_refresh_token(refresh_token)
1050    }
1051
1052    /// Return the token endpoint.
1053    pub fn token_uri(&self) -> Option<&TokenUrl> {
1054        self.oauth2_client.token_uri()
1055    }
1056}
1057
1058/// Methods requiring a device authorization endpoint.
1059impl<
1060        AC,
1061        AD,
1062        GC,
1063        JE,
1064        K,
1065        P,
1066        TE,
1067        TR,
1068        TIR,
1069        RT,
1070        TRE,
1071        HasAuthUrl,
1072        HasIntrospectionUrl,
1073        HasRevocationUrl,
1074        HasTokenUrl,
1075        HasUserInfoUrl,
1076    >
1077    Client<
1078        AC,
1079        AD,
1080        GC,
1081        JE,
1082        K,
1083        P,
1084        TE,
1085        TR,
1086        TIR,
1087        RT,
1088        TRE,
1089        HasAuthUrl,
1090        EndpointSet,
1091        HasIntrospectionUrl,
1092        HasRevocationUrl,
1093        HasTokenUrl,
1094        HasUserInfoUrl,
1095    >
1096where
1097    AC: AdditionalClaims,
1098    AD: AuthDisplay,
1099    GC: GenderClaim,
1100    JE: JweContentEncryptionAlgorithm<
1101        KeyType = <K::SigningAlgorithm as JwsSigningAlgorithm>::KeyType,
1102    >,
1103    K: JsonWebKey,
1104    P: AuthPrompt,
1105    TE: ErrorResponse + 'static,
1106    TR: TokenResponse<AC, GC, JE, K::SigningAlgorithm>,
1107    TIR: TokenIntrospectionResponse,
1108    RT: RevocableToken,
1109    TRE: ErrorResponse + 'static,
1110    HasAuthUrl: EndpointState,
1111    HasIntrospectionUrl: EndpointState,
1112    HasRevocationUrl: EndpointState,
1113    HasTokenUrl: EndpointState,
1114    HasUserInfoUrl: EndpointState,
1115{
1116    /// Begin the [RFC 8628](https://tools.ietf.org/html/rfc8628) Device Authorization Flow and
1117    /// retrieve a Device Authorization Response.
1118    ///
1119    /// Requires
1120    /// [`set_device_authorization_url()`](Self::set_device_authorization_url) to have
1121    /// been previously called to set the device authorization endpoint.
1122    ///
1123    /// See [`exchange_device_access_token()`](Self::exchange_device_access_token).
1124    pub fn exchange_device_code(&self) -> DeviceAuthorizationRequest<TE> {
1125        let request = self.oauth2_client.exchange_device_code();
1126        if self.use_openid_scope {
1127            request.add_scope(Scope::new(OPENID_SCOPE.to_string()))
1128        } else {
1129            request
1130        }
1131    }
1132
1133    /// Return the [RFC 8628](https://tools.ietf.org/html/rfc8628) device authorization endpoint
1134    /// used for the Device Authorization Flow.
1135    ///
1136    /// See [`exchange_device_code()`](Self::exchange_device_code).
1137    pub fn device_authorization_url(&self) -> &DeviceAuthorizationUrl {
1138        self.oauth2_client.device_authorization_url()
1139    }
1140}
1141
1142/// Methods requiring an introspection endpoint.
1143impl<
1144        AC,
1145        AD,
1146        GC,
1147        JE,
1148        K,
1149        P,
1150        TE,
1151        TR,
1152        TIR,
1153        RT,
1154        TRE,
1155        HasAuthUrl,
1156        HasDeviceAuthUrl,
1157        HasRevocationUrl,
1158        HasTokenUrl,
1159        HasUserInfoUrl,
1160    >
1161    Client<
1162        AC,
1163        AD,
1164        GC,
1165        JE,
1166        K,
1167        P,
1168        TE,
1169        TR,
1170        TIR,
1171        RT,
1172        TRE,
1173        HasAuthUrl,
1174        HasDeviceAuthUrl,
1175        EndpointSet,
1176        HasRevocationUrl,
1177        HasTokenUrl,
1178        HasUserInfoUrl,
1179    >
1180where
1181    AC: AdditionalClaims,
1182    AD: AuthDisplay,
1183    GC: GenderClaim,
1184    JE: JweContentEncryptionAlgorithm<
1185        KeyType = <K::SigningAlgorithm as JwsSigningAlgorithm>::KeyType,
1186    >,
1187    K: JsonWebKey,
1188    P: AuthPrompt,
1189    TE: ErrorResponse + 'static,
1190    TR: TokenResponse<AC, GC, JE, K::SigningAlgorithm>,
1191    TIR: TokenIntrospectionResponse,
1192    RT: RevocableToken,
1193    TRE: ErrorResponse + 'static,
1194    HasAuthUrl: EndpointState,
1195    HasDeviceAuthUrl: EndpointState,
1196    HasRevocationUrl: EndpointState,
1197    HasTokenUrl: EndpointState,
1198    HasUserInfoUrl: EndpointState,
1199{
1200    /// Retrieve metadata for an access token using the
1201    /// [`RFC 7662`](https://tools.ietf.org/html/rfc7662) introspection endpoint.
1202    ///
1203    /// Requires [`set_introspection_url()`](Self::set_introspection_url) to have been previously
1204    /// called to set the introspection endpoint.
1205    pub fn introspect<'a>(&'a self, token: &'a AccessToken) -> IntrospectionRequest<'a, TE, TIR> {
1206        self.oauth2_client.introspect(token)
1207    }
1208
1209    /// Return the [RFC 7662](https://tools.ietf.org/html/rfc7662) introspection endpoint.
1210    pub fn introspection_url(&self) -> &IntrospectionUrl {
1211        self.oauth2_client.introspection_url()
1212    }
1213}
1214
1215/// Methods requiring a revocation endpoint.
1216impl<
1217        AC,
1218        AD,
1219        GC,
1220        JE,
1221        K,
1222        P,
1223        TE,
1224        TR,
1225        TIR,
1226        RT,
1227        TRE,
1228        HasAuthUrl,
1229        HasDeviceAuthUrl,
1230        HasIntrospectionUrl,
1231        HasTokenUrl,
1232        HasUserInfoUrl,
1233    >
1234    Client<
1235        AC,
1236        AD,
1237        GC,
1238        JE,
1239        K,
1240        P,
1241        TE,
1242        TR,
1243        TIR,
1244        RT,
1245        TRE,
1246        HasAuthUrl,
1247        HasDeviceAuthUrl,
1248        HasIntrospectionUrl,
1249        EndpointSet,
1250        HasTokenUrl,
1251        HasUserInfoUrl,
1252    >
1253where
1254    AC: AdditionalClaims,
1255    AD: AuthDisplay,
1256    GC: GenderClaim,
1257    JE: JweContentEncryptionAlgorithm<
1258        KeyType = <K::SigningAlgorithm as JwsSigningAlgorithm>::KeyType,
1259    >,
1260    K: JsonWebKey,
1261    P: AuthPrompt,
1262    TE: ErrorResponse + 'static,
1263    TR: TokenResponse<AC, GC, JE, K::SigningAlgorithm>,
1264    TIR: TokenIntrospectionResponse,
1265    RT: RevocableToken,
1266    TRE: ErrorResponse + 'static,
1267    HasAuthUrl: EndpointState,
1268    HasDeviceAuthUrl: EndpointState,
1269    HasIntrospectionUrl: EndpointState,
1270    HasTokenUrl: EndpointState,
1271    HasUserInfoUrl: EndpointState,
1272{
1273    /// Revoke an access or refresh token using the [RFC 7009](https://tools.ietf.org/html/rfc7009)
1274    /// revocation endpoint.
1275    ///
1276    /// Requires [`set_revocation_url()`](Self::set_revocation_url) to have been previously
1277    /// called to set the revocation endpoint.
1278    pub fn revoke_token(
1279        &self,
1280        token: RT,
1281    ) -> Result<RevocationRequest<RT, TRE>, ConfigurationError> {
1282        self.oauth2_client.revoke_token(token)
1283    }
1284
1285    /// Return the [RFC 7009](https://tools.ietf.org/html/rfc7009) revocation endpoint.
1286    ///
1287    /// See [`revoke_token()`](Self::revoke_token()).
1288    pub fn revocation_url(&self) -> &RevocationUrl {
1289        self.oauth2_client.revocation_url()
1290    }
1291}
1292
1293/// Methods requiring a user info endpoint.
1294impl<
1295        AC,
1296        AD,
1297        GC,
1298        JE,
1299        K,
1300        P,
1301        TE,
1302        TR,
1303        TIR,
1304        RT,
1305        TRE,
1306        HasAuthUrl,
1307        HasDeviceAuthUrl,
1308        HasIntrospectionUrl,
1309        HasRevocationUrl,
1310        HasTokenUrl,
1311    >
1312    Client<
1313        AC,
1314        AD,
1315        GC,
1316        JE,
1317        K,
1318        P,
1319        TE,
1320        TR,
1321        TIR,
1322        RT,
1323        TRE,
1324        HasAuthUrl,
1325        HasDeviceAuthUrl,
1326        HasIntrospectionUrl,
1327        HasRevocationUrl,
1328        HasTokenUrl,
1329        EndpointSet,
1330    >
1331where
1332    AC: AdditionalClaims,
1333    AD: AuthDisplay,
1334    GC: GenderClaim,
1335    JE: JweContentEncryptionAlgorithm<
1336        KeyType = <K::SigningAlgorithm as JwsSigningAlgorithm>::KeyType,
1337    >,
1338    K: JsonWebKey,
1339    P: AuthPrompt,
1340    TE: ErrorResponse + 'static,
1341    TR: TokenResponse<AC, GC, JE, K::SigningAlgorithm>,
1342    TIR: TokenIntrospectionResponse,
1343    RT: RevocableToken,
1344    TRE: ErrorResponse + 'static,
1345    HasAuthUrl: EndpointState,
1346    HasDeviceAuthUrl: EndpointState,
1347    HasIntrospectionUrl: EndpointState,
1348    HasRevocationUrl: EndpointState,
1349    HasTokenUrl: EndpointState,
1350{
1351    /// Request info about the user associated with the given access token.
1352    ///
1353    /// Requires [`set_user_info_url()`](Self::set_user_info_url) to have been previously
1354    /// called to set the user info endpoint.
1355    ///
1356    /// To help protect against token substitution attacks, this function optionally allows clients
1357    /// to provide the subject identifier whose user info they expect to receive. If provided and
1358    /// the subject returned by the OpenID Connect Provider does not match, the
1359    /// [`UserInfoRequest::request`] or [`UserInfoRequest::request_async`] functions will return
1360    /// [`UserInfoError::ClaimsVerification`](crate::UserInfoError::ClaimsVerification). If set to
1361    /// `None`, any subject is accepted.
1362    pub fn user_info(
1363        &self,
1364        access_token: AccessToken,
1365        expected_subject: Option<SubjectIdentifier>,
1366    ) -> UserInfoRequest<JE, K> {
1367        self.user_info_impl(self.user_info_url(), access_token, expected_subject)
1368    }
1369
1370    /// Return the user info endpoint.
1371    ///
1372    /// See ['user_info()'](Self::user_info).
1373    pub fn user_info_url(&self) -> &UserInfoUrl {
1374        // This is enforced statically via the HasUserInfo generic type.
1375        self.userinfo_endpoint
1376            .as_ref()
1377            .expect("should have user info endpoint")
1378    }
1379}
1380
1381/// Methods with a possibly-set user info endpoint.
1382impl<
1383        AC,
1384        AD,
1385        GC,
1386        JE,
1387        K,
1388        P,
1389        TE,
1390        TR,
1391        TIR,
1392        RT,
1393        TRE,
1394        HasAuthUrl,
1395        HasDeviceAuthUrl,
1396        HasIntrospectionUrl,
1397        HasRevocationUrl,
1398        HasTokenUrl,
1399    >
1400    Client<
1401        AC,
1402        AD,
1403        GC,
1404        JE,
1405        K,
1406        P,
1407        TE,
1408        TR,
1409        TIR,
1410        RT,
1411        TRE,
1412        HasAuthUrl,
1413        HasDeviceAuthUrl,
1414        HasIntrospectionUrl,
1415        HasRevocationUrl,
1416        HasTokenUrl,
1417        EndpointMaybeSet,
1418    >
1419where
1420    AC: AdditionalClaims,
1421    AD: AuthDisplay,
1422    GC: GenderClaim,
1423    JE: JweContentEncryptionAlgorithm<
1424        KeyType = <K::SigningAlgorithm as JwsSigningAlgorithm>::KeyType,
1425    >,
1426    K: JsonWebKey,
1427    P: AuthPrompt,
1428    TE: ErrorResponse + 'static,
1429    TR: TokenResponse<AC, GC, JE, K::SigningAlgorithm>,
1430    TIR: TokenIntrospectionResponse,
1431    RT: RevocableToken,
1432    TRE: ErrorResponse + 'static,
1433    HasAuthUrl: EndpointState,
1434    HasDeviceAuthUrl: EndpointState,
1435    HasIntrospectionUrl: EndpointState,
1436    HasRevocationUrl: EndpointState,
1437    HasTokenUrl: EndpointState,
1438{
1439    /// Request info about the user associated with the given access token.
1440    ///
1441    /// Requires [`from_provider_metadata()`](Self::from_provider_metadata) to have been previously
1442    /// called to construct the client.
1443    ///
1444    /// To help protect against token substitution attacks, this function optionally allows clients
1445    /// to provide the subject identifier whose user info they expect to receive. If provided and
1446    /// the subject returned by the OpenID Connect Provider does not match, the
1447    /// [`UserInfoRequest::request`] or [`UserInfoRequest::request_async`] functions will return
1448    /// [`UserInfoError::ClaimsVerification`](crate::UserInfoError::ClaimsVerification). If set to
1449    /// `None`, any subject is accepted.
1450    pub fn user_info(
1451        &self,
1452        access_token: AccessToken,
1453        expected_subject: Option<SubjectIdentifier>,
1454    ) -> Result<UserInfoRequest<JE, K>, ConfigurationError> {
1455        Ok(self.user_info_impl(
1456            self.userinfo_endpoint
1457                .as_ref()
1458                .ok_or(ConfigurationError::MissingUrl("user info"))?,
1459            access_token,
1460            expected_subject,
1461        ))
1462    }
1463
1464    /// Return the user info endpoint.
1465    ///
1466    /// See ['user_info()'](Self::user_info).
1467    pub fn user_info_url(&self) -> Option<&UserInfoUrl> {
1468        self.userinfo_endpoint.as_ref()
1469    }
1470}