Experimental

Verifiable Credential Issuance

Caution

The Curity Identity Server support for verifiable credential issuance is experimental and should not be used in production scenarios. The described capabilities, configuration model, and associated behavior may change between releases of the Curity Identity Server in a way that is not backward compatible.

The Curity Identity Server supports verifiable credential issuance (VCI), as defined by OpenID for Verifiable Credential Issuance (draft 13 - Implementer’s Draft 1), henceforth identified as OpenID4VCI. For the moment being, this support is being added to the Curity Identity Server for experimentation and evaluation purposes only. By default the verifiable credential issuance functionality is disabled. Run the Curity Identity Server with the se.curity.verifiable-credentials.enable system property set to true to enable it.

The verifiable credential issuance behavior is mostly configured in the verifiable-credentials setting, added to the Token Service profile configuration. It is comprised by two main child settings:

  • A list of verifiable-credentials/verifiable-credential configuration items, where each item defines how a particular kind of verifiable credential (e.g. academic degree credential, driver’s license) should be issued.
  • A set of shared settings that can be used by one or more verifiable credential types.

Each verifiable-credentials/verifiable-credential contains both generic settings, applicable to all credential data models, as well as settings that are specific to the data model used by that credential type.

The following sections provide more information about this configuration model.

Formats and data models

The OpenID for Verifiable Credential Issuance (draft 13 - Implementer’s Draft 1) specification aims to support multiple verifiable credential formats and associated data models. In the current version, the Curity Identity Server supports two formats:

Future versions may add support for other signature packaging methods or different verifiable credential data models.

W3C data model

In the W3C data model, “the type property is used to uniquely identify the type of the verifiable credential in which it appears, i.e., to indicate which set of claims the verifiable credential contains”. The Curity Identity Server follows this guidance by having a configuration model where:

  • First, multiple W3C data model types can be configured using the verifiable-credentials/w3c/type setting. Each type includes references to claims or to scopes (as set of claims). This directly or indirectly defines the claims to include on verifiable credentials of that type.
  • Second, each verifiable-credentials/verifiable-credential entry, defining a particular kind of verifiable credential using the W3C data model, references one or more of the types previously defined.

SD-JWT VC data model

In the SD-JWT VC data model, “A type is associated with rules defining which claims may or must appear in the Unsecured Payload of the SD-JWT VC and whether they may, must, or must not be selectively disclosable”.

The Curity Identity Server follows this guidance by having a configuration model where:

Each claim referenced by an SD-JWT VC data model type has two extra configuration settings, defining:

  • Whether the claim presence in the credential is mandatory or optional.
  • Whether the claim can be selectively disclosable or not. A claim that is not selectively disclosable will always be included in the verifiable credential presentations.

Two different SD-JWT VC data model types may define different mandatory or selective disclosure settings for the same claim.

If a claim is configured as being selectively disclosable and the claim value is an object, then it is also possible to configure which inner properties are selectively disclosable. As an example, consider an address claim, whose value is an object composed by the street_address and country properties.

  • If the address is not configured as selectively disclosable, then a credential presentation will always include an object with both properties.
  • If the address is configured as selectively disclosable, then a credential presentation can choose if the claim should be included or not. If included, both properties will be there.
  • However, it is also possible to configure both the address claim and the inner street_address property as selectively disclosable. This allows for three different options when presenting a verifiable credential issued with this configuration:
    • Do not disclose the address claim.
    • Disclose the address claim, but keep the inner street_address claim concealed, i.e., only include the country property.
    • Disclose the address claim and all its inner properties.

Endpoints

The verifiable credential issuance functionality adds the oauth-verifiable-credential endpoint type. Endpoints of this type are responsible for receiving credential requests and producing credential responses, containing the issued verifiable credentials, as defined by the OpenID4VC draft specification.

A Token Service profile can have zero or more verifiable credential endpoints, which are created, configured, and deployed like any other endpoint of the profile.

If enabled, the verifiable credential issuance functionality will expose the Credential Issuance Metadata in a subpath of the anonymous endpoint, namely in the well known path /.well-known/openid-credential-issuer (see verifiable-credentials/expose-metadata). The full path depends on the configuration details such as base URL, service role and anonymous endpoint. See verifiable-credentials/expose-metadata for more information. Each entry in the credential_configurations_supported object of the Credential Issuer Metadata corresponds to a verifiable-credentials/verifiable-credential entry.

Token procedures

