openidconnect 4.0.1

OpenID Connect library
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
use crate::core::{
    CoreApplicationType, CoreClientAuthMethod, CoreClientMetadata, CoreClientRegistrationResponse,
    CoreGrantType, CoreJweContentEncryptionAlgorithm, CoreJweKeyManagementAlgorithm,
    CoreJwsSigningAlgorithm, CoreResponseType, CoreSubjectIdentifierType,
};
use crate::jwt::tests::TEST_RSA_PUB_KEY;
use crate::{
    AuthenticationContextClass, ClientConfigUrl, ClientContactEmail, ClientName, ClientUrl,
    JsonWebKeySet, JsonWebKeySetUrl, LanguageTag, LogoUrl, PolicyUrl, RequestUrl, ResponseTypes,
    SectorIdentifierUrl, ToSUrl,
};
use crate::{ClientId, RedirectUrl};

use chrono::{TimeZone, Utc};
use itertools::sorted;

use std::time::Duration;

#[test]
fn test_metadata_serialization() {
    // `jwks_uri` and `jwks` aren't supposed to be used together, but this test is just for
    // serialization/deserialization.
    let json_response = format!("{{
            \"redirect_uris\": [\"https://example.com/redirect-1\", \"https://example.com/redirect-2\"],
            \"response_types\": [\"code\", \"code token id_token\"],
            \"grant_types\": [\"authorization_code\", \"client_credentials\", \"implicit\", \
                \"password\", \"refresh_token\"],
            \"application_type\": \"web\",
            \"contacts\": [\"user@example.com\", \"admin@openidconnect.local\"],
            \"client_name\": \"Example\",
            \"client_name#es\": \"Ejemplo\",
            \"logo_uri\": \"https://example.com/logo.png\",
            \"logo_uri#fr\": \"https://example.com/logo-fr.png\",
            \"client_uri\": \"https://example.com/client-app\",
            \"client_uri#de\": \"https://example.com/client-app-de\",
            \"policy_uri\": \"https://example.com/policy\",
            \"policy_uri#sr-Latn\": \"https://example.com/policy-sr-latin\",
            \"tos_uri\": \"https://example.com/tos\",
            \"tos_uri#sr-Cyrl\": \"https://example.com/tos-sr-cyrl\",
            \"jwks_uri\": \"https://example.com/jwks\",
            \"jwks\": {{\"keys\": [{}]}},
            \"sector_identifier_uri\": \"https://example.com/sector\",
            \"subject_type\": \"pairwise\",
            \"id_token_signed_response_alg\": \"HS256\",
            \"id_token_encrypted_response_alg\": \"RSA1_5\",
            \"id_token_encrypted_response_enc\": \"A128CBC-HS256\",
            \"userinfo_signed_response_alg\": \"RS384\",
            \"userinfo_encrypted_response_alg\": \"RSA-OAEP\",
            \"userinfo_encrypted_response_enc\": \"A256CBC-HS512\",
            \"request_object_signing_alg\": \"ES512\",
            \"request_object_encryption_alg\": \"ECDH-ES+A128KW\",
            \"request_object_encryption_enc\": \"A256GCM\",
            \"token_endpoint_auth_method\": \"client_secret_basic\",
            \"token_endpoint_auth_signing_alg\": \"PS512\",
            \"default_max_age\": 3600,
            \"require_auth_time\": true,
            \"default_acr_values\": [\"0\", \"urn:mace:incommon:iap:silver\", \
                \"urn:mace:incommon:iap:bronze\"],
            \"initiate_login_uri\": \"https://example.com/login\",
            \"request_uris\": [\"https://example.com/request-1\", \"https://example.com/request-2\"]
        }}", TEST_RSA_PUB_KEY);

    let client_metadata: CoreClientMetadata = serde_json::from_str(&json_response).unwrap();

    assert_eq!(
        *client_metadata.redirect_uris(),
        vec![
            RedirectUrl::new("https://example.com/redirect-1".to_string()).unwrap(),
            RedirectUrl::new("https://example.com/redirect-2".to_string()).unwrap(),
        ]
    );
    assert_eq!(
        *client_metadata.response_types().unwrap(),
        vec![
            ResponseTypes::new(vec![CoreResponseType::Code]),
            ResponseTypes::new(vec![
                CoreResponseType::Code,
                CoreResponseType::Token,
                CoreResponseType::IdToken,
            ]),
        ]
    );
    assert_eq!(
        client_metadata.grant_types().unwrap(),
        &vec![
            CoreGrantType::AuthorizationCode,
            CoreGrantType::ClientCredentials,
            CoreGrantType::Implicit,
            CoreGrantType::Password,
            CoreGrantType::RefreshToken,
        ]
    );
    assert_eq!(
        *client_metadata.application_type().unwrap(),
        CoreApplicationType::Web
    );
    assert_eq!(
        *client_metadata.contacts().unwrap(),
        vec![
            ClientContactEmail::new("user@example.com".to_string()),
            ClientContactEmail::new("admin@openidconnect.local".to_string()),
        ]
    );
    assert_eq!(
        sorted(client_metadata.client_name().unwrap().clone())
            .collect::<Vec<(Option<LanguageTag>, ClientName)>>(),
        vec![
            (None, ClientName::new("Example".to_string())),
            (
                Some(LanguageTag::new("es".to_string())),
                ClientName::new("Ejemplo".to_string()),
            ),
        ]
    );
    assert_eq!(
        sorted(client_metadata.logo_uri().unwrap().clone())
            .collect::<Vec<(Option<LanguageTag>, LogoUrl)>>(),
        vec![
            (
                None,
                LogoUrl::new("https://example.com/logo.png".to_string()).unwrap(),
            ),
            (
                Some(LanguageTag::new("fr".to_string())),
                LogoUrl::new("https://example.com/logo-fr.png".to_string()).unwrap(),
            ),
        ]
    );
    assert_eq!(
        sorted(client_metadata.client_uri().unwrap().clone())
            .collect::<Vec<(Option<LanguageTag>, ClientUrl)>>(),
        vec![
            (
                None,
                ClientUrl::new("https://example.com/client-app".to_string()).unwrap(),
            ),
            (
                Some(LanguageTag::new("de".to_string())),
                ClientUrl::new("https://example.com/client-app-de".to_string()).unwrap(),
            ),
        ]
    );
    assert_eq!(
        sorted(client_metadata.policy_uri().unwrap().clone())
            .collect::<Vec<(Option<LanguageTag>, PolicyUrl)>>(),
        vec![
            (
                None,
                PolicyUrl::new("https://example.com/policy".to_string()).unwrap(),
            ),
            (
                Some(LanguageTag::new("sr-Latn".to_string())),
                PolicyUrl::new("https://example.com/policy-sr-latin".to_string()).unwrap(),
            ),
        ]
    );
    assert_eq!(
        sorted(client_metadata.tos_uri().unwrap().clone())
            .collect::<Vec<(Option<LanguageTag>, ToSUrl)>>(),
        vec![
            (
                None,
                ToSUrl::new("https://example.com/tos".to_string()).unwrap(),
            ),
            (
                Some(LanguageTag::new("sr-Cyrl".to_string())),
                ToSUrl::new("https://example.com/tos-sr-cyrl".to_string()).unwrap(),
            ),
        ]
    );
    assert_eq!(
        *client_metadata.jwks_uri().unwrap(),
        JsonWebKeySetUrl::new("https://example.com/jwks".to_string()).unwrap()
    );
    assert_eq!(
        client_metadata.jwks(),
        Some(&JsonWebKeySet::new(vec![serde_json::from_str(
            TEST_RSA_PUB_KEY
        )
        .unwrap()],))
    );
    assert_eq!(
        *client_metadata.sector_identifier_uri().unwrap(),
        SectorIdentifierUrl::new("https://example.com/sector".to_string()).unwrap()
    );
    assert_eq!(
        *client_metadata.subject_type().unwrap(),
        CoreSubjectIdentifierType::Pairwise
    );
    assert_eq!(
        *client_metadata.id_token_signed_response_alg().unwrap(),
        CoreJwsSigningAlgorithm::HmacSha256
    );
    assert_eq!(
        *client_metadata.id_token_encrypted_response_alg().unwrap(),
        CoreJweKeyManagementAlgorithm::RsaPkcs1V15
    );
    assert_eq!(
        *client_metadata.id_token_encrypted_response_enc().unwrap(),
        CoreJweContentEncryptionAlgorithm::Aes128CbcHmacSha256
    );
    assert_eq!(
        *client_metadata.userinfo_signed_response_alg().unwrap(),
        CoreJwsSigningAlgorithm::RsaSsaPkcs1V15Sha384
    );
    assert_eq!(
        *client_metadata.userinfo_encrypted_response_alg().unwrap(),
        CoreJweKeyManagementAlgorithm::RsaOaep
    );
    assert_eq!(
        *client_metadata.userinfo_encrypted_response_enc().unwrap(),
        CoreJweContentEncryptionAlgorithm::Aes256CbcHmacSha512
    );
    assert_eq!(
        *client_metadata.request_object_signing_alg().unwrap(),
        CoreJwsSigningAlgorithm::EcdsaP521Sha512
    );
    assert_eq!(
        *client_metadata.request_object_encryption_alg().unwrap(),
        CoreJweKeyManagementAlgorithm::EcdhEsAesKeyWrap128
    );
    assert_eq!(
        *client_metadata.request_object_encryption_enc().unwrap(),
        CoreJweContentEncryptionAlgorithm::Aes256Gcm
    );
    assert_eq!(
        *client_metadata.token_endpoint_auth_method().unwrap(),
        CoreClientAuthMethod::ClientSecretBasic
    );
    assert_eq!(
        *client_metadata.token_endpoint_auth_signing_alg().unwrap(),
        CoreJwsSigningAlgorithm::RsaSsaPssSha512
    );
    assert_eq!(
        *client_metadata.default_max_age().unwrap(),
        Duration::from_secs(3600)
    );
    assert!(client_metadata.require_auth_time().unwrap());
    assert_eq!(
        *client_metadata.default_acr_values().unwrap(),
        vec![
            AuthenticationContextClass::new("0".to_string()),
            AuthenticationContextClass::new("urn:mace:incommon:iap:silver".to_string()),
            AuthenticationContextClass::new("urn:mace:incommon:iap:bronze".to_string()),
        ]
    );
    assert_eq!(
        *client_metadata.sector_identifier_uri().unwrap(),
        SectorIdentifierUrl::new("https://example.com/sector".to_string()).unwrap()
    );
    assert_eq!(
        *client_metadata.request_uris().unwrap(),
        vec![
            RequestUrl::new("https://example.com/request-1".to_string()).unwrap(),
            RequestUrl::new("https://example.com/request-2".to_string()).unwrap(),
        ]
    );
    let serialized_json = serde_json::to_string(&client_metadata).unwrap();

    assert_eq!(
        client_metadata,
        serde_json::from_str(&serialized_json).unwrap()
    );
}

