[[_oid4vci]]
== Configuring {project_name} as a Verifiable Credential Issuer

[IMPORTANT]
====
This is an experimental feature and should not be used in production. Backward compatibility is not guaranteed, and future updates may introduce breaking changes.
====

{project_name} provides experimental support for https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html[OpenID for Verifiable Credential Issuance].

=== Introduction

This chapter provides step-by-step instructions for configuring {project_name} as a Verifiable Credential Issuer using the OpenID for Verifiable Credential Issuance (OID4VCI) protocol. It outlines the process for setting up a {project_name} instance to securely issue and manage Verifiable Credentials (VCs), supporting decentralized identity solutions.

=== What are Verifiable Credentials (VCs)?

Verifiable Credentials (VCs) are cryptographically signed, tamper-evident data structures that represent claims about an entity, such as a person, organization, or device. They are foundational to decentralized identity systems, allowing secure and privacy-preserving identity verification without reliance on centralized authorities. VCs support advanced features like selective disclosure and zero-knowledge proofs, enhancing user privacy and security.

=== What is OID4VCI?

OpenID for Verifiable Credential Issuance (OID4VCI) is an extension of the OpenID Connect (OIDC) protocol. It defines a standardized, interoperable framework for credential issuers to deliver VCs to holders, who can then present them to verifiers. OID4VCI leverages {project_name}'s existing authentication and authorization capabilities to streamline VC issuance.

=== Scope of This Chapter

This chapter covers the following technical configurations:

- Creating a dedicated realm for VC issuance.
- Setting up a test user for credential testing.
- Configuring custom cryptographic keys for signing and encrypting VCs.
- Defining realm attributes to specify VC metadata.
- Establishing client scopes and mappers to include user attributes in VCs.
- Registering a client to handle VC requests.
- Configuring a credential builder for VC formatting.
- Verifying the configuration using the issuer metadata endpoint.

=== Prerequisites

Ensure the following requirements are met before configuring {project_name} as a Verifiable Credential Issuer:

=== {project_name} Instance

A running {project_name} server with the OID4VCI feature enabled.

To enable the feature, add the following flag to the startup command:

[source,bash]
----
--features=oid4vc-vci
----

Verify activation by checking the server logs for the `OID4VC_VCI` initialization message.

=== Authentication

An access token is required to authenticate API requests.

Refer to the following {project_name} documentation sections for detailed steps on:

- <<proc-creating-oidc-client_{context},Creating a Client>>
- <<_oidc-auth-flows-direct, Obtaining an Access Token>>

=== Configuration Steps

Follow these steps to configure {project_name} as a Verifiable Credential Issuer. Each section is detailed with procedures, explanations, and examples where applicable.

=== Creating a Realm

A realm in {project_name} is a logical container that manages users, clients, roles, and authentication flows.
For Verifiable Credential (VC) issuance, create a dedicated realm to ensure isolation and maintain a clear separation of functionality.

[NOTE]
====
For detailed instructions on creating a realm, refer to the {project_name} documentation:
<<proc-creating-a-realm_{context},Creating a Realm>>.
====

=== Creating a User Account

A test user is required to simulate credential issuance and verify the setup.

[NOTE]
====
For step-by-step instructions on creating a user, refer to the {project_name} documentation:
<<assembly-managing-users_{context},Creating a User>>.
====

Ensure that the user has a valid username, email, and password. If the password should not be reset upon first login, disable the "Temporary" toggle during password configuration.

=== Key Management Configuration

{project_name} uses cryptographic keys for signing and encrypting Verifiable Credentials (VCs). To ensure secure and standards-compliant issuance, configure **ECDSA (ES256) for signing**, **RSA (RS256) for signing**, and **RSA-OAEP for encryption** using a keystore.

[NOTE]
====
For a detailed guide on configuring realm keys, refer to the {project_name} documentation:
<<realm_keys,Managing Realm Keys>>.
====

==== Configuring Key Providers

To enable cryptographic operations for VC issuance:

- **ECDSA (ES256) Key**: Used for signing VCs with the ES256 algorithm.
- **RSA (RS256) Key**: Alternative signing mechanism using RS256.
- **RSA-OAEP Key**: Used for encrypting sensitive data in VCs.

Each key must be registered as a **java-keystore provider** within the **Realm Settings** > **Keys** section, ensuring:
- The keystore file is correctly specified and securely stored.
- The appropriate algorithm (ES256, RS256, or RSA-OAEP) is selected.
- The key is active, enabled, and configured with the correct usage (signing or encryption).
- Priority values are set to define precedence among keys.