Each oauth-verifiable-credential endpoint can be configured to use a token procedure, allowing the programmatic customization of credential responses, analogously to what is possible for other Token Service endpoints. These procedures can be implemented by scripts or by SDK token procedure plugins.

Credential Request Handling

The Curity Identity Server supports the generic credential request parameters format and proof, as defined by the OpenID4VCI generic credential request:

  • format (mandatory) - must have the jwt_vc_json value or the vc+sd-jwt value, which are currently the only formats supported by the Curity Identity Server.
  • proof (mandatory) - must contain a proof of possession for the key material associated to the subject. The specified type must be jwt.

Both the proof JWT content and the remaining credential request parameters depend on the credential format

jwt_vc_json format - W3C data model

When using the jwt_vc_json format, the proof parameter must include a JWT with the following characteristics:

  • A mandatory kid header property, holding a DID URL pointing to the subject’s verification key. When issuance is successful, the issued verifiable credential will use the DID from this DID URL as the credential’s subject identifier.
  • An optional jwk header property, containing the subject’s verification key. This property is only needed when the used DID method does not provide enough information to fully retrieve the key.

The jwt_vc_json format also defines the credential_definition mandatory credential endpoint request parameter, which is an object with two properties:

  • type (mandatory) - must contain the types of the issued credential, according to what is defined by the W3C data model. The request types must exactly match what is configured by a verifiable-credential configuration entry using a W3C data model, otherwise the issuance will be denied. The supported combination of types is present in the exposed metadata.
  • credentialSubject (optional) - can contain the optional subject claims that also should be included in the issued verifiable credential. By default only the mandatory claims for the requested set of types are included in the issued verifiable credential. By using this parameter, the client/wallet can ask for the inclusion of additional optional claims. The claims for each set of types, as well if they are mandatory or optional, are described in the exposed metadata.

Subject and issuer DID methods

The supported DID methods for subject identification are configured by the verifiable-credentials/verifiable-credential/w3c-vc/allowed-subject-did-methods setting. It is expected that the Curity Identity Server in the future will support more DID methods for subject identification.

Any DID method is supported for issuer identification, as long as the key used by the token issuer has a external-id containing a DID URL.

vc+sd-jwt format - SD-JWT VC data model

When using the vc+sd-jwt format, the proof parameter must include a JWT with the following characteristics:

  • A mandatory jwk header property, containing the subject’s verification key, to which the issued credential will be bound.

The vc+sd-jwt format also defines the following specific credential endpoint request parameters:

  • vct (mandatory) - must contain the type of the issued credential, according to what is defined by the SD-JWT-based Verifiable Credentials specification. The requested type must exactly match what is configured by a verifiable-credential configuration entry using the SD-JWT VC data model, otherwise the issuance will be denied. The supported types are present in the exposed metadata.
  • claims (optional) - can contain the optional subject claims that also should be included in the issued verifiable credential. By default only the mandatory claims for the requested type are included in the issued verifiable credential. By using this parameter, the client/wallet can request for the inclusion of additional optional claims. The claims for each type, as well if they are mandatory or optional, are described in the exposed metadata.

Token Issuers

The signature and issuance of verifiable credentials with the jwt_vc_json format (i.e. the W3C data model) is done by custom token issuers with the verifiable-credential purpose and the jwt type.

The signature and issuance of verifiable credentials with the vc+sd-jwt format (i.e. SD-JWT VC data model) is done by custom token issuers with the verifiable-credential purpose and the sd-jwt type.

Each verifiable credential kind (i.e. each verifiable-credentials/verifiable-credential entry) can use a distinct token issuer.

Authorization Requests

A credential request needs to include an access token granting:

  • Access to the verifiable credential issuance.
  • Access to the claims that will be included in the issued verifiable credential.

A way for a client/wallet to obtain such an access token is by using the OAuth 2.0 authorization_code grant. The authorization request, used to obtain that authorization code, needs to specify the above access token requirements by using scopes, as defined by OpenID4VCI. For that, the scope parameter needs to:

  • Include the special openid_credential scope.
  • Include the scopes that grant access to the required claims. Alternatively, the request can also use the OpenID Connect claims request parameter to specify the required claims.

It is also possible to use the authorization_details authorization request parameter, as defined by RFC 9396 - OAuth 2.0 Rich Authorization Requests specification. Each authorization_details item should have the type property set to openid_credential. The remaining properties are documented in OpenID4VCI usage of authorization_details and in the OpenID4VCI credential format profiles.

Configuration Model Summary

