1use std::{collections::HashMap, time::Duration};
2
3use serde_json::Value;
4
5use crate::{
6 helpers::{convert_json_to, now, validate_url},
7 http::request_async,
8 issuer::Issuer,
9 jwks::Jwks,
10 types::{
11 http_client::HttpMethod, ClientMetadata, ClientOptions, ClientRegistrationOptions, Fapi,
12 HttpRequest, OidcClientError, OidcHttpClient, OidcReturnType,
13 },
14};
15
16use super::dpop_nonce_cache::DPoPNonceCache;
17
18#[derive(Debug)]
20pub struct Client {
21 pub(crate) client_id: String,
22 pub(crate) client_secret: Option<String>,
23 pub(crate) registration_access_token: Option<String>,
24 pub(crate) registration_client_uri: Option<String>,
25 pub(crate) client_id_issued_at: Option<i64>,
26 pub(crate) client_secret_expires_at: Option<i64>,
27 pub(crate) token_endpoint_auth_method: Option<String>,
28 pub(crate) token_endpoint_auth_signing_alg: Option<String>,
29 pub(crate) introspection_endpoint_auth_method: Option<String>,
30 pub(crate) introspection_endpoint_auth_signing_alg: Option<String>,
31 pub(crate) revocation_endpoint_auth_method: Option<String>,
32 pub(crate) revocation_endpoint_auth_signing_alg: Option<String>,
33 pub(crate) redirect_uri: Option<String>,
34 pub(crate) redirect_uris: Option<Vec<String>>,
35 pub(crate) response_type: Option<String>,
36 pub(crate) response_types: Vec<String>,
37 pub(crate) grant_types: Vec<String>,
38 pub(crate) jwks_uri: Option<String>,
39 pub(crate) jwks: Option<Jwks>,
40 pub(crate) sector_identifier_uri: Option<String>,
41 pub(crate) subject_type: Option<String>,
42 pub(crate) id_token_signed_response_alg: String,
43 pub(crate) id_token_encrypted_response_alg: Option<String>,
44 pub(crate) id_token_encrypted_response_enc: Option<String>,
45 pub(crate) userinfo_signed_response_alg: Option<String>,
46 pub(crate) userinfo_encrypted_response_alg: Option<String>,
47 pub(crate) userinfo_encrypted_response_enc: Option<String>,
48 pub(crate) request_object_signing_alg: Option<String>,
49 pub(crate) request_object_encryption_alg: Option<String>,
50 pub(crate) request_object_encryption_enc: Option<String>,
51 pub(crate) default_max_age: Option<u64>,
52 pub(crate) require_auth_time: Option<bool>,
53 pub(crate) default_acr_values: Option<Vec<String>>,
54 pub(crate) initiate_login_uri: Option<String>,
55 pub(crate) request_uris: Option<String>,
56 pub(crate) tls_client_certificate_bound_access_tokens: Option<bool>,
57 pub(crate) post_logout_redirect_uris: Option<Vec<String>>,
58 pub(crate) authorization_encrypted_response_alg: Option<String>,
59 pub(crate) authorization_encrypted_response_enc: Option<String>,
60 pub(crate) authorization_signed_response_alg: Option<String>,
61 pub(crate) private_jwks: Option<Jwks>,
62 pub(crate) issuer: Option<Issuer>,
63 pub(crate) client_options: Option<ClientOptions>,
64 pub(crate) skip_max_age_check: bool,
65 pub(crate) skip_nonce_check: bool,
66 pub(crate) clock_tolerance: Duration,
67 pub(crate) fapi: Option<Fapi>,
68 pub(crate) dpop_nonce_cache: DPoPNonceCache,
69 pub(crate) dpop_bound_access_tokens: Option<bool>,
70 pub(crate) backchannel_token_delivery_mode: Option<String>,
71 pub(crate) backchannel_client_notification_endpoint: Option<String>,
72 pub(crate) backchannel_authentication_request_signing_alg: Option<String>,
73 pub(crate) backchannel_user_code_parameter: Option<bool>,
74 pub(crate) other_fields: HashMap<String, Value>,
75 pub(crate) now: fn() -> u64,
76}
77
78impl Client {
79 pub(crate) fn default(fapi: Option<Fapi>) -> Self {
80 let mut client = Self {
81 client_id: String::new(),
82 client_secret: None,
83 registration_access_token: None,
84 registration_client_uri: None,
85 client_id_issued_at: None,
86 client_secret_expires_at: None,
87 token_endpoint_auth_method: Some("client_secret_basic".to_string()),
88 token_endpoint_auth_signing_alg: None,
89 introspection_endpoint_auth_method: None,
90 introspection_endpoint_auth_signing_alg: None,
91 revocation_endpoint_auth_method: None,
92 revocation_endpoint_auth_signing_alg: None,
93 redirect_uri: None,
94 redirect_uris: None,
95 response_type: None,
96 response_types: vec!["code".to_string()],
97 grant_types: vec!["authorization_code".to_string()],
98 jwks_uri: None,
99 jwks: None,
100 sector_identifier_uri: None,
101 subject_type: None,
102 id_token_signed_response_alg: "RS256".to_string(),
103 id_token_encrypted_response_alg: None,
104 id_token_encrypted_response_enc: Some("A128CBC-HS256".to_string()),
105 userinfo_signed_response_alg: None,
106 userinfo_encrypted_response_alg: None,
107 userinfo_encrypted_response_enc: None,
108 request_object_signing_alg: None,
109 request_object_encryption_alg: None,
110 request_object_encryption_enc: None,
111 default_max_age: None,
112 require_auth_time: None,
113 default_acr_values: None,
114 initiate_login_uri: None,
115 request_uris: None,
116 private_jwks: None,
117 issuer: None,
118 tls_client_certificate_bound_access_tokens: None,
119 post_logout_redirect_uris: None,
120 authorization_encrypted_response_alg: None,
121 authorization_encrypted_response_enc: None,
122 authorization_signed_response_alg: None,
123 other_fields: HashMap::new(),
124 client_options: None,
125 skip_max_age_check: false,
126 skip_nonce_check: false,
127 clock_tolerance: Duration::from_secs(0),
128 fapi: None,
129 dpop_nonce_cache: DPoPNonceCache::new(),
130 dpop_bound_access_tokens: None,
131 backchannel_token_delivery_mode: None,
132 backchannel_client_notification_endpoint: None,
133 backchannel_authentication_request_signing_alg: None,
134 backchannel_user_code_parameter: None,
135 now,
136 };
137
138 match fapi.as_ref() {
139 Some(Fapi::V1) => {
140 client.grant_types = vec!["authorization_code".to_string(), "implicit".to_string()];
141 client.id_token_signed_response_alg = "PS256".to_string();
142 client.authorization_signed_response_alg = Some("PS256".to_string());
143 client.response_types = vec!["code".to_string(), "id_token".to_string()];
144 client.tls_client_certificate_bound_access_tokens = Some(true);
145 client.token_endpoint_auth_method = None;
146 }
147 Some(Fapi::V2) => {
148 client.id_token_signed_response_alg = "PS256".to_string();
149 client.authorization_signed_response_alg = Some("PS256".to_string());
150 client.token_endpoint_auth_method = None;
151 }
152 None => {}
153 };
154
155 client.fapi = fapi;
156
157 client
158 }
159
160 pub(crate) fn from_internal(
161 metadata: ClientMetadata,
162 issuer: Option<&Issuer>,
163 jwks: Option<Jwks>,
164 options: Option<ClientOptions>,
165 fapi: Option<Fapi>,
166 ) -> OidcReturnType<Self> {
167 let mut valid_client_id = true;
168
169 if let Some(client_id) = &metadata.client_id {
170 if client_id.is_empty() {
171 valid_client_id = false;
172 }
173 } else {
174 valid_client_id = false;
175 }
176
177 if !valid_client_id {
178 return Err(Box::new(OidcClientError::new_type_error(
179 "client_id is required",
180 None,
181 )));
182 }
183
184 let mut client = Self {
185 client_id: metadata.client_id.unwrap(),
186 client_secret: metadata.client_secret,
187 sector_identifier_uri: metadata.sector_identifier_uri,
188 subject_type: metadata.subject_type,
189 registration_access_token: metadata.registration_access_token,
190 registration_client_uri: metadata.registration_client_uri,
191 client_id_issued_at: metadata.client_id_issued_at,
192 client_secret_expires_at: metadata.client_secret_expires_at,
193 id_token_encrypted_response_alg: metadata.id_token_encrypted_response_alg,
194 userinfo_signed_response_alg: metadata.userinfo_signed_response_alg,
195 userinfo_encrypted_response_alg: metadata.userinfo_encrypted_response_alg,
196 userinfo_encrypted_response_enc: metadata.userinfo_encrypted_response_enc,
197 request_object_signing_alg: metadata.request_object_signing_alg,
198 request_object_encryption_alg: metadata.request_object_encryption_alg,
199 request_object_encryption_enc: metadata.request_object_encryption_enc,
200 jwks_uri: metadata.jwks_uri,
201 jwks: metadata.jwks,
202 default_max_age: metadata.default_max_age,
203 require_auth_time: metadata.require_auth_time,
204 default_acr_values: metadata.default_acr_values,
205 initiate_login_uri: metadata.initiate_login_uri,
206 request_uris: metadata.request_uris,
207 post_logout_redirect_uris: metadata.post_logout_redirect_uris,
208 authorization_encrypted_response_alg: metadata.authorization_encrypted_response_alg,
209 authorization_encrypted_response_enc: metadata.authorization_encrypted_response_enc,
210 dpop_bound_access_tokens: metadata.dpop_bound_access_tokens,
211 backchannel_authentication_request_signing_alg: metadata
212 .backchannel_authentication_request_signing_alg,
213 backchannel_client_notification_endpoint: metadata
214 .backchannel_client_notification_endpoint,
215 backchannel_token_delivery_mode: metadata.backchannel_token_delivery_mode,
216 backchannel_user_code_parameter: metadata.backchannel_user_code_parameter,
217 other_fields: metadata.other_fields,
218 ..Client::default(fapi)
219 };
220
221 if metadata
222 .tls_client_certificate_bound_access_tokens
223 .is_some()
224 {
225 client.tls_client_certificate_bound_access_tokens =
226 metadata.tls_client_certificate_bound_access_tokens;
227 }
228
229 if metadata.authorization_signed_response_alg.is_some() {
230 client.authorization_signed_response_alg = metadata.authorization_signed_response_alg;
231 }
232
233 client.client_options = options;
234
235 if client.jwks_uri.is_some() && client.jwks.is_some() {
236 client.jwks = None;
237 }
238
239 if metadata.response_type.is_some() && metadata.response_types.is_some() {
240 return Err(Box::new(OidcClientError::new_type_error(
241 "provide a response_type or response_types, not both",
242 None,
243 )));
244 }
245
246 if let Some(response_type) = &metadata.response_type {
247 client.response_type = Some(response_type.clone());
248 client.response_types = vec![response_type.clone()];
249 }
250
251 if let Some(response_types) = &metadata.response_types {
252 client.response_types = response_types.clone().to_vec();
253 }
254
255 if metadata.redirect_uri.is_some() && metadata.redirect_uris.is_some() {
256 return Err(Box::new(OidcClientError::new_type_error(
257 "provide a redirect_uri or redirect_uris, not both",
258 None,
259 )));
260 }
261
262 if let Some(redirect_uri) = &metadata.redirect_uri {
263 client.redirect_uri = Some(redirect_uri.clone());
264 client.redirect_uris = Some(vec![redirect_uri.clone()])
265 }
266
267 if let Some(redirect_uris) = &metadata.redirect_uris {
268 client.redirect_uris = Some(redirect_uris.clone().to_vec());
269 }
270
271 if let Some(team) = metadata.token_endpoint_auth_method {
272 client.token_endpoint_auth_method = Some(team);
273 } else if let Some(iss) = issuer {
274 if let Some(teams) = &iss.token_endpoint_auth_methods_supported {
275 if let Some(team) = &client.token_endpoint_auth_method {
276 if !teams.contains(team) && teams.contains(&"client_secret_post".to_string()) {
277 client.token_endpoint_auth_method = Some("client_secret_post".to_string());
278 }
279 }
280 }
281 }
282
283 if metadata.token_endpoint_auth_signing_alg.is_some() {
284 client.token_endpoint_auth_signing_alg = metadata.token_endpoint_auth_signing_alg;
285 }
286
287 client.introspection_endpoint_auth_method = metadata
288 .introspection_endpoint_auth_method
289 .or(client.token_endpoint_auth_method.clone());
290
291 client.introspection_endpoint_auth_signing_alg = metadata
292 .introspection_endpoint_auth_signing_alg
293 .or(client.token_endpoint_auth_signing_alg.clone());
294
295 client.revocation_endpoint_auth_method = metadata
296 .revocation_endpoint_auth_method
297 .or(client.token_endpoint_auth_method.clone());
298
299 client.revocation_endpoint_auth_signing_alg = metadata
300 .revocation_endpoint_auth_signing_alg
301 .or(client.token_endpoint_auth_signing_alg.clone());
302
303 if let Some(iss) = issuer {
304 if iss.token_endpoint.is_some() {
305 Self::assert_signing_alg_values_support(
306 &client.token_endpoint_auth_method.clone(),
307 &client.token_endpoint_auth_signing_alg,
308 &iss.token_endpoint_auth_signing_alg_values_supported,
309 "token",
310 )?;
311 }
312
313 if iss.introspection_endpoint.is_some() {
314 Self::assert_signing_alg_values_support(
315 &client.introspection_endpoint_auth_method,
316 &client.introspection_endpoint_auth_signing_alg,
317 &iss.token_endpoint_auth_signing_alg_values_supported,
318 "introspection",
319 )?;
320 }
321
322 if iss.revocation_endpoint.is_some() {
323 Self::assert_signing_alg_values_support(
324 &client.revocation_endpoint_auth_method,
325 &client.revocation_endpoint_auth_signing_alg,
326 &iss.token_endpoint_auth_signing_alg_values_supported,
327 "revocation",
328 )?;
329 }
330
331 client.issuer = Some(iss.clone());
332 }
333
334 if metadata.id_token_encrypted_response_enc.is_some() {
335 client.id_token_encrypted_response_enc = metadata.id_token_encrypted_response_enc;
336 }
337
338 if jwks.is_some() {
339 client.private_jwks = jwks;
340 }
341
342 if let Some(alg) = metadata.id_token_signed_response_alg {
343 client.id_token_signed_response_alg = alg;
344 }
345
346 if client.is_fapi1() {
347 match client.token_endpoint_auth_method.as_deref() {
348 Some("private_key_jwt") => {
349 if client.private_jwks.is_none() {
350 return Err(Box::new(OidcClientError::new_type_error(
351 "jwks is required",
352 None,
353 )));
354 }
355 }
356 Some("self_signed_tls_client_auth") | Some("tls_client_auth") => {}
357 Some(_) => {
358 return Err(Box::new(OidcClientError::new_type_error(
359 "invalid or unsupported token_endpoint_auth_method",
360 None,
361 )));
362 }
363 None => {
364 return Err(Box::new(OidcClientError::new_type_error(
365 "token_endpoint_auth_method is required",
366 None,
367 )));
368 }
369 };
370 }
371
372 if client.is_fapi2() {
373 match (
374 client.tls_client_certificate_bound_access_tokens.as_ref(),
375 client.dpop_bound_access_tokens.as_ref(),
376 ) {
377 (Some(&false), Some(&false))
378 | (Some(&false), None)
379 | (None, Some(&false))
380 | (None, None) => return Err(Box::new(OidcClientError::new_type_error(
381 "one of tls_client_certificate_bound_access_tokens or dpop_bound_access_tokens must be true",
382 None,
383 ))),
384
385 (Some(&true), Some(&true)) => return Err(Box::new(OidcClientError::new_type_error(
386 "only one of tls_client_certificate_bound_access_tokens or dpop_bound_access_tokens must be true",
387 None,
388 ))),
389
390 (_, _) => {}
391 };
392 }
393
394 Ok(client)
395 }
396
397 fn assert_signing_alg_values_support(
398 auth_method: &Option<String>,
399 supported_alg: &Option<String>,
400 issuer_supported_alg_values: &Option<Vec<String>>,
401 endpoint: &str,
402 ) -> OidcReturnType<()> {
403 if let Some(am) = auth_method {
404 if am.ends_with("_jwt")
405 && supported_alg.is_none()
406 && issuer_supported_alg_values.is_none()
407 {
408 return Err(Box::new(OidcClientError::new_type_error(
409 &format!("{endpoint}_endpoint_auth_signing_alg_values_supported must be configured on the issuer if {endpoint}_endpoint_auth_signing_alg is not defined on a client"),
410 None,
411 )));
412 }
413 }
414 Ok(())
415 }
416
417 pub fn get_other_fields(&self) -> &HashMap<String, Value> {
419 &self.other_fields
420 }
421}
422
423impl Client {
425 pub async fn from_uri_async<T>(
437 http_client: &T,
438 registration_client_uri: &str,
439 issuer: &Issuer,
440 registration_access_token: Option<String>,
441 jwks: Option<Jwks>,
442 client_options: Option<ClientOptions>,
443 fapi: Option<Fapi>,
444 ) -> OidcReturnType<Self>
445 where
446 T: OidcHttpClient,
447 {
448 Self::jwks_only_private_keys_validation(jwks.as_ref())?;
449
450 let url = validate_url(registration_client_uri)?;
451
452 let mut headers = HashMap::new();
453 headers.insert("accept".to_string(), vec!["application/json".to_string()]);
454
455 if let Some(rat) = registration_access_token {
456 headers.insert("authorization".to_string(), vec![format!("Bearer {rat}")]);
457 }
458
459 let req = HttpRequest::new()
460 .url(url)
461 .method(HttpMethod::GET)
462 .expect_body(true)
463 .expect_status_code(200)
464 .expect_bearer(true)
465 .headers(headers);
466
467 let res = request_async(req, http_client).await?;
468
469 let client_metadata = convert_json_to::<ClientMetadata>(res.body.as_ref().unwrap())
470 .map_err(|_| {
471 OidcClientError::new_op_error(
472 "invalid client metadata".to_string(),
473 Some("error while deserializing".to_string()),
474 None,
475 Some(res),
476 )
477 })?;
478
479 Self::from_internal(client_metadata, Some(issuer), jwks, client_options, fapi)
480 }
481}
482
483impl Client {
485 pub async fn register_async<T>(
495 http_client: &T,
496 issuer: &Issuer,
497 mut client_metadata: ClientMetadata,
498 register_options: Option<ClientRegistrationOptions>,
499 fapi: Option<Fapi>,
500 ) -> OidcReturnType<Self>
501 where
502 T: OidcHttpClient,
503 {
504 if issuer.registration_endpoint.is_none() {
505 return Err(Box::new(OidcClientError::new_type_error(
506 "registration_endpoint must be configured on the issuer",
507 None,
508 )));
509 }
510
511 let mut initial_access_token: Option<String> = None;
512 let mut jwks: Option<Jwks> = None;
513 let mut client_options: Option<ClientOptions> = None;
514
515 if let Some(options) = ®ister_options {
516 initial_access_token.clone_from(&options.initial_access_token);
517 jwks.clone_from(&options.jwks);
518 client_options = Some(options.client_options.clone());
519
520 if options.jwks.is_some()
521 && client_metadata.jwks_uri.is_none()
522 && client_metadata.jwks.is_none()
523 {
524 if let Some(jwks) = options.jwks.as_ref() {
525 client_metadata.jwks = Some(jwks.get_public_jwks());
526 }
527 }
528 }
529
530 Self::jwks_only_private_keys_validation(jwks.as_ref())?;
531
532 let url = validate_url(issuer.registration_endpoint.as_ref().unwrap())?;
533
534 let body = serde_json::to_string(&client_metadata).map_err(|_| {
535 OidcClientError::new_error("client metadata is an invalid json format", None)
536 })?;
537
538 let mut headers = HashMap::new();
539 headers.insert("accept".to_string(), vec!["application/json".to_string()]);
540
541 if let Some(iat) = initial_access_token {
542 headers.insert("authorization".to_string(), vec![format!("Bearer {iat}")]);
543 }
544
545 let req = HttpRequest::new()
546 .url(url)
547 .method(HttpMethod::POST)
548 .expect_body(true)
549 .expect_status_code(201)
550 .expect_bearer(true)
551 .headers(headers)
552 .json(body);
553
554 let response = request_async(req, http_client).await?;
555
556 let client_metadata = convert_json_to::<ClientMetadata>(response.body.as_ref().unwrap())
557 .map_err(|_| {
558 OidcClientError::new_op_error(
559 "invalid client metadata".to_string(),
560 None,
561 None,
562 Some(response),
563 )
564 })?;
565
566 Self::from_internal(client_metadata, Some(issuer), jwks, client_options, fapi)
567 }
568
569 pub fn metadata(&self) -> ClientMetadata {
572 ClientMetadata {
573 client_id: Some(self.client_id.clone()),
574 client_secret: self.client_secret.clone(),
575 registration_access_token: self.registration_access_token.clone(),
576 registration_client_uri: self.registration_client_uri.clone(),
577 client_id_issued_at: self.client_id_issued_at,
578 client_secret_expires_at: self.client_secret_expires_at,
579 token_endpoint_auth_method: self.token_endpoint_auth_method.clone(),
580 token_endpoint_auth_signing_alg: self.token_endpoint_auth_signing_alg.clone(),
581 introspection_endpoint_auth_method: self.introspection_endpoint_auth_method.clone(),
582 introspection_endpoint_auth_signing_alg: self
583 .introspection_endpoint_auth_signing_alg
584 .clone(),
585 revocation_endpoint_auth_method: self.revocation_endpoint_auth_method.clone(),
586 revocation_endpoint_auth_signing_alg: self.revocation_endpoint_auth_signing_alg.clone(),
587 redirect_uri: self.redirect_uri.clone(),
588 redirect_uris: self.redirect_uris.clone(),
589 response_type: self.response_type.clone(),
590 response_types: Some(self.response_types.clone()),
591 grant_types: Some(self.grant_types.clone()),
592 jwks_uri: self.jwks_uri.clone(),
593 jwks: self.jwks.clone(),
594 sector_identifier_uri: self.sector_identifier_uri.clone(),
595 subject_type: self.subject_type.clone(),
596 id_token_signed_response_alg: Some(self.id_token_signed_response_alg.clone()),
597 id_token_encrypted_response_alg: self.id_token_encrypted_response_alg.clone(),
598 id_token_encrypted_response_enc: self.id_token_encrypted_response_enc.clone(),
599 userinfo_signed_response_alg: self.userinfo_signed_response_alg.clone(),
600 userinfo_encrypted_response_alg: self.userinfo_encrypted_response_alg.clone(),
601 userinfo_encrypted_response_enc: self.userinfo_encrypted_response_enc.clone(),
602 request_object_signing_alg: self.request_object_signing_alg.clone(),
603 request_object_encryption_alg: self.request_object_encryption_alg.clone(),
604 request_object_encryption_enc: self.request_object_encryption_enc.clone(),
605 default_max_age: self.default_max_age,
606 require_auth_time: self.require_auth_time,
607 default_acr_values: self.default_acr_values.clone(),
608 initiate_login_uri: self.initiate_login_uri.clone(),
609 request_uris: self.request_uris.clone(),
610 tls_client_certificate_bound_access_tokens: self
611 .tls_client_certificate_bound_access_tokens,
612 post_logout_redirect_uris: self.post_logout_redirect_uris.clone(),
613 authorization_signed_response_alg: self.authorization_signed_response_alg.clone(),
614 authorization_encrypted_response_alg: self.authorization_encrypted_response_alg.clone(),
615 authorization_encrypted_response_enc: self.authorization_encrypted_response_enc.clone(),
616 dpop_bound_access_tokens: self.dpop_bound_access_tokens,
617 backchannel_token_delivery_mode: self.backchannel_token_delivery_mode.clone(),
618 backchannel_client_notification_endpoint: self
619 .backchannel_client_notification_endpoint
620 .clone(),
621 backchannel_authentication_request_signing_alg: self
622 .backchannel_authentication_request_signing_alg
623 .clone(),
624 backchannel_user_code_parameter: self.backchannel_user_code_parameter,
625 other_fields: self.other_fields.clone(),
626 }
627 }
628
629 pub(crate) fn jwks_only_private_keys_validation(jwks: Option<&Jwks>) -> OidcReturnType<()> {
631 if let Some(jwks) = jwks {
632 if !jwks.is_only_private_keys() || jwks.has_oct_keys() {
633 return Err(Box::new(OidcClientError::new_error(
634 "jwks must only contain private keys",
635 None,
636 )));
637 }
638 }
639 Ok(())
640 }
641}
642
643impl Clone for Client {
644 fn clone(&self) -> Self {
645 Self {
646 client_id: self.client_id.clone(),
647 client_secret: self.client_secret.clone(),
648 registration_access_token: self.registration_access_token.clone(),
649 registration_client_uri: self.registration_client_uri.clone(),
650 client_id_issued_at: self.client_id_issued_at,
651 client_secret_expires_at: self.client_secret_expires_at,
652 token_endpoint_auth_method: self.token_endpoint_auth_method.clone(),
653 token_endpoint_auth_signing_alg: self.token_endpoint_auth_signing_alg.clone(),
654 introspection_endpoint_auth_method: self.introspection_endpoint_auth_method.clone(),
655 introspection_endpoint_auth_signing_alg: self
656 .introspection_endpoint_auth_signing_alg
657 .clone(),
658 revocation_endpoint_auth_method: self.revocation_endpoint_auth_method.clone(),
659 revocation_endpoint_auth_signing_alg: self.revocation_endpoint_auth_signing_alg.clone(),
660 redirect_uri: self.redirect_uri.clone(),
661 redirect_uris: self.redirect_uris.clone(),
662 response_type: self.response_type.clone(),
663 response_types: self.response_types.clone(),
664 grant_types: self.grant_types.clone(),
665 jwks_uri: self.jwks_uri.clone(),
666 jwks: self.jwks.clone(),
667 sector_identifier_uri: self.sector_identifier_uri.clone(),
668 subject_type: self.subject_type.clone(),
669 id_token_signed_response_alg: self.id_token_signed_response_alg.clone(),
670 id_token_encrypted_response_alg: self.id_token_encrypted_response_alg.clone(),
671 id_token_encrypted_response_enc: self.id_token_encrypted_response_enc.clone(),
672 userinfo_signed_response_alg: self.userinfo_signed_response_alg.clone(),
673 userinfo_encrypted_response_alg: self.userinfo_encrypted_response_alg.clone(),
674 userinfo_encrypted_response_enc: self.userinfo_encrypted_response_enc.clone(),
675 request_object_signing_alg: self.request_object_signing_alg.clone(),
676 request_object_encryption_alg: self.request_object_encryption_alg.clone(),
677 request_object_encryption_enc: self.request_object_encryption_enc.clone(),
678 default_max_age: self.default_max_age,
679 require_auth_time: self.require_auth_time,
680 default_acr_values: self.default_acr_values.clone(),
681 initiate_login_uri: self.initiate_login_uri.clone(),
682 request_uris: self.request_uris.clone(),
683 tls_client_certificate_bound_access_tokens: self
684 .tls_client_certificate_bound_access_tokens,
685 post_logout_redirect_uris: self.post_logout_redirect_uris.clone(),
686 authorization_encrypted_response_alg: self.authorization_encrypted_response_alg.clone(),
687 authorization_encrypted_response_enc: self.authorization_encrypted_response_enc.clone(),
688 authorization_signed_response_alg: self.authorization_signed_response_alg.clone(),
689 other_fields: self.other_fields.clone(),
690 private_jwks: self.private_jwks.clone(),
691 issuer: self.issuer.clone(),
692 client_options: self.client_options.clone(),
693 skip_max_age_check: self.skip_max_age_check,
694 skip_nonce_check: self.skip_nonce_check,
695 clock_tolerance: self.clock_tolerance,
696 fapi: self.fapi.clone(),
697 dpop_nonce_cache: self.dpop_nonce_cache.clone(),
698 dpop_bound_access_tokens: self.dpop_bound_access_tokens,
699 backchannel_token_delivery_mode: self.backchannel_token_delivery_mode.clone(),
700 backchannel_client_notification_endpoint: self
701 .backchannel_client_notification_endpoint
702 .clone(),
703 backchannel_authentication_request_signing_alg: self
704 .backchannel_authentication_request_signing_alg
705 .clone(),
706 backchannel_user_code_parameter: self.backchannel_user_code_parameter,
707 now: self.now,
708 }
709 }
710}
711
712#[cfg(test)]
713#[path = "../tests/client/mod.rs"]
714mod client_test;