#[test]
fn test_metadata_serialization_minimal() {
    let json_response = "{\"redirect_uris\": [\"https://example.com/redirect-1\"]}";

    let client_metadata: CoreClientMetadata = serde_json::from_str(json_response).unwrap();

    assert_eq!(
        *client_metadata.redirect_uris(),
        vec![RedirectUrl::new("https://example.com/redirect-1".to_string()).unwrap(),]
    );
    assert_eq!(client_metadata.response_types(), None);
    assert_eq!(client_metadata.grant_types(), None);
    assert_eq!(client_metadata.application_type(), None);
    assert_eq!(client_metadata.contacts(), None);
    assert_eq!(client_metadata.client_name(), None);
    assert_eq!(client_metadata.logo_uri(), None);
    assert_eq!(client_metadata.client_uri(), None);
    assert_eq!(client_metadata.policy_uri(), None);
    assert_eq!(client_metadata.tos_uri(), None);
    assert_eq!(client_metadata.jwks_uri(), None);
    assert_eq!(client_metadata.jwks(), None);
    assert_eq!(client_metadata.sector_identifier_uri(), None);
    assert_eq!(client_metadata.subject_type(), None);
    assert_eq!(client_metadata.id_token_signed_response_alg(), None);
    assert_eq!(client_metadata.id_token_encrypted_response_alg(), None);
    assert_eq!(client_metadata.id_token_encrypted_response_enc(), None);
    assert_eq!(client_metadata.userinfo_signed_response_alg(), None);
    assert_eq!(client_metadata.userinfo_encrypted_response_alg(), None);
    assert_eq!(client_metadata.userinfo_encrypted_response_enc(), None);
    assert_eq!(client_metadata.request_object_signing_alg(), None);
    assert_eq!(client_metadata.request_object_encryption_alg(), None);
    assert_eq!(client_metadata.request_object_encryption_enc(), None);
    assert_eq!(client_metadata.token_endpoint_auth_method(), None);
    assert_eq!(client_metadata.token_endpoint_auth_signing_alg(), None);
    assert_eq!(client_metadata.default_max_age(), None);
    assert_eq!(client_metadata.require_auth_time(), None);
    assert_eq!(client_metadata.default_acr_values(), None);
    assert_eq!(client_metadata.sector_identifier_uri(), None);
    assert_eq!(client_metadata.request_uris(), None);

    let serialized_json = serde_json::to_string(&client_metadata).unwrap();

    assert_eq!(
        client_metadata,
        serde_json::from_str(&serialized_json).unwrap()
    );
}