This section contains a brief summary of the verifiable issuance configuration model.

  • verifiable-credentials - Root for the verifiable credentials issuance configuration.

    • name - Name for the verifiable credential issuer, used on the issuer metadata.

    • expose-metada - Used to enable and configure the exposure of verifiable credential issuance metadata.

    • w3c - Root for the shared settings that are specific to the W3C VC data model.

      • type - Each type list entry defines a W3C data model type, characterized by a simple name (e.g. UniversityDegreeCredential), a fully qualified name (e.g. https://example.org/examples#UniversityDegreeCredential) and the set of subject claims that should be added to verifiable credentials with this type, defined via references to claims or scopes.
    • vc-sd-jwt - Root for the shared settings that are specific to the SD-JWT VC data model.

      • type - Each type list entry defines a SD-JWT VC data model type, characterized by the type identifier and the set of subject claims that should be added to verifiable credentials with this type, defined via references to claims.
    • verifiable-credential - Each verifiable-credential list entry defines an issuance template for a kind of verifiable credential, i.e., defines how that credential kind should be created.

      • credential-ttl - Defines the validity duration of the verifiable credential.

      • data-model/w3c-vc - Contains configuration settings specific to verifiable credentials that follow the W3C verifiable credential data model.

        • context - Defines the contents of the @context verifiable credential property.

        • schema - Defines the contents of the credentialSchema verifiable credential property.

        • token-issuer - Defines the token issuer used to sign the verifiable credential. The token issuer purpose must be verifiable_credential and its type defines how the verifiable credential is signed. Currently, the only supported type is jwt, meaning that the verifiable credential will be contained inside a JSON Web Token, i.e., have the jwt_vc_json format.

        • issuer - Defines the value of the issuer verifiable credential property, containing the issuer identifier, which can be:

          • The same as the Token Service issuer.
          • An explicitly defined URI.
          • The URI inferred from the token issuer’s Key ID (KID) identifying the cryptographic key used to sign the verifiable credential, applicable when that KID is a DID URL. On the Curity Identity Server, this KID can be defined by using the key’s external-id.
        • allowed-subject-did-methods - Defines the DID methods allowed for the subject identification.

      • data-model/w3c-vc - Contains configuration settings specific to verifiable credentials that follow the SD-JWT VC data model.

        • type - Defines the SD-JWT VC type to use for this verifiable credential.
        • token-issuer - Defines the token issuer used to sign the verifiable credential. The token issuer purpose must be verifiable_credential and its type must be sd-jwt.

Note

The access to the root verifiable-credentials configuration setting is hidden by default in the bin/idsh command line interface tool, since the verifiable credential issuance feature is still experimental. Running the command unhide verifiable-credentials on the bin/idsh shell will make the verifiable-credentials configuration setting usable on that shell.

Configuration Example

This section illustrates the verifiable credential issuance configuration model via a brief example, which:

  • Creates the signing-key used to sign the verifiable credentials and assigns its external-id with a DID URL.
  • Creates a jwt custom token issuer, using the above key, with a purpose-type of verifiable_credential.
  • Creates the set of claims that should be included as subject claims on the issued verifiable credentials. The way these claims are defined is not specific to verifiable credential issuance.
  • Defines the special openid_credential scope required for an access token to grant access to the credential endpoint.
  • Defines a W3C data model type, including the claims that are associated to that type.
  • Defines a verifiable-credential entry, with all the information necessary to issue a verifiable credential. This verifiable-credential entry includes a reference to the W3C type created in the previous step.
Listing 166 Example configuration for verifiable credential issuance.
  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
<config xmlns="http://tail-f.com/ns/config/1.0">
    <facilities xmlns="https://curity.se/ns/conf/base">
        <crypto>
            <signing-keys>
                <!-- Defining the key used to sign the verifiable credential -->
                <signing-key>
                    <id>esbi-1</id>
                    <keystore>...the key contents...</keystore>
                    <curve-name>P-256</curve-name>
                    <type>elliptic-curve</type>
                    <external-id>...the DID URL of the key...</external-id>
                </signing-key>
            </signing-keys>
        </crypto>
    </facilities>
    <profiles xmlns="https://curity.se/ns/conf/base">
        <profile>
            <id>oauth-dev</id>
            <type xmlns:as="https://curity.se/ns/conf/profile/oauth">as:oauth-service</type>
            <token-issuers>
                <!-- Defining the custom token issuer used to create and sign the verifiable credential -->
                <custom-token-issuer>
                    <id>jwt-vc-issuer-1</id>
                    <issuer-type>jwt</issuer-type>
                    <purpose-type>verifiable_credential</purpose-type>
                    <jwt>
                        <algorithm>ES256</algorithm>
                        <!-- the ID of the key previously created -->
                        <signing-key-id>esbi-1</signing-key-id>
                    </jwt>
                </custom-token-issuer>
            </token-issuers>
            <settings>
                <authorization-server xmlns="https://curity.se/ns/conf/profile/oauth">
                    <!-- Defining the subject claims, using the normal way of defining claims in Curity Identity Server -->
                    <claims>
                        <claim>
                            <name>givenName</name>
                            ...
                        </claim>
                        <claim>
                            <name>familyName</name>
                            ...
                        </claim>
                        <claim>
                            <name>middleName</name>
                            ...
                        </claim>
                        <claim>
                            <name>degreeSchool</name>
                            ...
                        </claim>
                        <claim>
                            <name>degreeType</name>
                            ...
                        </claim>
                    </claims>
                    <scopes>
                        <!-- Defining a scope as a group of claims -->
                        <scope>
                            <id>UniversityDegreeCredentialScope</id>
                            <time-to-live>3600</time-to-live>
                            <claims>givenName</claims>
                            <claims>middleName</claims>
                            <claims>familyName</claims>
                            <claims>degreeType</claims>
                            <claims>degreeSchool</claims>
                        </scope>
                        <scope>
                            <!-- This special scope needs to be created because it will be required on the credential endpoint -->
                            <id>openid_credential</id>
                        </scope>
                    </scopes>
                    <verifiable-credentials>
                        <name>Development Verifiable Credentials Issuer</name>
                        <w3c>
                            <!-- Defining a W3C type with the required claims -->
                            <type>
                                <id>https://example.org/examples#UniversityDegreeCredential</id>
                                <simple-name>UniversityDegreeCredential</simple-name>
                                <!-- Claims from the UniversityDegreeCredentialScope scope can included in a credential of this type but are not mandatory -->
                                <scope>UniversityDegreeCredentialScope</scope>
                                <!-- Claims from the address scope can included in a credential of this type but are not mandatory -->
                                <scope>address</scope>
                                <claim>
                                    <name>givenName</name>
                                    <mandatory>true</mandatory>
                                </claim>
                                <claim>
                                    <name>familyName</name>
                                    <mandatory>true</mandatory>
                                </claim>
                                <claim>
                                    <name>degreeType</name>
                                    <mandatory>true</mandatory>
                                </claim>
                                <claim>
                                    <name>degreeSchool</name>
                                    <mandatory>true</mandatory>
                                </claim>
                                <!-- claim middleName is included on UniversityDegreeCredentialScope but is not mandatory -->
                            </type>
                        </w3c>
                        <!-- Defining a particular kind of verifiable credential, by using the type defined above -->
                        <verifiable-credential>
                            <id>university-degree-credential</id>
                            <name>University Degree Credential</name>
                            <description>A verifiable credential with your degree completion information.</description>
                            <logo>...</logo>
                            <!-- Defining data specific to the W3C data model -->
                            <w3c-vc>
                                <context>
                                    <id>W3C example</id>
                                    <uri>https://www.w3.org/2018/credentials/examples/v1</uri>
                                </context>
                                <!-- the reference to the type created above-->
                                <type>https://example.org/examples#UniversityDegreeCredential</type>
                                <schema>
                                    <!-- example taken from https://www.w3.org/TR/vc-data-model/#data-schemas -->
                                    <id>https://example.org/examples/degree.json</id>
                                    <type>JsonSchemaValidator2018</type>
                                </schema>
                                <token-issuer>jwt-vc-issuer-1</token-issuer>
                                <issuer>
                                    <!-- the issuer ID should be inferred from the DID URL present in the signature key external-id -->
                                    <infer-from-kid />
                                </issuer>
                                <allowed-subject-did-methods>
                                    <method>ebsi</method>
                                </allowed-subject-did-methods>
                            </w3c-vc>
                            <credential-ttl>31536000</credential-ttl>
                        </verifiable-credential>
                    </verifiable-credentials>
                    <client-store>
                        <config-backed>
                            <client>
                                <!-- The client that will be requesting credentials -->
                                <id>client-one</id>
                                <scope>openid</scope>
                                <scope>profile</scope>
                                <scope>UniversityDegreeCredentialScope</scope>
                                <!-- Needs to have this special scope -->
                                <scope>openid_credential</scope>
                            </client>
                        </config-backed>
                    </client-store>
                </authorization-server>
            </settings>
        </profile>
    </profiles>
</config>