[WARNING]
====
Ensure the keystore file is **securely stored** and accessible to the {project_name} server. Use **strong passwords** to protect both the keystore and the private keys.
====

=== Registering Realm Attributes

Realm attributes define metadata for Verifiable Credentials (VCs), such as **expiration times, supported formats, and scope definitions**. These attributes allow {project_name} to issue VCs with predefined settings.

Since the **{project_name} Admin Console does not support direct attribute creation**, use the **{project_name} Admin REST API** to configure these attributes.

==== Define Realm Attributes

Create a JSON file (e.g., `realm-attributes.json`) with the following content:

[source,json]
----
{
  "realm": "oid4vc-vci",
  "enabled": true,
  "preAuthorizedCodeLifespanS": 120,
  "issuerDid": "https://localhost:8443/realms/oid4vc-vci",
  "attributes": {
    "vc.IdentityCredential.expiry_in_s": "31536000",
    "vc.IdentityCredential.format": "vc+sd-jwt",
    "vc.IdentityCredential.scope": "identity_credential",
    "vc.IdentityCredential.vct": "https://credentials.example.com/identity_credential",
    "vc.SteuerberaterCredential.expiry_in_s": "31536000",
    "vc.SteuerberaterCredential.format": "vc+sd-jwt",
    "vc.SteuerberaterCredential.scope": "stbk_westfalen_lippe",
    "vc.SteuerberaterCredential.vct": "stbk_westfalen_lippe",
    "vc.SteuerberaterCredential.cryptographic_binding_methods_supported": "jwk"
  }
}
----

[NOTE]
====
This is a **sample configuration**. You can define **additional attributes** depending on your specific requirements, such as:
- Different VC types and scopes.
- Alternative credential formats.
- Custom cryptographic settings.
====

==== Attribute Breakdown

- **preAuthorizedCodeLifespanS** – Defines how long pre-authorized codes remain valid (in seconds).
- **issuerDid** – The Decentralized Identifier (DID) of the issuer.
- **attributes** – Contains VC-specific metadata, which can be **expanded** as needed:
- **expiry_in_s** – Credential expiration time (in seconds).
- **format** – Defines the VC format (e.g., `vc+sd-jwt`).
- **scope** – Identifies the credential’s scope.
- **vct** – The **Verifiable Credential Type (VCT)**.
- **cryptographic_binding_methods_supported** – Specifies supported cryptographic methods (if applicable).

==== Import Realm Attributes

Use the following `curl` command to import the attributes into {project_name}:

[source,bash]
----
curl -X POST "https://localhost:8443/admin/realms/oid4vc-vci" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d @realm-attributes.json
----

[NOTE]
====
- Replace `$ACCESS_TOKEN` with a valid **{project_name} Admin API access token**.
- **Avoid using `-k` in production**; instead, configure a **trusted TLS certificate**.
- If updating an existing realm, use `PUT` instead of `POST`.
====

=== Create Client Scopes with Mappers

Client scopes define **which user attributes** are included in Verifiable Credentials (VCs). These scopes use **protocol mappers** to map specific claims into VCs.

Since the **{project_name} Admin Console does not support direct client scope creation with mappers**, use the **{project_name} Admin REST API**.

==== Define a Client Scope with a Mapper

Create a JSON file (e.g., `client-scopes.json`) with the following content:

[source,json]
----
{
  "name": "vc-scope-mapping",
  "protocol": "openid-connect",
  "attributes": {
    "include.in.token.scope": "false",
    "display.on.consent.screen": "false"
  },
  "protocolMappers": [
    {
      "name": "academic_title-mapper-bsk",
      "protocol": "oid4vc",
      "protocolMapper": "oid4vc-static-claim-mapper",
      "config": {
        "subjectProperty": "academic_title",
        "staticValue": "N/A",
        "supportedCredentialTypes": "stbk_westfalen_lippe"
      }
    }
  ]
}
----

[NOTE]
====
This is a **sample configuration**.
You can define **additional protocol mappers** to support different claim mappings, such as:
- Dynamic attribute values instead of static ones.
- Mapping multiple attributes per credential type.
- Alternative supported credential types.
====

==== Attribute Breakdown

