-
Notifications
You must be signed in to change notification settings - Fork 13
/
index.html
907 lines (818 loc) · 43.1 KB
/
index.html
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
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>Self-Issued OpenID Connect Provider DID Profile v0.1 (DEPRECATED)</title>
<link rel="icon" type="image/png" sizes="16x16" href="images/favicon-16x16.png">
<style>
#subtitle ~ h2,
.copyright,
#sotd p:first-of-type {
display: none;
}
</style>
<script src='https://www.w3.org/Tools/respec/respec-w3c-common' class='remove'></script>
<script class='remove' src="./common.js"></script>
<script class='remove'>
var respecConfig = {
subtitle: "DIF Working Group Draft",
wg: "Authentication Working Group",
logos: [{
src: 'https://raw.githubusercontent.com/decentralized-identity/decentralized-identity.github.io/master/images/logo-large.png',
href: "https://identity.foundation/",
alt: "Decentralized Identity Foundation",
width: 200,
id: 'dif-logo',
}],
editors: [{
name: "Oliver Terbu",
url: "https://www.linkedin.com/in/oliver-terbu/",
company: "uPort | ConsenSys",
companyURL: "https://uport.me/"
}
],
authors: [{
name: "Oliver Terbu",
url: "https://www.linkedin.com/in/oliver-terbu/",
company: "uPort | ConsenSys",
companyURL: "https://uport.me/"
},
{
name: "Ivan Basart",
url: "https://www.linkedin.com/in/ivanbasart/",
company: "Validated ID",
companyURL: "https://www.validatedid.com/"
},
{
name: "Kyle Den Hartog",
url: "https://www.linkedin.com/in/kyledenhartog/",
company: "Mattr",
companyURL: "https://mattr.global/"
},
{
name: "Christian Lundkvist",
url: "https://www.linkedin.com/in/chrislun/",
company: "ConsenSys",
companyURL: "https://consensys.net/"
},
{
name: "David Stark",
url: "https://www.linkedin.com/in/david-stark-a3bb40/",
company: "SecureKey",
companyURL: "https://securekey.com/"
},
{
name: "Dmitri Zagidulin",
url: "https://www.linkedin.com/in/dzagidulin/",
company: "Digital Bazaar",
companyURL: "https://digitalbazaar.com/"
},
{
name: "Danny Strockis",
url: "https://www.linkedin.com/in/dannystrockis/",
company: "Microsoft",
companyURL: "https://www.microsoft.com/en-us/security/technology/own-your-identity"
},
{
name: "Orie Steele",
url: "https://www.linkedin.com/in/or13b/",
company: "Transmute",
companyURL: "https://www.transmute.industries/"
}],
github: "https://github.com/decentralized-identity/did-siop",
edDraftURI: "https://identity.foundation/did-siop/",
shortName: "did-siop",
localBiblio: siop.localBiblio
};
</script>
</head>
<body>
<section id="abstract">
<h2>Abstract</h2>
<p>
This specification defines the "SIOP DID Profile" (<a href="did-siop">SIOP DID</a>) that is a
<a href="#did-authn">DID AuthN</a> flavor to use
OpenID Connect (<a href="#oidc">OIDC</a>) together with the strong decentralization, privacy and security
guarantees of Decentralized Identifiers (<a href="#did">DID</a>) for everyone who wants to have a generic
way to integrate <a href="#identity-wallet">Identity Wallets</a> into their web applications.
</p>
</section>
<section id='sotd'>
<p>
<a href="did-siop">SIOP DID</a> is an unapproved DIF working group draft specification and now being DEPRECATED within the
<a href="https://identity.foundation"> Decentralized Identity Foundation</a> (DIF).
</p>
<div class="issue">
The work on DIF SIOP DID Profile specification has moved to OIDF AB WG to work on a number of new specifications in the course of the DIF/OIDF liaison:
<ul>
<li><a href="https://openid.net/specs/openid-connect-4-verifiable-presentations-1_0.html">OpenID Connect for Verifiable Presentations</a></li>
<li><a href="https://openid.net/specs/openid-connect-self-issued-v2-1_0.html">SIOP V2</a></li>
</ul>
</div>
</section>
<section class="informative">
<h1>Terminology</h1>
<table class="simple">
<thead>
<tr>
<th style="min-width: 8em;">Term</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td id="did">DID</td>
<td>Decentralized Identifier as per [[DID]]</td>
</tr>
<tr>
<td id="did-document">DID Document</td>
<td>DID Document as per [[DID]]</td>
</tr>
<tr>
<td id="did-siop">SIOP DID</td>
<td>Self-Issued OpenID Connect Provider DID profile. Refers to a specific flavor of DID AuthN used in the
OIDC SIOP flow.</td>
</tr>
<tr>
<td id="jwt">JWT</td>
<td>JSON Web Token as per [[RFC7797]]</td>
</tr>
<tr>
<td id="jwe">JWE</td>
<td>JSON Web Encryption as per [[RFC7516]]</td>
</tr>
<tr>
<td id="jws">JWS</td>
<td>JSON Web Signature as per [[RFC7515]]</a></td>
</tr>
<tr>
<td id="jwk">JWK</td>
<td>JSON Web Key as per [[RFC7517]]</a></td>
</tr>
<tr>
<td id="jwks">JWKS</td>
<td>JWK Set as per [[RFC7517]]</td>
</tr>
<tr>
<td id="oidc">OIDC</td>
<td>OpenID Connect as per [[?OIDC.Core]]</td>
</tr>
<tr>
<td id="oidc-client">OIDC client</td>
<td>Used synonymously with Relying Party (see <a href="#rp">RP</a>)</td>
</tr>
<tr>
<td id="op">OP</td>
<td>OpenID Provider as per [[?OIDC.Core]]</td>
</tr>
<tr>
<td id="siop">SIOP</td>
<td>Self-Issued OpenID Provider as per [[?OIDC.Core]]</td>
</tr>
<tr>
<td id="rp">RP</td>
<td>Relying Party, as used in [[?OIDC.Core]]</td>
</tr>
<tr>
<td id="identity-wallet">Identity Wallet</td>
<td>An Identity Wallet refers to a application that is under the control and acts on behalf of the
DID holder. This Also known as an identity agent. The Identity Wallet can have different form factors
such as a mobile app, browser extension/ plugin etc.</td>
</tr>
<tr>
<td id="did-authn">DID AuthN</td>
<td>Refers to a method of proofing control over a DID for the purpose of authentication.</td>
</tr>
</tbody>
</table>
</section>
<section class="informative">
<h1>
Introduction
</h1>
<p>
An everyday use case that the Decentralized Identity community identified is the sign-up or login with web
applications. Nowadays, this is often achieved through social login schemes such as Google Sign-In. While
the Decentralized Identity community has serious concerns about social login, the underlying protocol,
<a href="#oidc">OIDC</a>, does not have these flaws by design. <a href="#did-siop">SIOP DID</a> provides
great potential by leveraging an <a href="#identity-wallet">Identity Wallet</a>,
e.g., as a smartphone app, on the web. This will increase and preserve the user’s privacy by preventing
third-parties from having the ability to track which web applications a user is interacting with.
</p>
<p class="note">
While this specification focuses on the integration of <a href="#identity-wallet">Identity Wallets</a>
in the form of browser extensions/ plugins, or smartphone apps, it does not prevent implementers using
the proposed flow in different scenarios as well, e.g., between two web services with pre-populated
<a href="#did">DIDs</a>.
</p>
<section class="informative">
<h2>
Purpose
</h2>
<p>
The main purpose is to sign up with/ login to an <a href="#rp">RP</a>, i.e., web application. It assumes
the user operates a mobile or desktop browser or a browser-based app that can respond to
<a href="#siop">SIOP</a> requests according to this specification.
</p>
<p class="note">
The <a href="#siop">SIOP</a> flow is conducted peer-to-peer between the <a href="#rp">RP</a> and the
<a href="#siop">SIOP</a>. This could be used to authenticate holders based on their <a href="#did">DID</a>,
to setup/ bootstrap a DID Comm connection with any <a href="#did">DID</a> routing that you may need, or to
provide the <code>login_hint</code> to an OpenID Connect service in the <a href="#did-document">DID Document</a>
supporting the Client-Initiated Backend Channel (CIBA) as per [[?OIDC.CIBA]].
</p>
</section>
<section class="informative">
<h2>
Goals
</h2>
<p>
The main goals of this specification are:
</p>
<ul>
<li>
Staying backward compatible with existing <a href="#oidc-client">OIDC clients</a> and
<a href="#op">OPs</a> that implement the <a href="#siop">SIOP</a> specification which is part of the
<a href="oidc">OIDC</a> core specification as per [[?OIDC.Core]] to reach a broader community.
</li>
<li>
Adding validation rules for <a href="#oidc-client">OIDC clients</a> that have
<a href="#did-authn">DID AuthN</a> support to make full use of <a href="#did">DIDs</a>.
</li>
<li>
Not relying on any intermediary such as a traditional centralized public or private
<a href="#op">OP</a> while still being <a href="#oidc">OIDC</a>-compliant.
</li>
</ul>
</section>
</section>
<section class="normative">
<h1>Protocol Flow</h1>
<p>
This specification assumes, the user is operating a mobile or desktop browser to visit a web application or uses
a browser-based app.
</p>
<p>
First, the user clicks on the sign up or login UX element. The <a href="#rp">RP</a> will then generate the
redirect to <code>openid://<SIOP Request></code> which will be handled by the <a href="#siop">SIOP</a>.
</p>
<p class="note">
On the mobile device, this would open the <a href="#identity-wallet">Identity Wallet</a> app, e.g., uport,
connect.me. On the desktop browser, this would either show a QR code which can be scanned by the
<a href="#identity-wallet">Identity Wallet</a> app or a redirect to <code>openid://<SIOP Request></code>
that for instance could be handled by a browser extension/ plugin implementing the <a href="#siop">SIOP</a>.
</p>
<p>
The <a href="#siop">SIOP</a> will generate the <code><SIOP Response></code> based on the specific
<a href="#did">DID</a> method that is supported. The <code><SIOP Response></code> will be signed and
optionally encrypted and will be provided according to the requested response mode.
</p>
<p>
This specification does not explicitly support any intermediate hubs or cloud agents. It is meant to be a
protocol to exchange the <a href="#did">DID</a>. You could then interact with a hub/ cloud agent using the
service endpoint in the <a href="#did-document">DID Document</a>.
</p>
<p>
Unlike the <a href="#oidc">OIDC</a> Authorization Code Flow as per [[!OIDC.Core]], the <a href="#siop">SIOP</a>
will not return an access token to the <a href="#rp">RP</a>. If this is desired, this could be achieved by
following the aforementioned CIBA flow as per [[?OIDC.CIBA]] in addition. <a href="#siop">SIOP</a> also
differs from Authorization Code Flow by not relying on a centralized and known
<a href="#op">OP</a>. The <a href="#siop">SIOP</a> can be unknown to the <a href="#rp">RP</a> until the
user starts to interact with the <a href="#rp">RP</a> using its <a href="#identity-wallet">Identity Wallet</a>.
<a href="#oidc">OIDC</a> Authorization Code Flow is still a useful approach and should be used whenever the
<a href="op">OP</a> is known, and <a href="#op">OP</a> discovery is possible, e.g., exchanged or pre-populated
<a href="#did-document">DID Document</a> containing an openid element in the service section.
The <a href="#siop">SIOP</a> flow allows to integrate <a href="#identity-wallet">Identity Wallets</a> with
plain <a href="oidc-client">OIDC clients</a> if they implemented the <a href="#siop">SIOP</a> specification.
In contrast, using <a href="#did-authn">DID AuthN</a> as the authentication means in the <a href="oidc">OIDC</a>
Authorization Code Flow would require integration with the <a href="op">OP</a> vendor itself.
</p>
<figure id="protocol-flow">
<img style="margin: auto; display: block; width: 100%;"
src="assets/did_authn_siop_profile_flow.png" alt="Example SIOP flow with a mobile browser as the User-Agent
and an Identity Wallet app as the SIOP.">
<figcaption style="text-align: center;">
Example <a href="#siop">SIOP</a> flow with a mobile browser as the User-Agent and an
<a href="#identity-wallet">Identity Wallet</a> app as the <a href="#siop">SIOP</a>.
</figcaption>
</figure>
<section>
<h2>Generate SIOP Request</h2>
<h3>Redirect Request</h3>
<p>
The request contains <code>scope</code>, <code>response_type</code> and <code>client_id</code> as query
string parameters for backward compatibility with the OAuth2 specification [[!RFC6749]].
<code>response_type</code> MUST be <code>id_token</code> and <code>client_id</code> MUST specify the
redirect URI of the <a href="#rp">RP</a> (as per [[!OIDC.Core]]). All other <a href="#oidc">OIDC</a>
request parameters MUST be provided in an Request Object as per [[!OIDC.Core]] which is encoded as a JWT.
This enables the <a href="#rp">RP</a> to authenticate against the <a href="#siop">SIOP</a> using the
<a href="#rp">RP's</a> <a href="#did">DID</a>. The Request Object can be passed by value in the
<code>request</code> request parameter, or by reference using the <code>request_uri</code> parameter.
</p>
<pre class="example nohighlight">
openid://?response_type=id_token
&client_id=https%3A%2F%2Frp.example.com%2Fcb
&scope=openid%20did_authn
&request=<JWT>
</pre>
<p>
In the example above the <a href="#did-authn">DID AuthN</a> <code><SIOP Request></code> is initiated
by the <a href="#rp">RP</a> using Request Object by value.
</p>
<pre class="example nohighlight">
openid://?response_type=id_token
&client_id=https%3A%2F%2Frp.example.com%2Fcb
&scope=openid%20did_authn
&request_uri=https%3A%2F%2Frp.example.com%2F90ce0b8a-a910-4dd0
</pre>
<p>
In the example above the <a href="#did-authn">DID AuthN</a> <code><SIOP Request></code> is initiated
by the <a href="#rp">RP</a> using Request Object by reference.
</p>
<h3>RP Metadata</h3>
<p>
In contrast to other <a href="#oidc">OIDC</a> flows, e.g., Authorization Code Flow, <a href="#rp">RPs</a>
can provide client metadata in the <code>registration</code> request parameter. Clients MAY include
any registration metadata parameters defined in <a href="https://openid.net/specs/openid-connect-registration-1_0.html#ClientMetadata"
>OpenID Connect Registration 1.0</a>, and servers MAY use these parameters as they see fit.
</p>
<p>
In addition to <code>RS256</code>, an <a href="#siop">SIOP</a> according to this specification MUST support
<code>EdDSA</code> and <code>ES256K</code> [[!draft-ietf-cose-webauthn-algorithms-03]] for
<code>request_object_signing_alg</code> and <code>request_object_signing_alg</code> can be omitted.
<a href="#rp">RPs</a> implementing the <a href="#did-authn">DID AuthN</a> profile MUST not use
<code>none</code> for <code>request_object_signing_alg</code>.
</p>
<p>
The Request Object MUST be directly or indirectly verifiable by a verification method in the
<a href="#rp">RP's</a> <a href="#did-document">DID Document</a> and directly by the <a href="#rp">RP's</a>
JWKS. The JWKS MUST be provided in the <code>jwks_uri</code> or <code>jwks</code> entry of the
<code>registration</code> parameter. The JWKS MUST contain an entry with a <code>kid</code> that matches
the <code>kid</code> in the Request Object. <code>jwks_uri</code> MUST use the HTTP(S) DID Resolution
Binding as per [[DID.Resolution]] for backward compatibility reasons with plain <a href="#siop">SIOP</a>
<a href="#op">OPs</a>. The <code>jwks</code> request parameter SHOULD be used only if the public key cannot
be directly obtained from the <a href="#did-document">DID Document</a>.
</p>
<p>
<a href="#rp">RPs</a> can decide to receive the <code>SIOP Response</code> encrypted. To enable encryption,
the registration parameter MUST use <code>id_token_encrypted_response_alg</code> and
<code>id_token_encrypted_response_enc</code> according to <a href="oidc">OIDC</a> Client Metadata
[[!OIDC.Registration]]. This specification RECOMMENDS the use of `ECDH-ES` with the `X25519` curve for JWE
as explained in section <a href="#encryption">Encryption</a> and described in
[[!draft-amringer-jose-chacha-00]].
</p>
<h3>Request Object</h3>
<p>
The Request Object follows the <a href="#oidc">OIDC</a> specification, e.g., adding <code>nonce</code>,
<code>state</code>, <code>response_type</code>, and <code>client_id</code> parameters.
</p>
<p>
The request contains <code>scope</code>, <code>response_type</code> and <code>client_id</code> as query
string parameters for backward compatibility with the OAuth2 specification [[!RFC6749]].
<code>response_type</code> MUST be <code>id_token</code> and <code>client_id</code> MUST specify the
redirect URI of the <a href="#rp">RP</a> (as per [[!OIDC.Core]]). All other <a href="#oidc">OIDC</a>
request parameters MUST be provided in an Request Object as per [[!OIDC.Core]] which is encoded as a JWT.
This enables the <a href="#rp">RP</a> to authenticate against the <a href="#siop">SIOP</a> using the
<a href="#rp">RP's</a> <a href="#did">DID</a>. The Request Object can be passed by value in the
<code>request</code> request parameter, or by reference using the <code>request_uri</code> parameter.
</p>
<p>
The Request Object follows the <a href="#oidc">OIDC</a> specification, e.g., adding <code>nonce</code>,
<code>state</code>, <code>response_type</code>, and <code>client_id</code> parameters.
</p>
<p>
This specification introduces additional rules for request parameters and claims in the Request Object:
</p>
<ul>
<li>
REQUIRED. <code>iss</code> MUST contain the <a href="#did">DID</a> of the <a href="#rp">RP</a> that can
be resolved to a <a href="#did-document">DID Document</a>. The <a href="#did-document">DID Document</a>
MUST contain a verification method in the authentication section, e.g., public key, that allows the
<a href="#siop">SIOP</a> to verify the Request Object.
</li>
<p class="note">
By default, the <code>iss</code> claim refers to the <code>client_id</code> but <a href="#siop">SIOP</a>
assumes that <code>client_id</code> is the redirect URI of the <a href="#rp">RP</a>. That is the reason
why the <a href="#did">DID</a> is not encoded in the <code>client_id</code>. It is compliant with the
<a href="#oidc">OIDC</a> specification to use different values for <code>iss</code> and
<code>client_id</code>.
</p>
<li>
REQUIRED. <code>kid</code> MUST be a DID URL referring to a verification method in the authentication
section in the <a href="#rp">RP's</a> <a href="#did-document">DID Document</a>, e.g.,
<code>did:example:0xab#key1</code>. The <a href="#siop">SIOP</a> MUST be able to use that verification
method to verify the Request Object directly or indirectly. Additionally, the referred JWKS in the
<code>registration</code> parameter MUST contain an entry with the same <code>kid</code>.
</li>
<li>
REQUIRED. <code>scope</code> MUST include <code>did_authn</code> to indicate the <a href="#did-siop">
SIOP DID </a> profile is used.
</li>
<li>
REQUIRED. <code>registration</code> MUST be included in the Request Object
</li>
<li>
REQUIRED. <code>client_id</code> MUST be repeated in the Request Object
</li>
<li>
OPTIONAL. <code>response_mode</code> specifies how the response is returned to the redirect URI by the
<a href="#siop">SIOP</a>. <a href="#siop">SIOP</a> implementing this specification MAY set the
<code>response_mode</code> to <code>form_post</code>. <code>fragment</code> is the default
Response Mode. <a href="#rp">RPs</a> MUST take into consideration the platform of the
User-Agent when specifying this request parameter.
</li>
<p class="note">
See OAuth 2.0 Form Post Response Mode [[?OAuth2.FormPost]] and OAuth 2.0 Multiple Response Type Encoding
Practices [[?OAuth2.ResponseTypes]] for more information about <code>response_mode</code>.
</p>
<li>
OPTIONAL. <code>response_context</code> specifies whether the response should be returned to the
redirect URI in the context of an existing system browser session, or whether the response can be
returned in a new/empty context (requested with a <code>response_context</code> of <code>wallet</code>).
The default <code>response_context</code> is <code>rp</code>, indicating that the response should be submitted
in the conext of the RP's existing system browser session.
</li>
<p class="note">
A <code>response_context</code> of <code>wallet</code> indicates to the SIOP that the user flow should end in the SIOP,
without any in-band redirection back to the RP. This behavior is useful in cross-device workflows where
it's appropriate for the mobile portion of the flow to terminate in the wallet.
</p>
<li>
OPTIONAL. <code>claims</code> follows the
<a href="https://openid.net/specs/openid-connect-core-1_0.html#ClaimsParameter">OIDC Core schema</a>,
adding a top-level <code>vc</code> property as a sibling to (and following the schema of) <code>id_token</code>
and <code>userinfo</code>. Requesting claims within the <code>vc</code> set indicates that the requesting party
would like to receive (if <code>essential</code> is <code>false</code>), or requires (if <code>true</code>)
a specific set of verifiable credential types within the <code>.vp.verifiableCredential</code> array of the
SIOP Response. Specific [VC types](https://www.w3.org/TR/vc-data-model/#types) are identified using the VC type's full URI.
</li>
<p class="note">
When providing claims in this manner, the SIOP Response acts as a W3C Verifiable Presentation; requested claims
are provided in the Response by populating the array of Verifiable Credentials within the Presentation.
</p>
</ul>
<p>
The following is a non-normative example of the JWT header of a Request Object:
</p>
<pre class="example nohighlight">
{
"alg": "ES256K",
"typ": "JWT",
"kid": "did:example:0xab#veri-key1"
}
</pre>
<p>
The following is a non-normative example of the JWT payload of a Request Object without requesting
<code><SIOP DID Response></code> encryption:
</p>
<pre class="example nohighlight">
{
"iss": "did:example:0xab",
"response_type": "id_token",
"client_id": "https://my.rp.com/cb",
"scope": "openid did_authn",
"state": "af0ifjsldkj",
"nonce": "n-0S6_WzA2Mj",
"response_mode" : "form_post",
"registration" : {
"jwks_uri" : "https://uniresolver.io/1.0/identifiers/did:example:0xab;transform-keys=jwks",
"id_token_signed_response_alg" : "ES256K"
}
}
</pre>
<p>
The following is a non-normative example HTTP 302 redirect response by the <a href="#rp">RP</a>, which
triggers the User-Agent to make an <a href="siop-did">SIOP DID</a> Authentication Request using Request
Object by value to the <a href="#siop">SIOP</a> (with line wraps within values for display purposes
only):
</p>
<pre class="example nohighlight">
HTTP/1.1 302 Found
Location: openid://?
&client_id=https%3A%2F%2Frp.example.com%2Fcb
&scope=openid%20did_authn
&request=<JWT>
</pre>
<p>
The following is a non-normative example HTTP 302 redirect response by the <a href="#rp">RP</a>, which
triggers the User-Agent to make an <a href="siop-did">SIOP DID</a> Authentication Request using Request
Object by reference to the <a href="#siop">SIOP</a> (with line wraps within values for display purposes
only):
</p>
<pre class="example nohighlight">
HTTP/1.1 302 Found
Location: openid://?
response_type=id_token
&client_id=https%3A%2F%2Frp.example.com%2Fcb
&scope=openid%20did_authn
&request_uri=https%3A%2F%2Frp.example.com%2F90ce0b8a-a910-4dd0
</pre>
<h3 id="encryption">Encryption</h3>
<p>
JWE encryption SHOULD use Diffie-Hellman key agreement, i.e., algorithm `ECDH-ES` using the `X25519` curve
which uses direct key agreement with an ephemeral key. This means that a symmetric key is derived using
Diffie-Hellman from the <a href="#rp">RP's</a> public key and a randomly generated ephemeral private key.
The corresponding ephemeral public key is included in the header of the JWE in the `epk` and the derived
symmetric key is used to directly encrypt the JWT content. For symmetrically encrypting the content
`XChaCha20Poly1305` is used which has algorithm code `XC20P`.
</p>
<p>
The following is an example of the protected header of the resulting JWE:
</p>
<pre class="example nohighlight">
{
"alg": "ECDH-ES",
"epk":
{
"kty": "OKP",
"crv":"X25519",
"x":"hSDwCYkwp1R0i33ctD73Wg2_Og0mOBr066SpjqqbTmo"
}
"enc": "XC20P",
"kid": "did:example:0xab#key-1"
}
</pre>
<p>
Note that the `kid` above denotes the DID and key of the <a href="#rp">RP</a>, i.e., this public key is the
key used by the sender together with the ephemeral private key in order to derive the shared secret. For the
encryption the 24 bytes nonce field in the `XChaCha20` algorithm is used as the initialization vector. The
authentication tag is the MAC computed by the `Poly1305` function. It is 16 bytes long.
</p>
<p>
The message to be encrypted is the JWT of the `id_token`, including header and signature. The JWT is encoded
via base64url before encryption.
</p>
<p>
For the final encoding of the JWE the JWE Compact Serialization outlined in
[[!RFC7516]] is used. The structure of the message is as follows:
</p>
<pre class="example nohighlight">
BASE64URL(JWE Protected Header) || '.' || '.' ||
BASE64URL(JWE Initialization Vector) || '.' ||
BASE64URL(JWE Ciphertext) || '.' ||
BASE64URL(JWE Authentication Tag)
</pre>
<p>
Note the two '.' characters above which indicates that the encrypted key is empty since we are
using direct key agreement.
</p>
</section>
<section>
<h2>SIOP Request Validation</h2>
<p>
The <a href="#siop">SIOP</a> MUST validate the <code><SIOP Request></code> by following the
Self-Issued ID Token Validation rules as per [[!OIDC.Core]].
</p>
<p class="note">
The step described above ensures that the Request Object is verified according to the
<a href="#oidc">OIDC</a> specification. This includes basic JWS verification.
</p>
<p>
If scope contains the <code>did_authn</code> scope, the receiving <a href="#siop">SIOP</a>
MUST further validate the <code><SIOP Request></code> as follows in no particular order:
</p>
<ul>
<li>
Resolve the <a href="#did-document">DID Document</a> from the
<a href="#rp">RP's</a> <a href="#did">DID</a> specified in the <code>iss</code> request parameter.
</li>
<li>
If <code>jwks_uri</code> is present, ensure that the <a href="#did">DID</a> in the
<code>jwks_uri</code> matches the <a href="#did">DID</a> in the <code>iss</code> claim.
</li>
<li>
Determine the verification method from the <a href="#rp">RP's</a>
<a href="#did-document">DID Document</a> that matches the <code>kid</code> of the
<code>SIOP Request</code>.
</li>
<li>
Verify the <code>SIOP Request</code> according to the verification method above. This step depends on
the verification method in the authentication section in the <a href="#did-document">DID Document</a>
and is out-of-scope of this specification.
</li>
</ul>
<p class="note">
If the key pair that signed the <code>SIOP Request</code> refers to the same key as indicated by the
verification method, then no additional verification has to be done as the <a href="#siop">SIOP</a>
validation will verify the signature of the JWS.
</p>
</section>
<section>
<h2>Generate SIOP Response</h2>
<p>
The <a href="#siop">SIOP</a> MUST generate and send the <code><SIOP Response></code> to the
<a href="#rp">RP</a> as described in the Self-Issued OpenID Provider Response section in [[!OIDC.Core]].
The <code>id_token</code> represents the <SIOP Response> encoded as a JWS, or nested JWS/JWE.
</p>
<p>
This specification introduces additional rules for claims in the <code>id_token</code>:
</p>
<ul>
<li>
REQUIRED. <code>sub_jwk</code> MUST contain a <code>kid</code> that is a DID URL referring to the
verification method in the <a href="#siop">SIOP's</a> <a href="#did-document">DID Document</a> that can
be used to verify the JWS of the <code>id_token</code> directly or indirectly.
</li>
<li>
REQUIRED. <code>did</code> MUST be the <a href="#siop">SIOP's</a> <a href="#did">DID</a>.
</li>
</ul>
<p class="note">
The <code>sub_jwk</code> claim has to be provided for backward compatibility reasons. The verification
method in the <a href="#did-document">DID Document</a> can be different from a public key and can use a
<code>publicKey</code> property value other than <code>publicKeyJwk</code>.
</p>
<p>
The following is a non-normative example of the JWT header of an <code>id_token</code> using no encryption:
</p>
<pre class="example nohighlight">
{
"alg": "ES256K",
"typ": "JWT",
"kid": "did:example:0xab#key-1"
}
</pre>
The following is a non-normative example of the unencrypted JWT payload of an <code>id_token</code>:
<pre class="example nohighlight">
{
"iss": "https://self-issued.me",
"nonce": "n-0S6_WzA2Mj",
"exp": 1311281970,
"iat": 1311280970,
"sub_jwk" : {
"crv":"secp256k1",
"kid":"did:example:0xcd#verikey-1",
"kty":"EC",
"x":"7KEKZa5xJPh7WVqHJyUpb2MgEe3nA8Rk7eUlXsmBl-M",
"y":"3zIgl_ml4RhapyEm5J7lvU-4f5jiBvZr4KgxUjEhl9o"
},
"sub": "9-aYUQ7mgL2SWQ_LNTeVN2rtw7xFP-3Y2EO9WV22cF0",
"did": "did:example:0xcd"
}
</pre>
</section>
<section>
<h2>SIOP Response Validation</h2>
<p>
The <a href="#rp">RP</a> MUST validate the <code><SIOP Response></code> as described in the
Self-Issued ID Token Validation section in [[!OIDC.Core]]. This includes:
</p>
<ul>
<li>
Optionally decrypting the JWE to obtain the JWS which contains the <code>id_token</code>.
</li>
<li>
Verifying that the <code>id_token</code> was signed by the key specified in the <code>sub_jwk</code>
claim.
</li>
</ul>
<p>
Additionally, the <a href="#rp">RP</a> MUST validate the <code>id_token</code> against the
<a href="#siop">SIOP's</a> <a href="#did-document">DID Document</a> as follows:
</p>
<ul>
<li>
Resolve the <a href="#did-document">DID Document</a> from the
<a href="#siop">SIOP's</a> <a href="#did">DID</a> specified in the <code>did</code> claim.
</li>
<li>
Determine the verification method from the <a href="#siop">SIOP's</a> <a href="#did-document">DID
Document</a> that matches the <code>kid</code> of the <code>sub_jwk</code> claim in the
<code>id_token</code>.
</li>
<li>
Verify the <code>id_token</code> according to the verification method above. This step depends on the
verification method in the authentication section in the <a href="#did-document">DID Document</a> and
is out-of-scope of this specification.
</li>
</ul>
<p class="note">
If the key pair that signed the <code>id_token</code> refers to the same key as indicated by the
verification method, then no additional verification has to be done as the <a href="#siop">SIOP</a>
validation will verify the signature of the JWS.
</p>
</section>
<section>
<h2>SIOP Discovery</h2>
<p>
The <a href="#siop">SIOP</a> specification assumes the following OP discovery metadata:
</p>
<pre class="nohighlight">
"id_token_signing_alg_values_supported": ["RS256"],
"request_object_signing_alg_values_supported": ["none", "RS256"]
</pre>
<p>
The <a href="#did-authn">DID AuthN</a> profile assumes the following OP discovery metadata:
</p>
<pre class="nohighlight">
"id_token_signing_alg_values_supported": ["RS256", "ES256K", "EdDSA"],
"request_object_signing_alg_values_supported":
["none", "RS256", "ES256K", "EdDSA"]
</pre>
<p>
This change will allow <a href="#did-authn">DID AuthN</a> enabled <a href="#rp">RPs</a> to use additional
signature algorithms commonly used amongst members of the SSI community.
</p>
<p class="note">
"Self-Issued OpenID Provider Discovery" IS NOT normative and does not contain any MUST, SHOULD, or MAY
statements. Therefore, using a different signing algorithmn than <code>RS256</code> shouldn't break the
<a href="#siop">SIOP</a> specification. A <a href="#did-authn">DID AuthN</a> enabled <a href="#rp">RP</a>
would provide <code>id_token_signed_response_alg</code> to indicate its preferred signature algorithm
among the three <code>id_token_signing_alg_values_supported</code> options listed above.
</p>
</section>
</section>
<section class="informative">
<h1>UX Considerations</h1>
<p>
<a href="#siop">SIOP</a> uses the custom URL scheme <code>openid://</code>. Mobile browsers would open the app
that registered that scheme. Desktop browser extensions/ plugins have support for similar functionality. It is
out of the scope of the spec under which circumstances a QR code will be rendered. One option will be to provide
the QR code if the user is using the desktop browser, and no browser extension/ plugin is available.
</p>
<p>
On Android, the user can choose which app should open if multiple apps registered the same custom URL scheme. On
iOS, the behavior is undefined. One approach would be to check if the user is on an iOS device and then, won't
render the button if this is a concern. A fallback on iOS could be the use of custom mime types, but unusual UX
has to be considered. Note, this issue is not specific to <a href="#siop">SIOP</a> only but affects all apps
using custom URL schemes. In case a QR Code is used where the user has to open the app first and has to scan the
QR Code, this issue is mitigated.
</p>
</section>
<section class="informative">
<h1>Security Considerations</h1>
<h2>Threat: Interception of the Redirect URI</h2>
<p>
If an attacker can cause the <code><SIOP Response></code> to be sent a URI under his control, he will
directly get access to the fragment carrying the <code>id_token</code>.
</p>
<p>
This attack can be mitigated by hardening the <a href="#rp">RP</a>, e.g., no support for the open redirector
pattern.
</p>
<h2>Threat: Identity Token Leak in Browser History</h2>
<p>
An attacker could obtain the <code><SIOP Response></code> from the browser's history.
</p>
<p>
This attack cannot be fully mitigated. It is RECOMMENDED to use short expiration times for
<code>id_token</code>, and indicating that browsers should not cache the response.
</p>
<h2>Threat: Identity Token Leak to Third Party Scripts</h2>
<p>
It is relatively common to use third-party scripts on <a href="#rp">RP</a> pages, such as analytics tools, crash
reporting. The author of the application may not be able to be fully aware of the entirety of the code running
in the application. When a <code><SIOP Response></code> is returned in the fragment, it is visible to any
third-party scripts on the page.
</p>
<p>
This attack could be mitigated by using trusted/ audited third party scripts on the <a href="#rp">RP's</a> page,
or browser-based app.
</p>
<h2>Countermeasures</h2>
<p>
Use <code>response_mode=form_post</code> whenever possible to mitigate the risks described above. Under some
circumstances, e.g., this will not be possible as such in the case of purely decentralized apps (dApp).
</p>
<h2>Threat: Session Fixation in Cross-Device Flow</h2>
<p>
When the protocol begins on one device and ends on another, there is a risk that the cross-device transfer can
be hijacked. For example, consider a flow that begins with the display of a QR code by the <a href="#rp">RP</a>
transfers to a mobile wallet when the user scans the QR code. In this scenario, an attacker can trick the user
into scanning a QR code associated with a legitimate RP's sign-in request, thereby causing the user to
authenticate within the context of the attacker's session.
<h2>Countermeasures</h2>
<p>
Validate that the browser session in which the DID SIOP Response is submitted belongs to the same user as the
browser session in which the DID SIOP Request was displayed. Even if these sessions are on different devices,
the RP can take steps to ensure these belong to the same user (e.g., by checking whether an existing session
exists or by asking the user to sign in through a non-SIOP means).
</p>
<h2>Additional Security Considerations</h2>
<p>
The OWASP Foundation maintains a set of security recommendations and best practices for web applications, and it
is RECOMMENDED to follow these best practices when creating an <a href="#siop">SIOP</a> or <a href="#rp">RP</a>
based on this specification.
</p>
</section>
<section class="informative">
<h1>IANA Considerations</h1>
<p>
This specification registers the <code>did</code> claim in the IANA JSON Web Token
Claims registry defined in JWT.
</p>
</section>
<section class="informative">
<h1>OIDC Considerations</h1>
<p>
This specification aims to be backward compatible with existing <a href="#oidc-client">OIDC clients</a> and
<a href="#op">OPs</a> that implement the <a href="#siop">SIOP</a> specification. Although the
<a href="#siop">SIOP</a> specification is part of the OIDC core specification, it is not widely adopted yet.
One of the reasons was that not many apps existed that provided functionality we can find in
<a href="#identity-wallet">Identity Wallets</a>. Nevertheless, <a href="#siop">SIOP</a> uses the same or similar
request and response messages and should be easy to allow <a href="#oidc">OIDC</a> vendors to upgrade existing
<a href="#oidc-client">OIDC</a> clients to support <a href="#siop">SIOP</a>.
</p>
</section>
</body>
</html>