#[test]
fn test_response_serialization() {
    let json_response = format!("{{
            \"client_id\": \"abcdefgh\",
            \"client_secret\": \"shhhh\",
            \"registration_access_token\": \"use_me_to_update_registration\",
            \"registration_client_uri\": \"https://example-provider.com/registration\",
            \"client_id_issued_at\": 1523953306,
            \"client_secret_expires_at\": 1526545306,
            \"redirect_uris\": [\"https://example.com/redirect-1\", \"https://example.com/redirect-2\"],
            \"response_types\": [\"code\", \"code token id_token\"],
            \"grant_types\": [\"authorization_code\", \"client_credentials\", \"implicit\", \
                \"password\", \"refresh_token\"],
            \"application_type\": \"web\",
            \"contacts\": [\"user@example.com\", \"admin@openidconnect.local\"],
            \"client_name\": \"Example\",
            \"client_name#es\": \"Ejemplo\",
            \"logo_uri\": \"https://example.com/logo.png\",
            \"logo_uri#fr\": \"https://example.com/logo-fr.png\",
            \"client_uri\": \"https://example.com/client-app\",
            \"client_uri#de\": \"https://example.com/client-app-de\",
            \"policy_uri\": \"https://example.com/policy\",
            \"policy_uri#sr-Latn\": \"https://example.com/policy-sr-latin\",
            \"tos_uri\": \"https://example.com/tos\",
            \"tos_uri#sr-Cyrl\": \"https://example.com/tos-sr-cyrl\",
            \"jwks_uri\": \"https://example.com/jwks\",
            \"jwks\": {{\"keys\": [{}]}},
            \"sector_identifier_uri\": \"https://example.com/sector\",
            \"subject_type\": \"pairwise\",
            \"id_token_signed_response_alg\": \"HS256\",
            \"id_token_encrypted_response_alg\": \"RSA1_5\",
            \"id_token_encrypted_response_enc\": \"A128CBC-HS256\",
            \"userinfo_signed_response_alg\": \"RS384\",
            \"userinfo_encrypted_response_alg\": \"RSA-OAEP\",
            \"userinfo_encrypted_response_enc\": \"A256CBC-HS512\",
            \"request_object_signing_alg\": \"ES512\",
            \"request_object_encryption_alg\": \"ECDH-ES+A128KW\",
            \"request_object_encryption_enc\": \"A256GCM\",
            \"token_endpoint_auth_method\": \"client_secret_basic\",
            \"token_endpoint_auth_signing_alg\": \"PS512\",
            \"default_max_age\": 3600,
            \"require_auth_time\": true,
            \"default_acr_values\": [\"0\", \"urn:mace:incommon:iap:silver\", \
                \"urn:mace:incommon:iap:bronze\"],
            \"initiate_login_uri\": \"https://example.com/login\",
            \"request_uris\": [\"https://example.com/request-1\", \"https://example.com/request-2\"]
        }}", TEST_RSA_PUB_KEY);

    let registration_response: CoreClientRegistrationResponse =
        serde_json::from_str(&json_response).unwrap();

    assert_eq!(
        *registration_response.client_id(),
        ClientId::new("abcdefgh".to_string())
    );
    assert_eq!(
        *registration_response.client_secret().unwrap().secret(),
        "shhhh"
    );
    assert_eq!(
        *registration_response
            .registration_access_token()
            .unwrap()
            .secret(),
        "use_me_to_update_registration",
    );
    assert_eq!(
        *registration_response.registration_client_uri().unwrap(),
        ClientConfigUrl::new("https://example-provider.com/registration".to_string()).unwrap()
    );
    assert_eq!(
        registration_response.client_id_issued_at().unwrap(),
        Utc.timestamp_opt(1523953306, 0)
            .single()
            .expect("valid timestamp")
    );
    assert_eq!(
        registration_response.client_secret_expires_at().unwrap(),
        Utc.timestamp_opt(1526545306, 0)
            .single()
            .expect("valid timestamp")
    );
    assert_eq!(
        *registration_response.redirect_uris(),
        vec![
            RedirectUrl::new("https://example.com/redirect-1".to_string()).unwrap(),
            RedirectUrl::new("https://example.com/redirect-2".to_string()).unwrap(),
        ]
    );
    assert_eq!(
        *registration_response.response_types().unwrap(),
        vec![
            ResponseTypes::new(vec![CoreResponseType::Code]),
            ResponseTypes::new(vec![
                CoreResponseType::Code,
                CoreResponseType::Token,
                CoreResponseType::IdToken,
            ]),
        ]
    );
    assert_eq!(
        registration_response.grant_types().unwrap(),
        &vec![
            CoreGrantType::AuthorizationCode,
            CoreGrantType::ClientCredentials,
            CoreGrantType::Implicit,
            CoreGrantType::Password,
            CoreGrantType::RefreshToken,
        ]
    );
    assert_eq!(
        *registration_response.application_type().unwrap(),
        CoreApplicationType::Web
    );
    assert_eq!(
        *registration_response.contacts().unwrap(),
        vec![
            ClientContactEmail::new("user@example.com".to_string()),
            ClientContactEmail::new("admin@openidconnect.local".to_string()),
        ]
    );
    assert_eq!(
        sorted(registration_response.client_name().unwrap().clone())
            .collect::<Vec<(Option<LanguageTag>, ClientName)>>(),
        vec![
            (None, ClientName::new("Example".to_string())),
            (
                Some(LanguageTag::new("es".to_string())),
                ClientName::new("Ejemplo".to_string()),
            ),
        ]
    );
    assert_eq!(
        sorted(registration_response.logo_uri().unwrap().clone())
            .collect::<Vec<(Option<LanguageTag>, LogoUrl)>>(),
        vec![
            (
                None,
                LogoUrl::new("https://example.com/logo.png".to_string()).unwrap(),
            ),
            (
                Some(LanguageTag::new("fr".to_string())),
                LogoUrl::new("https://example.com/logo-fr.png".to_string()).unwrap(),
            ),
        ]
    );
    assert_eq!(
        sorted(registration_response.client_uri().unwrap().clone())
            .collect::<Vec<(Option<LanguageTag>, ClientUrl)>>(),
        vec![
            (
                None,
                ClientUrl::new("https://example.com/client-app".to_string()).unwrap(),
            ),
            (
                Some(LanguageTag::new("de".to_string())),
                ClientUrl::new("https://example.com/client-app-de".to_string()).unwrap(),
            ),
        ]
    );
    assert_eq!(
        sorted(registration_response.policy_uri().unwrap().clone())
            .collect::<Vec<(Option<LanguageTag>, PolicyUrl)>>(),
        vec![
            (
                None,
                PolicyUrl::new("https://example.com/policy".to_string()).unwrap(),
            ),
            (
                Some(LanguageTag::new("sr-Latn".to_string())),
                PolicyUrl::new("https://example.com/policy-sr-latin".to_string()).unwrap(),
            ),
        ]
    );
    assert_eq!(
        sorted(registration_response.tos_uri().unwrap().clone())
            .collect::<Vec<(Option<LanguageTag>, ToSUrl)>>(),
        vec![
            (
                None,
                ToSUrl::new("https://example.com/tos".to_string()).unwrap(),
            ),
            (
                Some(LanguageTag::new("sr-Cyrl".to_string())),
                ToSUrl::new("https://example.com/tos-sr-cyrl".to_string()).unwrap(),
            ),
        ]
    );
    assert_eq!(
        *registration_response.jwks_uri().unwrap(),
        JsonWebKeySetUrl::new("https://example.com/jwks".to_string()).unwrap()
    );
    assert_eq!(
        registration_response.jwks(),
        Some(&JsonWebKeySet::new(vec![serde_json::from_str(
            TEST_RSA_PUB_KEY
        )
        .unwrap()],)),
    );
    assert_eq!(
        *registration_response.sector_identifier_uri().unwrap(),
        SectorIdentifierUrl::new("https://example.com/sector".to_string()).unwrap()
    );
    assert_eq!(
        *registration_response.subject_type().unwrap(),
        CoreSubjectIdentifierType::Pairwise
    );
    assert_eq!(
        *registration_response
            .id_token_signed_response_alg()
            .unwrap(),
        CoreJwsSigningAlgorithm::HmacSha256
    );
    assert_eq!(
        *registration_response
            .id_token_encrypted_response_alg()
            .unwrap(),
        CoreJweKeyManagementAlgorithm::RsaPkcs1V15
    );
    assert_eq!(
        *registration_response
            .id_token_encrypted_response_enc()
            .unwrap(),
        CoreJweContentEncryptionAlgorithm::Aes128CbcHmacSha256
    );
    assert_eq!(
        *registration_response
            .userinfo_signed_response_alg()
            .unwrap(),
        CoreJwsSigningAlgorithm::RsaSsaPkcs1V15Sha384
    );
    assert_eq!(
        *registration_response
            .userinfo_encrypted_response_alg()
            .unwrap(),
        CoreJweKeyManagementAlgorithm::RsaOaep
    );
    assert_eq!(
        *registration_response
            .userinfo_encrypted_response_enc()
            .unwrap(),
        CoreJweContentEncryptionAlgorithm::Aes256CbcHmacSha512
    );
    assert_eq!(
        *registration_response.request_object_signing_alg().unwrap(),
        CoreJwsSigningAlgorithm::EcdsaP521Sha512
    );
    assert_eq!(
        *registration_response
            .request_object_encryption_alg()
            .unwrap(),
        CoreJweKeyManagementAlgorithm::EcdhEsAesKeyWrap128
    );
    assert_eq!(
        *registration_response
            .request_object_encryption_enc()
            .unwrap(),
        CoreJweContentEncryptionAlgorithm::Aes256Gcm
    );
    assert_eq!(
        *registration_response.token_endpoint_auth_method().unwrap(),
        CoreClientAuthMethod::ClientSecretBasic
    );
    assert_eq!(
        *registration_response
            .token_endpoint_auth_signing_alg()
            .unwrap(),
        CoreJwsSigningAlgorithm::RsaSsaPssSha512
    );
    assert_eq!(
        *registration_response.default_max_age().unwrap(),
        Duration::from_secs(3600)
    );
    assert!(registration_response.require_auth_time().unwrap());
    assert_eq!(
        *registration_response.default_acr_values().unwrap(),
        vec![
            AuthenticationContextClass::new("0".to_string()),
            AuthenticationContextClass::new("urn:mace:incommon:iap:silver".to_string()),
            AuthenticationContextClass::new("urn:mace:incommon:iap:bronze".to_string()),
        ]
    );
    assert_eq!(
        *registration_response.sector_identifier_uri().unwrap(),
        SectorIdentifierUrl::new("https://example.com/sector".to_string()).unwrap()
    );
    assert_eq!(
        *registration_response.request_uris().unwrap(),
        vec![
            RequestUrl::new("https://example.com/request-1".to_string()).unwrap(),
            RequestUrl::new("https://example.com/request-2".to_string()).unwrap(),
        ]
    );
    let serialized_json = serde_json::to_string(&registration_response).unwrap();

    let deserialized: CoreClientRegistrationResponse =
        serde_json::from_str(&serialized_json).unwrap();
    assert_eq!(registration_response.client_id, deserialized.client_id);
    assert_eq!(
        registration_response.client_secret.unwrap().secret(),
        deserialized.client_secret.unwrap().secret(),
    );
    assert_eq!(
        registration_response
            .registration_access_token
            .unwrap()
            .secret(),
        deserialized.registration_access_token.unwrap().secret(),
    );
    assert_eq!(
        registration_response.registration_client_uri,
        deserialized.registration_client_uri,
    );
    assert_eq!(
        registration_response.client_id_issued_at,
        deserialized.client_id_issued_at,
    );
    assert_eq!(
        registration_response.client_secret_expires_at,
        deserialized.client_secret_expires_at,
    );
    assert_eq!(
        registration_response.client_metadata,
        deserialized.client_metadata,
    );
    assert_eq!(
        registration_response.additional_response,
        deserialized.additional_response,
    );
}