-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathREADME.html
2148 lines (2065 loc) · 162 KB
/
README.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
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="" xml:lang="" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8"/>
<meta content="pandoc" name="generator"/>
<meta content="width=device-width, initial-scale=1.0, user-scalable=yes" name="viewport"/>
<title>README</title>
<style>
html {
line-height: 1.5;
font-family: Georgia, serif;
font-size: 20px;
color: #1a1a1a;
background-color: #fdfdfd;
}
body {
margin: 0 auto;
max-width: 36em;
padding-left: 50px;
padding-right: 50px;
padding-top: 50px;
padding-bottom: 50px;
hyphens: auto;
overflow-wrap: break-word;
text-rendering: optimizeLegibility;
font-kerning: normal;
}
@media (max-width: 600px) {
body {
font-size: 0.9em;
padding: 1em;
}
h1 {
font-size: 1.8em;
}
}
@media print {
body {
background-color: transparent;
color: black;
font-size: 12pt;
}
p, h2, h3 {
orphans: 3;
widows: 3;
}
h2, h3, h4 {
page-break-after: avoid;
}
}
p {
margin: 1em 0;
}
a {
color: #1a1a1a;
}
a:visited {
color: #1a1a1a;
}
img {
max-width: 100%;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 1.4em;
}
h5, h6 {
font-size: 1em;
font-style: italic;
}
h6 {
font-weight: normal;
}
ol, ul {
padding-left: 1.7em;
margin-top: 1em;
}
li > ol, li > ul {
margin-top: 0;
}
blockquote {
margin: 1em 0 1em 1.7em;
padding-left: 1em;
border-left: 2px solid #e6e6e6;
color: #606060;
}
code {
font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
font-size: 85%;
margin: 0;
}
pre {
margin: 1em 0;
overflow: auto;
}
pre code {
padding: 0;
overflow: visible;
overflow-wrap: normal;
}
.sourceCode {
background-color: transparent;
overflow: visible;
}
hr {
background-color: #1a1a1a;
border: none;
height: 1px;
margin: 1em 0;
}
table {
margin: 1em 0;
border-collapse: collapse;
width: 100%;
overflow-x: auto;
display: block;
font-variant-numeric: lining-nums tabular-nums;
}
table caption {
margin-bottom: 0.75em;
}
tbody {
margin-top: 0.5em;
border-top: 1px solid #1a1a1a;
border-bottom: 1px solid #1a1a1a;
}
th {
border-top: 1px solid #1a1a1a;
padding: 0.25em 0.5em 0.25em 0.5em;
}
td {
padding: 0.125em 0.5em 0.25em 0.5em;
}
header {
margin-bottom: 4em;
text-align: center;
}
#TOC li {
list-style: none;
}
#TOC ul {
padding-left: 1.3em;
}
#TOC > ul {
padding-left: 0;
}
#TOC a:not(:hover) {
text-decoration: none;
}
code {
white-space: pre-wrap;
}
span.smallcaps {
font-variant: small-caps;
}
span.underline {
text-decoration: underline;
}
div.column {
display: inline-block;
vertical-align: top;
width: 50%;
}
div.hanging-indent {
margin-left: 1.5em;
text-indent: -1.5em;
}
ul.task-list {
list-style: none;
}
pre > code.sourceCode {
white-space: pre;
position: relative;
}
pre > code.sourceCode > span {
display: inline-block;
line-height: 1.25;
}
pre > code.sourceCode > span:empty {
height: 1.2em;
}
.sourceCode {
overflow: visible;
}
code.sourceCode > span {
color: inherit;
text-decoration: inherit;
}
div.sourceCode {
margin: 1em 0;
}
pre.sourceCode {
margin: 0;
}
@media screen {
div.sourceCode {
overflow: auto;
}
}
@media print {
pre > code.sourceCode {
white-space: pre-wrap;
}
pre > code.sourceCode > span {
text-indent: -5em;
padding-left: 5em;
}
}
pre.numberSource code {
counter-reset: source-line 0;
}
pre.numberSource code > span {
position: relative;
left: -4em;
counter-increment: source-line;
}
pre.numberSource code > span > a:first-child::before {
content: counter(source-line);
position: relative;
left: -1em;
text-align: right;
vertical-align: baseline;
border: none;
display: inline-block;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
padding: 0 4px;
width: 4em;
color: #aaaaaa;
}
pre.numberSource {
margin-left: 3em;
border-left: 1px solid #aaaaaa;
padding-left: 4px;
}
div.sourceCode {
}
@media screen {
pre > code.sourceCode > span > a:first-child::before {
text-decoration: underline;
}
}
code span.al {
color: #ff0000;
font-weight: bold;
}
/* Alert */
code span.an {
color: #60a0b0;
font-weight: bold;
font-style: italic;
}
/* Annotation */
code span.at {
color: #7d9029;
}
/* Attribute */
code span.bn {
color: #40a070;
}
/* BaseN */
code span.bu {
}
/* BuiltIn */
code span.cf {
color: #007020;
font-weight: bold;
}
/* ControlFlow */
code span.ch {
color: #4070a0;
}
/* Char */
code span.cn {
color: #880000;
}
/* Constant */
code span.co {
color: #60a0b0;
font-style: italic;
}
/* Comment */
code span.cv {
color: #60a0b0;
font-weight: bold;
font-style: italic;
}
/* CommentVar */
code span.do {
color: #ba2121;
font-style: italic;
}
/* Documentation */
code span.dt {
color: #902000;
}
/* DataType */
code span.dv {
color: #40a070;
}
/* DecVal */
code span.er {
color: #ff0000;
font-weight: bold;
}
/* Error */
code span.ex {
}
/* Extension */
code span.fl {
color: #40a070;
}
/* Float */
code span.fu {
color: #06287e;
}
/* Function */
code span.im {
}
/* Import */
code span.in {
color: #60a0b0;
font-weight: bold;
font-style: italic;
}
/* Information */
code span.kw {
color: #007020;
font-weight: bold;
}
/* Keyword */
code span.op {
color: #666666;
}
/* Operator */
code span.ot {
color: #007020;
}
/* Other */
code span.pp {
color: #bc7a00;
}
/* Preprocessor */
code span.sc {
color: #4070a0;
}
/* SpecialChar */
code span.ss {
color: #bb6688;
}
/* SpecialString */
code span.st {
color: #4070a0;
}
/* String */
code span.va {
color: #19177c;
}
/* Variable */
code span.vs {
color: #4070a0;
}
/* VerbatimString */
code span.wa {
color: #60a0b0;
font-weight: bold;
font-style: italic;
}
/* Warning */
.display.math {
display: block;
text-align: center;
margin: 0.5rem auto;
}
</style>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<!--suppress HtmlDeprecatedAttribute -->
<p><a href="https://sphereon.com"><img alt="Sphereon"
src="./resources/sphereon.png"/></a></p>
<p><strong>eIDAS Advanced Electronic Signature Client</strong></p>
<p>The eIDAS Advanced Electronic Signature (AdES) client, allows to sign
documents and digests (hashes), using CAdES (CMS, binary data), JAdES
(JSON), PAdES (PDF), XAdES (XML) signatures, as defined by the European
Telecommunications Standards Institute (ETSI). These signatures are part
of the eIDAS legal framework in the European Union. Next to PAdES it can
also create and verify PKCS#7 PDF signatures. These are non-ETSI, but
are the more common PDF signatures, provided by companies on Adobe’s
Approved Trust List.</p>
<p>The purpose of this client is to easily create and verify eIDAS and
PKCS#7 compliant signatures for documents and input data, using
certificates which are stored in keystore files (PKCS#12) or using
hardware (PKCS#11). Documents can be signed by providing the full
document or by generating a hash/digest of the document first.
Especially with remote signing REST APIs part of the Sphereon VDX
platform, we suggest to create the digest first and then use the
signature to merge with the original document. This means you are not
sending the full document across the wire, which obviously is better
from a privacy and security perspective.</p>
<h1 id="table-of-contents">Table of Contents</h1>
<ul>
<li><a href="#multiplatform-library-and-rest-api">Multiplatform library
and REST API</a></li>
<li><a href="#signature-flow">Signature flow</a></li>
<li><a href="#certificate-provider-service">Certificate Provider
Service</a>
<ul>
<li><a href="#pkcs12-keystore-certificate-provider-service">PKCS#12
Keystore Certificate Provider Service</a>
<ul>
<li><a
href="#use-existing-tooling-to-create-a-certificate-and-pkcs12-keystore">Use
existing tooling to create a certificate and PKCS#12 keystore</a>
<ul>
<li><a href="#creating-a-pkcs12-keystore-using-openssl">Creating a
PKCS#12 keystore using OpenSSL</a></li>
</ul>
</li>
</ul>
</li>
<li><a
href="#pkcs11-hardware-security-module-and-card-based-certificate-provider-service">PKCS#11
Hardware Security Module and Card based Certificate Provider
Service</a></li>
<li><a
href="#azure-keyvault-or-managed-hsm-certificate-provider-service">Azure
Keyvault or Managed HSM Certificate Provider Service</a></li>
<li><a href="#rest-certificate-provider">REST Certificate Provider</a>
<ul>
<li><a href="#authentication-and-authorization-support">Authentication
and Authorization support</a>
<ul>
<li><a href="#oauth2-support">OAuth2 support</a></li>
<li><a href="#bearer-token-and-jwt-support">Bearer Token and JWT
support</a></li>
<li><a href="#oauth2--openid-scopes">OAuth2, OpenID Scopes</a></li>
<li><a href="#roles-support">Roles support</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#certificate-provider-caching">Certificate Provider
caching</a></li>
<li><a href="#list-keys--certificates">List keys, certificates</a></li>
<li><a href="#get-a-key-certificate-by-kid">Get a key/certificate by
kid</a></li>
<li><a href="#create-the-signature">Create the signature</a></li>
</ul>
</li>
<li><a href="#signature-service">Signature Service</a>
<ul>
<li><a href="#initialize-the-signature-service">Initialize the Signature
Service</a></li>
<li><a href="#determine-sign-input">Determine Sign Input</a></li>
<li><a
href="#create-a-hash-digest-for-additional-privacy-and-security">Create
a hash digest for additional privacy and security</a></li>
<li><a href="#create-the-signature-1">Create the signature</a></li>
<li><a href="#signing-the-original-data--merging-the-signature">Signing
the original data, merging the signature</a></li>
<li><a href="#check-whether-a-signature-is-valid">Check whether a
signature is valid</a></li>
</ul>
</li>
<li><a href="#pdf-signatures">PDF Signatures</a>
<ul>
<li><a href="#default-pkcs7-pdf-signature">Default PKCS#7 PDF
signature</a>
<ul>
<li><a href="#pkcs7-configuration-options">PKCS#7 configuration
options</a></li>
<li><a href="#example-pkcs7-flow">Example PKCS#7 flow</a></li>
</ul>
</li>
<li><a href="#etsi-eidas-pades-detached-pdf-signature">ETSI eIDAS PAdES
detached PDF signature</a>
<ul>
<li><a href="#pades-configuration-options">PAdES configuration
options</a></li>
<li><a href="#example-pades-flow">Example PAdES flow</a></li>
</ul>
</li>
<li><a href="#visual-pkcs7-and-pades-signatures">Visual PKCS#7 and PAdES
signatures</a></li>
</ul>
</li>
<li><a href="#verifiable-credentials-and-ssi">Verifiable Credentials and
SSI</a></li>
<li><a href="#building-and-running-the-source-code">Building and running
the source code</a>
<ul>
<li><a href="#requirements">Requirements</a></li>
<li><a href="#adding-as-maven-dependency">Adding as Maven
dependency</a></li>
<li><a href="#gradle-build--local-maven-repo-">Gradle build (local maven
repo)</a></li>
</ul>
</li>
</ul>
<h1 id="multiplatform-library-and-rest-api">Multiplatform library and
REST API</h1>
<p>This is a multiplatform Kotlin library. Right now it supports Java
and Kotlin only. In the future Javascript/Typescript will be added.
Please note that a REST API is also available that has integrated this
client, allowing to generate and validate signatures using other
languages. Next to Java/Kotlin, Javascript/Typescript a .NET SDK is
available that integrates with the REST API. SDK code can be generated
for other languages based upon the OpenAPI 3 spec provided with the REST
API.</p>
<h1 id="signature-flow">Signature flow</h1>
<p>Creating a signed AdES document comprises several steps. It starts
with the Original Data/Document, for which we first need to determine
the Sign Input. The <code>SignInput</code> typically either is the full
document, or a part of the document (PDF for instance). The
<code>determineSignInput</code> method which requires the input document
together with the signature type and configuration as parameters,
automatically determines the Sign Input. The determineSignInput can be
run locally without the need to use a REST API for instance.</p>
<p>Next there are two options. Directly signing the
<code>SignInput</code> object using the <code>createSignature</code>
method, resulting in a signature, or creating a Digest (Hash) of the
<code>SignInput</code>. Since the createSignature method could be using
a remote REST service or remote Hardware Security Module for instance,
it is advisable to use the Digest method in most cases. The Digest
method can be run locally, so even if the createSignature method needs
to access remote resources, no information from the original
data/document would be sent across the wire. The digest method accepts a
<code>SignInput</code> object as parameter and results in another
<code>SignInput</code> object, with its sign method set to
<code>DIGEST</code> instead of the original method of
<code>DOCUMENT</code>.</p>
<p>The <code>createSignature</code> method accepts the
<code>SignInput</code> object, which the signMode either being
<code>DOCUMENT</code> or <code>DIGEST</code>, depending on which method
was chosen. It is using the supplied ‘KeyEntry’ or Key kid string to
sign the input object. This can either be done locally or remotely
depending on the CertProvider implementation. The end result is a
<code>Signature</code> object.</p>
<p>Lastly the <code>Signature</code> object needs to be merged with the
original Document. It really depends on the type of signature being used
how this is achieved. The document could for instance become part of the
signature (ENVELOPING), the signature could become part of the document
(ENVELOPED), or the signature could be detached (DETACHED)</p>
<p>The picture below gives a schematic overview of the process</p>
<figure>
<img alt="Signature Flow"
src="./resources/ades%20signature%20flow.png"/>
<figcaption aria-hidden="true">Signature Flow</figcaption>
</figure>
<p>It is possible to use multiple so called <em>SignatureServices</em>
with the same <em>CertificateProvider</em>. This allows for instance to
extract bytes and create a digest/hash from the input file locally,
while creating the signature using a REST API or Azure Keyvault for
instance. Then the signature is recombined with the original document
locally. The <em>createSignature</em> method and its counterpart
<em>verifySignature</em> methods are typically ran using a REST API,
Keyvault or locally with PKCS#11 hardware Certificate Providers. It is
up to the caller to determine whether creating the digest/hash, and
placing the signature in the input document also should run remotely or
not.</p>
<p>For non Kotlin/Java environments we advise to setup the eIDAS
Signature REST Microservice on premise, which connects to PKCS#11
hardware, a QTSP or Azure Keyvault remotely. Then use the REST
endpoints, or use an SDK if available for your language. Please note
that these SDKs typically have little local processing functionality
unlike the Kotlin/Java library. The setup ensures that Personally
Identifiable Information (PII) or other sensitive information doesn’t
leave your premise, and that only the signature is being created
remotely from the Digest/Hash value. It also allows you to use
authentication and roles/authorization locally on a per certificate and
configuration level.</p>
<h1 id="certificate-provider-service">Certificate Provider Service</h1>
<p>The Certificate Provider Service allows to manage public/private keys
and Certificates using either a PKCS#12 keystore file as byte array or
filepath. It also has support for PKCS#11 hardware (HSM and USB cards)
as well as support for a Remote REST Certificate Provider and a Azure
Keyvault/Managed HSM Certificate Provider. Next to certificate/key
management a Certificate Provider also is responsible for creating and
verifying signatures themselves. Other operations, like creating a hash,
merging a signature into an input document are handled by a Signature
Service instead of the Certificate Provider. A Single Certificate
Provider can be shared by different Signature Services, as explained <a
href="#signature-flow">above</a></p>
<p>Given the wide range of supported import/creation methods, this
library does not create or import certificates. Please use your method
of choice (see <a
href="#use-existing-tooling-to-create-a-certificate-and-keystore">below</a>
for some pointers).</p>
<h2 id="pkcs12-keystore-certificate-provider-service">PKCS#12 Keystore
Certificate Provider Service</h2>
<p>The below example in Kotlin sets up a certificate service using a
PKCS#12 keystore file at a certain path</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode kotlin"><code class="sourceCode kotlin"><span id="cb1-1"><a aria-hidden="true" href="#cb1-1" tabindex="-1"></a><span class="kw">val</span> <span
class="va">providerPath</span> <span class="op">=</span> <span class="st">"path/to/pkcs12.p12"</span></span>
<span id="cb1-2"><a aria-hidden="true" href="#cb1-2" tabindex="-1"></a><span class="kw">val</span> <span class="va">passwordInputCallback</span> <span
class="op">=</span> PasswordInputCallback<span class="op">(</span>password <span class="op">=</span> <span
class="st">"password"</span><span class="op">.</span>toCharArray<span class="op">())</span></span>
<span id="cb1-3"><a aria-hidden="true" href="#cb1-3" tabindex="-1"></a><span class="kw">val</span> <span class="va">providerConfig</span> <span
class="op">=</span> CertificateProviderConfig<span class="op">(</span></span>
<span id="cb1-4"><a aria-hidden="true" href="#cb1-4" tabindex="-1"></a> type <span class="op">=</span> CertificateProviderType<span
class="op">.</span>PKCS12<span class="op">,</span></span>
<span id="cb1-5"><a aria-hidden="true" href="#cb1-5" tabindex="-1"></a> pkcs12Parameters <span class="op">=</span> KeystoreParameters<span
class="op">(</span>providerPath<span class="op">)</span></span>
<span id="cb1-6"><a aria-hidden="true" href="#cb1-6" tabindex="-1"></a><span class="op">)</span></span>
<span id="cb1-7"><a aria-hidden="true" href="#cb1-7" tabindex="-1"></a><span class="kw">val</span> <span class="va">certProvider</span> <span
class="op">=</span> CertificateProviderService<span class="op">(</span></span>
<span id="cb1-8"><a aria-hidden="true" href="#cb1-8" tabindex="-1"></a> CertificateProviderSettings<span class="op">(</span></span>
<span id="cb1-9"><a aria-hidden="true" href="#cb1-9" tabindex="-1"></a> id <span class="op">=</span> <span class="st">"my-pkcs12-provider"</span><span
class="op">,</span></span>
<span id="cb1-10"><a aria-hidden="true" href="#cb1-10" tabindex="-1"></a> providerConfig<span class="op">,</span></span>
<span id="cb1-11"><a aria-hidden="true" href="#cb1-11" tabindex="-1"></a> passwordInputCallback</span>
<span id="cb1-12"><a aria-hidden="true" href="#cb1-12" tabindex="-1"></a> <span class="op">)</span></span>
<span id="cb1-13"><a aria-hidden="true" href="#cb1-13" tabindex="-1"></a><span class="op">)</span></span></code></pre>
</div>
<h3
id="use-existing-tooling-to-create-a-certificate-and-pkcs12-keystore">Use
existing tooling to create a certificate and PKCS#12 keystore</h3>
<p>How to generate and/or import X.509 certificates and PKCS#12
keystores is out of scope of this project, but we provide some hints
below. There are numerous resources on the internet to create X.509
certificates and PKCS#12 keystores.</p>
<h4 id="creating-a-pkcs12-keystore-using-openssl">Creating a PKCS#12
keystore using OpenSSL</h4>
<p>The private key and certificate must be in Privacy Enhanced Mail
(PEM) format (for example, base64-encoded with
<code>----BEGIN CERTIFICATE---- and ----END CERTIFICATE----</code>
headers and footers).</p>
<p>Use the following OpenSSL commands to create a PKCS#12 file from your
private key and certificate. If you have one certificate, use the CA
root certificate.</p>
<pre><code>openssl pkcs12 -export -in <signed_cert_filename> -inkey <private_key_filename> -name ‘tomcat’ -out keystore.p12</code></pre>
<p>If you have a chain of certificates, combine the certificates into a
single file and use it for the input file, as shown below. The order of
certificates must be from server certificate to the CA root
certificate.</p>
<p>See RFC 2246 section 7.4.2 for more information about this order.</p>
<pre><code>cat <signed_cert_filename> <intermediate.cert> [<intermediate2.cert>] > cert-chain.txt
openssl pkcs12 -export -in cert-chain.txt -inkey <private_key_filename> -name ‘tomcat’ -out keystore.p12</code></pre>
<p>When prompted, provide a password for the new keystore.</p>
<h2
id="pkcs11-hardware-security-module-and-card-based-certificate-provider-service">PKCS#11
Hardware Security Module and Card based Certificate Provider
Service</h2>
<p>The PKCS#11 Certificate Provider allows you to use Hardware Security
Based solutions that can interact using a PKCS#11 interface. It needs
access to the driver library in order to operate.</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode kotlin"><code class="sourceCode kotlin"><span id="cb4-1"><a aria-hidden="true" href="#cb4-1" tabindex="-1"></a><span class="kw">val</span> <span
class="va">passwordInputCallback</span> <span class="op">=</span> PasswordInputCallback<span class="op">(</span>password <span class="op">=</span> <span
class="st">"password"</span><span class="op">.</span>toCharArray<span class="op">())</span></span>
<span id="cb4-2"><a aria-hidden="true" href="#cb4-2" tabindex="-1"></a><span class="kw">val</span> <span class="va">providerConfig</span> <span
class="op">=</span> CertificateProviderConfig<span class="op">(</span></span>
<span id="cb4-3"><a aria-hidden="true" href="#cb4-3" tabindex="-1"></a> type <span class="op">=</span> CertificateProviderType<span
class="op">.</span>PKCS11<span class="op">,</span></span>
<span id="cb4-4"><a aria-hidden="true" href="#cb4-4" tabindex="-1"></a> pkcs11Parameters <span class="op">=</span> Pkcs11Parameters<span
class="op">(</span></span>
<span id="cb4-5"><a aria-hidden="true" href="#cb4-5" tabindex="-1"></a> pkcs11LibraryPath <span class="op">=</span> <span class="st">"/usr/lib/opensc-pkcs11.so"</span><span
class="op">,</span> <span class="co">// The PKCS11 driver path</span></span>
<span id="cb4-6"><a aria-hidden="true" href="#cb4-6" tabindex="-1"></a> slotId <span class="op">=</span> <span class="dv">0</span><span
class="op">,</span></span>
<span id="cb4-7"><a aria-hidden="true" href="#cb4-7" tabindex="-1"></a> slotListIndex <span class="op">=</span> <span
class="dv">2</span></span>
<span id="cb4-8"><a aria-hidden="true" href="#cb4-8" tabindex="-1"></a> <span class="op">)</span></span>
<span id="cb4-9"><a aria-hidden="true" href="#cb4-9" tabindex="-1"></a><span class="op">)</span></span>
<span id="cb4-10"><a aria-hidden="true" href="#cb4-10" tabindex="-1"></a><span class="kw">val</span> <span class="va">certProvider</span> <span
class="op">=</span> CertificateProviderService<span class="op">(</span></span>
<span id="cb4-11"><a aria-hidden="true" href="#cb4-11" tabindex="-1"></a> CertificateProviderSettings<span class="op">(</span></span>
<span id="cb4-12"><a aria-hidden="true" href="#cb4-12" tabindex="-1"></a> id <span class="op">=</span> <span class="st">"my-pkcs11-provider"</span><span
class="op">,</span></span>
<span id="cb4-13"><a aria-hidden="true" href="#cb4-13" tabindex="-1"></a> providerConfig<span class="op">,</span></span>
<span id="cb4-14"><a aria-hidden="true" href="#cb4-14" tabindex="-1"></a> passwordInputCallback</span>
<span id="cb4-15"><a aria-hidden="true" href="#cb4-15" tabindex="-1"></a> <span class="op">)</span></span>
<span id="cb4-16"><a aria-hidden="true" href="#cb4-16" tabindex="-1"></a><span class="op">)</span></span></code></pre>
</div>
<div class="sourceCode" id="cb5"><pre
class="sourceCode kotlin"><code class="sourceCode kotlin"><span id="cb5-1"><a aria-hidden="true" href="#cb5-1" tabindex="-1"></a><span class="kw">class</span> Pkcs11Parameters<span
class="op">(</span></span>
<span id="cb5-2"><a aria-hidden="true" href="#cb5-2" tabindex="-1"></a> /** <span class="va">The</span> <span class="va">path</span> <span
class="va">to</span> <span class="va">the</span> <span class="va">library</span> */</span>
<span id="cb5-3"><a aria-hidden="true" href="#cb5-3" tabindex="-1"></a> <span class="kw">val</span> <span class="va">pkcs11LibraryPath</span><span
class="op">:</span> <span class="dt">String</span><span class="op">?</span> <span class="op">=</span> null<span class="op">,</span></span>
<span id="cb5-4"><a aria-hidden="true" href="#cb5-4" tabindex="-1"></a></span>
<span id="cb5-5"><a aria-hidden="true" href="#cb5-5" tabindex="-1"></a> /** <span class="va">The</span> <span class="va">callback</span> <span
class="va">to</span> <span class="va">enter</span> <span class="va">a</span> <span class="va">password</span>/<span class="va">pincode</span> */</span>
<span id="cb5-6"><a aria-hidden="true" href="#cb5-6" tabindex="-1"></a> <span class="kw">val</span> <span class="va">callback</span><span
class="op">:</span> <span class="dt">PasswordInputCallback</span><span class="op">?</span> <span class="op">=</span> null<span class="op">,</span></span>
<span id="cb5-7"><a aria-hidden="true" href="#cb5-7" tabindex="-1"></a></span>
<span id="cb5-8"><a aria-hidden="true" href="#cb5-8" tabindex="-1"></a> /** <span class="va">The</span> <span class="va">slot</span> <span
class="va">Id</span> <span class="va">to</span> <span class="va">use</span> */</span>
<span id="cb5-9"><a aria-hidden="true" href="#cb5-9" tabindex="-1"></a> <span class="kw">val</span> <span class="va">slotId</span><span class="op">:</span> <span
class="dt">Int</span><span class="op">?</span> <span class="op">=</span> <span class="dv">0</span><span class="op">,</span></span>
<span id="cb5-10"><a aria-hidden="true" href="#cb5-10" tabindex="-1"></a></span>
<span id="cb5-11"><a aria-hidden="true" href="#cb5-11" tabindex="-1"></a> /** <span class="va">The</span> <span class="va">slot</span> <span
class="va">list</span> <span class="va">index</span> <span class="va">to</span> <span class="va">use</span> */</span>
<span id="cb5-12"><a aria-hidden="true" href="#cb5-12" tabindex="-1"></a> <span class="kw">val</span> <span class="va">slotListIndex</span><span
class="op">:</span> <span class="dt">Int</span><span class="op">?</span> <span class="op">=</span> -<span class="dv">1</span><span
class="op">,</span></span>
<span id="cb5-13"><a aria-hidden="true" href="#cb5-13" tabindex="-1"></a></span>
<span id="cb5-14"><a aria-hidden="true" href="#cb5-14" tabindex="-1"></a> /** <span class="va">Additional</span> <span
class="va">PKCS11</span> <span class="va">config</span> */</span>
<span id="cb5-15"><a aria-hidden="true" href="#cb5-15" tabindex="-1"></a> <span class="kw">val</span> <span
class="va">extraPkcs11Config</span><span class="op">:</span> <span class="dt">String</span><span class="op">?</span> <span class="op">=</span> null</span>
<span id="cb5-16"><a aria-hidden="true" href="#cb5-16" tabindex="-1"></a><span class="op">)</span></span></code></pre>
</div>
<h2
id="azure-keyvault-or-managed-hsm-certificate-provider-service">Azure
Keyvault or Managed HSM Certificate Provider Service</h2>
<p>An Azure Keyvault Certificate Provider uses Azure Keyvault and Azure
Managed HSM to retrieve certificates, create the Signature and verify a
signature. The below example in Kotlin sets up a Certificate Service
using Azure Keyvault or Azure Managed HSM. Both Keyvault and Managed HSM
support Hardware Security Modules. The Managed HSM service is
Microsoft’s solution for an HSM not shared with other
customers/tenants.</p>
<p><strong>Note:</strong> <em>Although the Azure Certificate Provider
should work with Azure Managed HSM, the library is not being tested
against Azure Managed HSM, as opposed to Azure Keyvault.</em></p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode kotlin"><code class="sourceCode kotlin"><span id="cb6-1"><a aria-hidden="true" href="#cb6-1" tabindex="-1"></a><span class="kw">val</span> <span
class="va">providerConfig</span> <span class="op">=</span> CertificateProviderConfig<span class="op">(</span></span>
<span id="cb6-2"><a aria-hidden="true" href="#cb6-2" tabindex="-1"></a> type <span class="op">=</span> CertificateProviderType<span
class="op">.</span>AZURE_KEYVAULT</span>
<span id="cb6-3"><a aria-hidden="true" href="#cb6-3" tabindex="-1"></a><span class="op">)</span></span>
<span id="cb6-4"><a aria-hidden="true" href="#cb6-4" tabindex="-1"></a><span class="kw">val</span> <span class="va">keyvaultConfig</span> <span
class="op">=</span> AzureKeyvaultClientConfig<span class="op">(</span></span>
<span id="cb6-5"><a aria-hidden="true" href="#cb6-5" tabindex="-1"></a> keyvaultUrl <span class="op">=</span> <span class="st">"https://your-keyvault-here.vault.azure.net/"</span><span
class="op">,</span></span>
<span id="cb6-6"><a aria-hidden="true" href="#cb6-6" tabindex="-1"></a> tenantId <span class="op">=</span> <span class="st">"<your-directory-id-as-shown-in-keyvault-properties>"</span><span
class="op">,</span></span>
<span id="cb6-7"><a aria-hidden="true" href="#cb6-7" tabindex="-1"></a> credentialOpts <span class="op">=</span> CredentialOpts<span
class="op">(</span></span>
<span id="cb6-8"><a aria-hidden="true" href="#cb6-8" tabindex="-1"></a> credentialMode <span class="op">=</span> CredentialMode<span
class="op">.</span>SERVICE_CLIENT_SECRET<span class="op">,</span> <span class="co">// Use a client id and secret to authenticate as an app</span></span>
<span id="cb6-9"><a aria-hidden="true" href="#cb6-9" tabindex="-1"></a> secretCredentialOpts <span
class="op">=</span> SecretCredentialOpts<span class="op">(</span></span>
<span id="cb6-10"><a aria-hidden="true" href="#cb6-10" tabindex="-1"></a> clientId <span class="op">=</span> <span class="st">"<client id which has access to keyvault>"</span><span
class="op">,</span></span>
<span id="cb6-11"><a aria-hidden="true" href="#cb6-11" tabindex="-1"></a> clientSecret <span class="op">=</span> <span class="st">"<client secret belonging to client id>"</span></span>
<span id="cb6-12"><a aria-hidden="true" href="#cb6-12" tabindex="-1"></a> <span class="op">)</span></span>
<span id="cb6-13"><a aria-hidden="true" href="#cb6-13" tabindex="-1"></a> <span class="op">),</span></span>
<span id="cb6-14"><a aria-hidden="true" href="#cb6-14" tabindex="-1"></a> hsmType <span class="op">=</span> HSMType<span class="op">.</span>KEYVAULT<span
class="op">,</span> <span class="co">// Either KEYVAULT as HSM (FIPS140 Level-2), or MANAGED_HSM</span></span>
<span id="cb6-15"><a aria-hidden="true" href="#cb6-15" tabindex="-1"></a> applicationId <span class="op">=</span> <span class="st">"your-application-id-or-name"</span><span
class="op">,</span> <span class="co">// This can be randomly choosen</span></span>
<span id="cb6-16"><a aria-hidden="true" href="#cb6-16" tabindex="-1"></a> exponentialBackoffRetryOpts <span class="op">=</span> ExponentialBackoffRetryOpts<span
class="op">(</span></span>
<span id="cb6-17"><a aria-hidden="true" href="#cb6-17" tabindex="-1"></a> maxTries <span class="op">=</span> <span class="dv">10</span><span
class="op">,</span> <span class="co">// let's try max 10 times</span></span>
<span id="cb6-18"><a aria-hidden="true" href="#cb6-18" tabindex="-1"></a> baseDelayInMS <span class="op">=</span> <span
class="dv">500</span><span class="op">,</span> <span class="co">// Wait 0,5 seconds the first time</span></span>
<span id="cb6-19"><a aria-hidden="true" href="#cb6-19" tabindex="-1"></a> maxDelayInMS <span class="op">=</span> <span class="dv">15000</span> <span
class="co">// Wait for max 15 seconds eventually</span></span>
<span id="cb6-20"><a aria-hidden="true" href="#cb6-20" tabindex="-1"></a> <span class="op">)</span></span>
<span id="cb6-21"><a aria-hidden="true" href="#cb6-21" tabindex="-1"></a><span class="op">)</span></span>
<span id="cb6-22"><a aria-hidden="true" href="#cb6-22" tabindex="-1"></a></span>
<span id="cb6-23"><a aria-hidden="true" href="#cb6-23" tabindex="-1"></a><span class="kw">val</span> <span class="va">providerSettings</span> <span
class="op">=</span> CertificateProviderSettings<span class="op">(</span></span>
<span id="cb6-24"><a aria-hidden="true" href="#cb6-24" tabindex="-1"></a> id <span class="op">=</span> <span class="st">"my-keyvault-provider"</span><span
class="op">,</span></span>
<span id="cb6-25"><a aria-hidden="true" href="#cb6-25" tabindex="-1"></a> providerConfig</span>
<span id="cb6-26"><a aria-hidden="true" href="#cb6-26" tabindex="-1"></a><span class="op">)</span></span>
<span id="cb6-27"><a aria-hidden="true" href="#cb6-27" tabindex="-1"></a></span>
<span id="cb6-28"><a aria-hidden="true" href="#cb6-28" tabindex="-1"></a><span class="co">// From a factory</span></span>
<span id="cb6-29"><a aria-hidden="true" href="#cb6-29" tabindex="-1"></a><span class="kw">var</span> <span class="va">certProvider</span> <span
class="op">=</span> CertificateProviderServiceFactory<span class="op">.</span>createFromConfig<span class="op">(</span>settings <span
class="op">=</span> providerSettings<span class="op">,</span> azureKeyvaultClientConfig <span class="op">=</span> keyvaultConfig<span
class="op">)</span></span>
<span id="cb6-30"><a aria-hidden="true" href="#cb6-30" tabindex="-1"></a></span>
<span id="cb6-31"><a aria-hidden="true" href="#cb6-31" tabindex="-1"></a></span>
<span id="cb6-32"><a aria-hidden="true" href="#cb6-32" tabindex="-1"></a><span class="co">// Or directly:</span></span>
<span id="cb6-33"><a aria-hidden="true" href="#cb6-33" tabindex="-1"></a>certProvider <span class="op">=</span> AzureKeyvaultCertificateProviderService<span
class="op">(</span>providerSettings<span class="op">,</span> keyvaultConfig<span class="op">)</span></span></code></pre>
</div>
<h2 id="rest-certificate-provider">REST Certificate Provider</h2>
<p>The REST Certificate Provider uses REST to get Keys/Certificates It
also exposes the createSignature and verifySignature methods as REST
endpoints. Lastly other methods like creating a digest,
determineSignInput and placing the signature in the original document
could also be executed remotely if desired. This is however handled by
the RESTSignatureService.</p>
<h3 id="authentication-and-authorization-support">Authentication and
Authorization support</h3>
<p>The REST Certificate Provider has OAuth2, OpenID Connect and bearer
token support integrated.</p>
<h4 id="oauth2-support">OAuth2 support</h4>
<p>The REST Certificate Provider client has support for oAuth2 and by
extension OpenID Connect. Access to the OAuth2 functionality can be
achieved by invoking the <code>oauth()</code> method on the REST
Certificate Provider after providing the appropriate configuration:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode kotlin"><code class="sourceCode kotlin"><span id="cb7-1"><a aria-hidden="true" href="#cb7-1" tabindex="-1"></a><span class="kw">val</span> <span
class="va">certProviderSettings</span> <span class="op">=</span> CertificateProviderSettings<span class="op">(</span></span>
<span id="cb7-2"><a aria-hidden="true" href="#cb7-2" tabindex="-1"></a> id <span class="op">=</span> <span
class="st">"rest-oauth2"</span><span class="op">,</span></span>
<span id="cb7-3"><a aria-hidden="true" href="#cb7-3" tabindex="-1"></a> config <span class="op">=</span> CertificateProviderConfig<span class="op">(</span></span>
<span id="cb7-4"><a aria-hidden="true" href="#cb7-4" tabindex="-1"></a> cacheEnabled <span class="op">=</span> <span
class="kw">true</span><span class="op">,</span></span>
<span id="cb7-5"><a aria-hidden="true" href="#cb7-5" tabindex="-1"></a> type <span class="op">=</span> CertificateProviderType<span class="op">.</span>REST<span
class="op">,</span></span>
<span id="cb7-6"><a aria-hidden="true" href="#cb7-6" tabindex="-1"></a> <span class="op">)</span></span>
<span id="cb7-7"><a aria-hidden="true" href="#cb7-7" tabindex="-1"></a><span class="op">)</span></span>
<span id="cb7-8"><a aria-hidden="true" href="#cb7-8" tabindex="-1"></a><span class="kw">val</span> <span class="va">restConfig</span> <span
class="op">=</span> RestClientConfig<span class="op">(</span></span>
<span id="cb7-9"><a aria-hidden="true" href="#cb7-9" tabindex="-1"></a> baseUrl <span class="op">=</span> <span class="st">"https://example.rest.service/signature/1.0"</span><span
class="op">,</span></span>
<span id="cb7-10"><a aria-hidden="true" href="#cb7-10" tabindex="-1"></a> oauth2 <span class="op">=</span> OAuth2Config<span
class="op">(</span></span>
<span id="cb7-11"><a aria-hidden="true" href="#cb7-11" tabindex="-1"></a> tokenUrl <span class="op">=</span> <span class="st">"https://example.auth-server.com/auth/realms/sign-test/protocol/openid-connect/token"</span><span
class="op">,</span></span>
<span id="cb7-12"><a aria-hidden="true" href="#cb7-12" tabindex="-1"></a> flow <span class="op">=</span> OAuthFlow<span class="op">.</span>APPLICATION<span
class="op">,</span> <span class="co">// Use a clientId/clientSecret</span></span>
<span id="cb7-13"><a aria-hidden="true" href="#cb7-13" tabindex="-1"></a> scope <span class="op">=</span> <span class="st">"sign:vdx_sign_cert"</span><span
class="op">,</span> <span class="co">// Request scope, see scope chapter below</span></span>
<span id="cb7-14"><a aria-hidden="true" href="#cb7-14" tabindex="-1"></a> clientId <span class="op">=</span> <span class="st">"<client-id>"</span><span
class="op">,</span> <span class="co">// Provided by the IDP administrator</span></span>
<span id="cb7-15"><a aria-hidden="true" href="#cb7-15" tabindex="-1"></a> clientSecret <span class="op">=</span> <span class="st">"<client-secret>"</span><span
class="op">,</span> <span class="co">// Provided by the IDP administrator</span></span>
<span id="cb7-16"><a aria-hidden="true" href="#cb7-16" tabindex="-1"></a> accessToken <span class="op">=</span> <span class="st">"ey...."</span> <span
class="co">// Typicaly should not be included. Can be used instead of clientId/secret when a static token is being used for instance</span></span>
<span id="cb7-17"><a aria-hidden="true" href="#cb7-17" tabindex="-1"></a> <span class="op">)</span></span>
<span id="cb7-18"><a aria-hidden="true" href="#cb7-18" tabindex="-1"></a><span class="op">)</span></span>
<span id="cb7-19"><a aria-hidden="true" href="#cb7-19" tabindex="-1"></a></span>
<span id="cb7-20"><a aria-hidden="true" href="#cb7-20" tabindex="-1"></a><span class="kw">val</span> <span
class="va">restCertificateProvider</span> <span class="op">=</span> RestCertificateProviderService<span
class="op">(</span>certProviderSettings<span class="op">,</span> restConfig<span class="op">)</span></span>
<span id="cb7-21"><a aria-hidden="true" href="#cb7-21" tabindex="-1"></a><span class="co">// Use the respective methods to get certificate or sign at this point. It will use oAuth2 to request a token and refresh tokens</span></span>
<span id="cb7-22"><a aria-hidden="true" href="#cb7-22" tabindex="-1"></a></span>
<span id="cb7-23"><a aria-hidden="true" href="#cb7-23" tabindex="-1"></a><span class="co">// If oauth2 access is needed the oauth() method can be used. For instance to renew the access token</span></span>
<span id="cb7-24"><a aria-hidden="true" href="#cb7-24" tabindex="-1"></a>restCertificateProvider<span class="op">.</span>oauth<span
class="op">().</span>renewAccessToken<span class="op">()</span></span>
<span id="cb7-25"><a aria-hidden="true" href="#cb7-25" tabindex="-1"></a></span>
<span id="cb7-26"><a aria-hidden="true" href="#cb7-26" tabindex="-1"></a><span class="co">// From this point on requests will use the new token</span></span></code></pre>
</div>
<h4 id="bearer-token-and-jwt-support">Bearer Token and JWT support</h4>
<p>The REST Certificate Provider client has support to include bearer
tokens (JWTs) in the authentication header. Access to the JWT
functionality can be achieved by invoking the bearerAuth() method on the
REST Certificate Provider after providing the appropriate
configuration:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode kotlin"><code class="sourceCode kotlin"><span id="cb8-1"><a aria-hidden="true" href="#cb8-1" tabindex="-1"></a><span class="kw">val</span> <span
class="va">certProviderSettings</span> <span class="op">=</span> CertificateProviderSettings<span class="op">(</span></span>
<span id="cb8-2"><a aria-hidden="true" href="#cb8-2" tabindex="-1"></a> id <span class="op">=</span> <span
class="st">"rest-bearer"</span><span class="op">,</span></span>
<span id="cb8-3"><a aria-hidden="true" href="#cb8-3" tabindex="-1"></a> config <span class="op">=</span> CertificateProviderConfig<span class="op">(</span></span>
<span id="cb8-4"><a aria-hidden="true" href="#cb8-4" tabindex="-1"></a> cacheEnabled <span class="op">=</span> <span
class="kw">true</span><span class="op">,</span></span>
<span id="cb8-5"><a aria-hidden="true" href="#cb8-5" tabindex="-1"></a> type <span class="op">=</span> CertificateProviderType<span class="op">.</span>REST<span
class="op">,</span></span>
<span id="cb8-6"><a aria-hidden="true" href="#cb8-6" tabindex="-1"></a> <span class="op">)</span></span>
<span id="cb8-7"><a aria-hidden="true" href="#cb8-7" tabindex="-1"></a><span class="op">)</span></span>
<span id="cb8-8"><a aria-hidden="true" href="#cb8-8" tabindex="-1"></a><span class="kw">val</span> <span class="va">restConfig</span> <span
class="op">=</span> RestClientConfig<span class="op">(</span></span>
<span id="cb8-9"><a aria-hidden="true" href="#cb8-9" tabindex="-1"></a> baseUrl <span class="op">=</span> <span class="st">"https://example.rest.service/signature/1.0"</span><span
class="op">,</span></span>
<span id="cb8-10"><a aria-hidden="true" href="#cb8-10" tabindex="-1"></a> bearerAuth <span class="op">=</span> BearerTokenConfig<span
class="op">(</span></span>
<span id="cb8-11"><a aria-hidden="true" href="#cb8-11" tabindex="-1"></a> schema <span class="op">=</span> <span
class="st">"bearer"</span><span class="op">,</span> <span class="co">// Can be omitted as it is the default</span></span>
<span id="cb8-12"><a aria-hidden="true" href="#cb8-12" tabindex="-1"></a> bearerToken <span class="op">=</span> <span class="st">"ey.....ffd"</span> <span
class="co">// Usefull to set an initial token or when the token is static</span></span>
<span id="cb8-13"><a aria-hidden="true" href="#cb8-13" tabindex="-1"></a> <span class="op">)</span></span>
<span id="cb8-14"><a aria-hidden="true" href="#cb8-14" tabindex="-1"></a><span class="op">)</span></span>
<span id="cb8-15"><a aria-hidden="true" href="#cb8-15" tabindex="-1"></a></span>
<span id="cb8-16"><a aria-hidden="true" href="#cb8-16" tabindex="-1"></a><span class="kw">val</span> <span
class="va">restCertificateProvider</span> <span class="op">=</span> RestCertificateProviderService<span
class="op">(</span>certProviderSettings<span class="op">,</span> restConfig<span class="op">)</span></span>
<span id="cb8-17"><a aria-hidden="true" href="#cb8-17" tabindex="-1"></a><span class="co">// Use the respective methods to get certificate or sign at this point. It will use the bearer token in every request</span></span>
<span id="cb8-18"><a aria-hidden="true" href="#cb8-18" tabindex="-1"></a></span>
<span id="cb8-19"><a aria-hidden="true" href="#cb8-19" tabindex="-1"></a><span class="co">// If the bearer token needs to be updated</span></span>
<span id="cb8-20"><a aria-hidden="true" href="#cb8-20" tabindex="-1"></a>restCertificateProvider<span class="op">.</span>bearerAuth<span class="op">().</span>bearerToken <span
class="op">=</span> <span class="st">"ey.....<updated.bearer.token>..."</span></span>
<span id="cb8-21"><a aria-hidden="true" href="#cb8-21" tabindex="-1"></a></span>
<span id="cb8-22"><a aria-hidden="true" href="#cb8-22" tabindex="-1"></a><span class="co">// From this point on requests will use the new token</span></span></code></pre>
</div>
<h4 id="oauth2-openid-scopes">OAuth2, OpenID Scopes</h4>
<p>The REST Microservice can be configured to support scopes. It is
supported for both OAuth2 and OpenID Connect. Scopes are optional and
when enabled, protect the API endpoints from users not having access to
a certain scope at an endpoint level.</p>
<p>The available scopes are:</p>
<ul>
<li><strong>read:vdx_sign_cert</strong>: Read/List certificates</li>
<li><strong>admin:vdx_sign_cert</strong>: Administer certificated</li>
<li><strong>sign:vdx_sign_cert</strong>: Sign using certificates</li>
<li><strong>read:vdx_sign_config</strong>: Read configurations</li>
<li><strong>admin:vdx_sign_config</strong>: Create and update
configurations
</li>
</ul>
<p>Please note that this doesn’t provide protection at an individual
configuration nor certificate level. For these there is role support.
The eIDAS REST MS documentation provides more info on this subject.</p>
<p>To enable scopes, you have to use your IAM solution of choice which
supports oAuth2 or OpenID Connect and ensure that the appropriate scopes
are requested from the IAM solution. How this works is different per IAM
and outside the scope of this README.</p>
<p>The REST Certificate Provider can set the scopes before requesting
the tokens using the configuration as shown <a
href="#oauth2-support">above</a>. You can also programaticaly set the
scopes:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode kotlin"><code class="sourceCode kotlin"><span id="cb9-1"><a aria-hidden="true" href="#cb9-1" tabindex="-1"></a>restCertificateProvider<span
class="op">.</span>oauth<span class="op">()..</span>setScope<span class="op">(</span><span class="st">"sign:vdx_sign_cert"</span><span
class="op">)</span></span></code></pre>
</div>
<h4 id="roles-support">Roles support</h4>
<p>The REST Microservice has role based support. It is possible to
define roles on individual configurations as well as individual
certificates. Meaning you can define which roles and thus users/groups