- **name** – Name of the client scope.
- **protocol** – Uses `openid-connect` for standard OAuth2 workflows.
- **attributes** – Defines scope visibility and consent behavior:
- `include.in.token.scope`: Whether this scope should be included in access tokens.
- `display.on.consent.screen`: Whether to display this scope in user consent screens.
- **protocolMappers** – Defines **how claims are mapped**:
- **name** – Mapper identifier.
- **protocol** – Uses `oid4vc` for Verifiable Credentials.
- **protocolMapper** – Specifies the claim mapping strategy (e.g., `oid4vc-static-claim-mapper`).
- **config**:
- `subjectProperty` – The user attribute to map.
- `staticValue` – Static value assigned when the attribute is missing.
- `supportedCredentialTypes` – Credential types that support this claim.

==== Import the Client Scope

Use the following `curl` command to import the client scope into {project_name}:

[source,bash]
----
curl -X POST "https://localhost:8443/admin/realms/oid4vc-vci/client-scopes" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d @client-scopes.json
----

[NOTE]
====
- Replace `$ACCESS_TOKEN` with a valid **{project_name} Admin API access token**.
- **Avoid using `-k` in production**; instead, configure a **trusted TLS certificate**.
- If updating an existing scope, use `PUT` instead of `POST`.
====

=== Create the OID4VC Client

Set up a client to handle VC requests and assign it the necessary scopes.

. Create a JSON file (e.g., `oid4vc-rest-api-client.json`) with the following content:
+
[source,json]
----
{
  "clientId": "oid4vc-rest-api",
  "enabled": true,
  "protocol": "openid-connect",
  "publicClient": false,
  "serviceAccountsEnabled": true,
  "clientAuthenticatorType": "client-secret",
  "redirectUris": ["http://localhost:8080/*"],
  "directAccessGrantsEnabled": true,
  "defaultClientScopes": ["profile"],
  "optionalClientScopes": ["vc-scope-mapping"],
  "attributes": {
    "client.secret.creation.time": "1719785014",
    "client.introspection.response.allow.jwt.claim.enabled": "false",
    "login_theme": "keycloak",
    "post.logout.redirect.uris": "http://localhost:8080"
  }
}
----
+
- **clientId**: Unique identifier for the client.
- **optionalClientScopes**: Links the `vc-scope-mapping` scope for VC requests.

. Import the client using the following `curl` command:
+
[source,bash]
----
curl -k -X POST "https://localhost:8443/admin/realms/oid4vc-vci/clients" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d @oid4vc-rest-api-client.json
----

=== Create a Credential Builder Component

A **Credential Builder** is responsible for formatting Verifiable Credentials (VCs), such as **SD-JWT**.
This component must be **registered in {project_name}** using the **Admin REST API**.

==== Register the Credential Builder

Use the following `curl` command to **create the credential builder**:

[source,bash]
----
curl -X POST "https://localhost:8443/admin/realms/oid4vc-vci/components" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "sd-jwt-credentialbuilder",
    "providerId": "vc+sd-jwt",
    "providerType": "org.keycloak.protocol.oid4vc.issuance.credentialbuilder.CredentialBuilder"
  }'
----

[NOTE]
====
- Replace `$ACCESS_TOKEN` with a valid **{project_name} Admin API access token**.
- **Avoid using `-k` in production**; instead, configure a **trusted TLS certificate**.
====

==== Configuration Details

- **name** – The identifier for the credential builder.
- **providerId** – Specifies the **VC format** (e.g., `vc+sd-jwt`).
- **providerType** – Points to the {project_name} **Credential Builder class** used for VC issuance.

[IMPORTANT]
====
This is a **sample configuration**.
You can **register multiple credential builders** for different VC formats **(e.g., JWT, JSON-LD, etc.)**.
====

=== Verify the Configuration

Validate the setup by accessing the **issuer metadata endpoint**:

. Open a browser or use a tool like `curl` to visit:
+
[source,bash]
----
https://localhost:8443/realms/oid4vc-vci/.well-known/openid-credential-issuer
----

A successful response returns a JSON object containing details such as:
- **Supported claims**
- **Credential formats**
- **Issuer metadata**

=== Conclusion

You have successfully configured **{project_name} as a Verifiable Credential Issuer** using the **OID4VCI protocol**.
This setup leverages {project_name}'s robust **identity management capabilities** to issue secure, **standards-compliant VCs**.

For a **complete reference implementation**, see the sample project:
https://github.com/adorsys/{project_name}-ssi-deployment/tree/main[{project_name} SSI Deployment^].
