LogoLogo
ProductsCommunityGitHubShare Feedback
SSI Kit
SSI Kit
  • General
    • Introduction
    • Transition To The Community Stack
    • SSI Kit | Basics
      • Overview
      • Functionality
      • Components
    • SSI Kit
      • SSI Flavors & Ecosystems
        • Trust Registries
        • Keys
        • Decentralized Identifiers (DIDs)
        • Verifiable Credentials (VCs)
        • Data Exchange Protocols
      • Architecture
        • Low-Level Service Abstraction
        • Ecosystem Abstraction
        • High-Level Interfaces / APIs
      • Use Cases
      • Self-Sovereign Identity (SSI)
        • SSI | Basics
        • Technologies & Concepts
          • Registries
          • Decentralised Identifiers (DIDs)
          • Verifiable Credentials (VCs)
          • Verifiable Presentations (VPs)
          • Data Exchange (Protocols)
  • Getting started
    • Quick Start
    • REST API
      • Signatory API - For Issuers
      • Custodian API - For Holders
        • Key management
        • Did management
        • Credentials management
      • Auditor API - For Verifiers
      • Core API
        • Cryptographic keys
        • Decentralised-Identifiers
        • Verifiable-Credentials
      • API Serving Configs
    • Dependency (JVM)
      • Java Examples
      • Kotlin Examples
    • CLI | Command Line Interface
      • Key Management
      • Decentralized Identifiers
      • Verifiable Credentials
      • OpenID Connect (OIDC)
    • Building the Project
      • Docker Build
      • Local Build
    • Project Configurations
    • Demo
  • Ecosystems
    • EBSI
      • Basics
      • Use Cases & Flow Diagrams
      • Command line interface
        • DID Registration
      • REST API
      • Usage / examples
        • Onboarding & DIDs
        • Build end-to-end use cases
    • IOTA
      • OIDC4VP profile for Login-with-IOTA
      • Login With IOTA Demo
    • Velocity
      • Basics
        • Onboarding
        • Issuing
        • Inspection
      • Integration with SSIKit
      • Command line interface
        • Onboarding
        • Issuing
        • Inspection
    • cheqd
      • Integration architecture
      • Create DID
      • Issue VC
      • Verify VC
  • Tutorials
    • My First VC
    • Advanced VC
  • Concepts
    • Credential Templates
    • Verification Policies
      • Static Policies
      • Parameterized Policies
      • Dynamic/Custom Policies
        • Creating Dynamic Policies
        • Using Dynamic Policies
        • Removing Dynamic Policies
        • Dynamic Policies | Data Classes
    • Selective Disclosure
      • Intro
      • Issuing a SD-JWT Credential
      • Verifying a SD-JWT Credential
    • Credential Statuses
      • StatusList2021Entry
      • SimpleCredentialStatus2022
      • Issue credentials with credentialStatus
      • REST API
        • Check the status of a credential
        • Revoke a credential
      • CLI
        • Check the status of a credential
        • Revoke a credential
    • DID Web
    • Open Policy Agent (OPA)
      • Setup
    • OpenID Connect (OIDC)
      • Credential Issuance
        • OIDC4CI | Example
      • Presentation Exchange
        • OIDC4VP | Example
    • Delegation and Mandates
  • Community
    • Discord
    • Twitter
    • Newsletter
    • GitHub Discussions
  • DEVELOPER RELATIONS
    • Contribute
    • Roadmap
    • Share Feedback
    • Contact
  • Product Editions
    • Open Source | Always Free
    • Enterprise | Self-Managed
    • Cloud Platform | Managed
Powered by GitBook
On this page
  • Running the SSI-Kit
  • Establishing a Digital Identity (DID)
  • Creating an EmployeeID Template
  • Issuing a Verifiable Credential to Emma
  • Authenticating with Door Access System
  • Next Steps

Was this helpful?

Export as PDF
  1. Tutorials

Advanced VC

Onboarding Emma to a Virtual Company, issuing custom credentials, and utilizing dynamic verification policies.

PreviousMy First VCNextCredential Templates

Last updated 1 month ago

Was this helpful?

In this tutorial, we will expand on the by now onboarding Emma to a virtual company. During the onboarding, Emma will receive an EmployeeID credential, which will be based on a custom credential template using the status property. With that, you learn about two more concepts; Custom credential templates and the status property. The credential will also have Emma's role as a property, which can then be checked with a dynamic verification policy, another new concept.

Where we start:

Using the walt.id SSI-Kit's REST API, we'll streamline access control within the company by

  • : The company will be set up as the issuer through its own Digital Identity (DID).

  • : This template will be used for generating verifiable credentials for employees.

  • : Emma, an employee, will be issued a Verifiable Credential, making her the holder.

  • : The system, acting as the Verifier, will:

    • Confirm Emma's employment status

    • Assess her role within the company

    • Grant or deny access to specific areas on the company campus based on the above.

Running the SSI-Kit

Make sure you have Docker or a JDK 16 build environment including Gradle installed on your machine

Pull the docker container directly from docker hub and run the project

docker run -p 7000-7004:7000-7004 -itv $(pwd)/data:/app/data waltid/ssikit serve -b 0.0.0.0

This will create a folder called data in your current directory as storage for the VC, DIDs, Keys and other things which need to be stored in order to provide all the functionality.

  1. Clone the project

git clone https://github.com/walt-id/waltid-ssikit.git

2. Change the folder

cd waltid-ssikit/

3. Run the project

The first time you run the command you will be asked to built the project. You can confirm the prompt.

./ssikit.sh serve

Now with the SSI-Kit up and running, we can create the DID for the company, establishing its Digital Identity.

Establishing a Digital Identity (DID)

You have two options for creating a DID: executing a curl command or visiting the swagger docs. The custodian endpoint should be visible in the terminal after you have run the serve command, visit the endpoint to see the swagger docs.

curl -X 'POST' \
  'http://localhost:7002/did/create' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "method": "{method}"
}'

Body Parameters method: [string] method of the did. Value can be one of key, web, ebsi, iota, cheqd, jwk Example

curl -X 'POST' \
  'http://localhost:7002/did/create' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "method": "key"
}'

Creating an EmployeeID Template

Let's create one for an EmployeeID. The template will include the following properties:

  • id: Identifier for the employee

  • name: Name of the employee

  • role: Role or designation in the company

  • joiningDate: Date of joining the company

{
  "type": ["VerifiableCredential", "EmployeeID"],
  "credentialSubject": {
    "id": "",
    "name": "",
    "role": "",
    "joiningDate": ""
  }
}

Saving the credential template

curl -X 'POST' \
  'http://127.0.0.1:7001/v1/templates/{id}' \
  -H 'accept: text/plain' \
  -H 'Content-Type: application/json' \
  -d '{credentialTemplate}'

Path Parameters

  • id: The name for the credential template, which we will later reference during issuance. e.g. EmployeeID

Body Use the JSON structure from above as the body. Example

curl -X 'POST' \
  'http://127.0.0.1:7001/v1/templates/EmployeeID' \
  -H 'accept: text/plain' \
  -H 'Content-Type: application/json' \
  -d '{
    "type": ["VerifiableCredential", "EmployeeID"],
    "credentialSubject": {
        "id": "",
        "name": "",
        "role": "",
        "joiningDate": ""
    }
}'

We can streamline the process of issuing a credential to Emma by utilizing the EmployeeID credential template. However, we also have the opportunity to further simplify the process using an additional feature: prefilling credential properties. This will be particularly beneficial as Emma likely won't be the only one receiving the Engineer role assignment. By creating a template where the Engineer role is prefilled, we can improve the issuance process.

EngineerEmployeeID Template

{
    "type": ["VerifiableCredential", "EmployeeID"],
    "credentialSubject": {
        "id": "",
        "name": "",
        "role": "Engineer",
        "joiningDate": ""
    }
}

You can now also save this template and use it later for the issuance of our VC, or use the one we created before and provide the value for the role attribute during issuance.

Issuing a Verifiable Credential to Emma

curl -X 'POST' \
  'http://localhost:7001/v1/credentials/issue' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "templateId": "{template type}",
  "config": {
    "issuerDid": "{issuerDid}",
    "subjectDid": "{subjectDid}",
    "proofType": "{proofType}",
    "statusType": "{statusType}"
  },
  "credentialData": {
    "id": "{subjectDID}",
    "name": "{name}",
    "role": "{role}",
    "joiningDate": "{joiningDate}"
  }
}'

Body Parameters

  • templateId: [string] The identifier of the template used for issuing a Verifiable Credential. In our case this would be the EmployeeID or EngineerEmployeeID template.

  • config: [object] Contains configuration parameters for the issuance process.

    • issuerDid: [string] The DID of the entity issuing the credential (University).

    • subjectDid: [string] The DID of the entity receiving the credential (Emma).

    • proofType: [string] Specifies the format and cryptographic algorithm used for the digital signature of the Verifiable Credential. E.g. LD_PROOF

    • statusType: [statusType] Specifies if the credential should be issued with status and the type of the status. Options StatusList2021Entry or SimpleCredentialStatus2022

  • credentialData: [object] Contains the actual data of the credential being issued.

    • credentialSubject: [object] Holds the information about the employee as described in the EmployeeID credential template.

The id in the credential subject we don't need to provide as this will be prefilled automatically with the DID of Emma.

Example EmployeeID:

curl -X 'POST' \
  'http://localhost:7001/v1/credentials/issue' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "templateId": "EmployeeID",
  "config": {
    "issuerDid": "did:key:z6MkmE21F2dAHkM71tnYdBEGaSvnPpxBFZYi2wtzYbTwqvgK",
    "subjectDid": "did:key:z6MkmE21F2dAHkM71tnYdBEGaSvnPpxBFZYi2wtzYbTwqvgK",
    "proofType": "LD_PROOF",
    "statusType": "StatusList2021Entry"
  },
  "credentialData": {
    "name": "Emma",
    "role": "Engineer",
    "joiningDate": "2023-06-28"
  }
}'

Example EngineerEmployeeID:

curl -X 'POST' \
  'http://localhost:7001/v1/credentials/issue' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "templateId": "EngineerEmployeeID",
  "config": {
    "issuerDid": "did:key:z6MkmE21F2dAHkM71tnYdBEGaSvnPpxBFZYi2wtzYbTwqvgK",
    "subjectDid": "did:key:z6MkmE21F2dAHkM71tnYdBEGaSvnPpxBFZYi2wtzYbTwqvgK",
    "proofType": "LD_PROOF",
    "statusType": "StatusList2021Entry"
  },
  "credentialData": {
    "name": "Emma",
    "joiningDate": "2023-06-28"
  }
}'

Now we can use the issued VC in the company campus verification system.

Authenticating with Door Access System

To successfully authorize access, our authentication system needs to verify four crucial elements regarding the Verifiable Credential presented during the verification process:

  1. Confirm the signature of the Verifiable Credential to ensure it's legitimate.

  2. Ascertain the credential's validity by validating its current status, ensuring it has not expired or been revoked.

  3. Verify that the issuer is indeed our company, thereby eliminating any fraudulent issuers.

  4. Evaluate whether the role of the employee, as indicated on the credential, authorizes them to access the desired area.

To facilitate successful verification, we will use Verification Policies. For the initial two cases, which are relatively common, we can utilize our built-in policies, namely SignaturePolicy and CredentialStatusPolicy. These policies essentially verify that the signature is authentic and that the status is still valid.

Creating Custom Policies - IsCompany

package system

default main = false

main {
    input.credentialData.issuer == {issuerDID}
}

Make sure to replace {issuerDID} with the DID of your issuer (company)

Creating Custom Policies - IsRole

This custom policy holds greater flexibility, as it accepts an argument containing a 'role' property. This property is then cross-verified with the role present in the Verifiable Credential. Alternatively, the role can be hardcoded, and the policy can be renamed accordingly, such as IsEngineer, similar to the IsCompany policy.

package system

default main = false

main {
    input.parameter.role == input.credentialData.credentialSubject.role
}

Saving the policies

curl -X 'POST' \
  'http://127.0.0.1:7003/v1/create/{{policyName}}?update=true&downloadPolicy=true' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "IsCompany",
    "description": "Test",
    "input": {},
    "policy": "package system

default main = false

main {
    input.credentialData.issuer == \"did:key:z6MkrFtzYS5RW748vvAjARZ4CYjBMveV9LYfSAFov439Bm8Z\"
}",
}
",
    "dataPath": "$",
    "policyQuery": "data.system.main",
    "policyEngine": "OPA",
    "applyToVC": true,
    "applyToVP": true
}'

Path parameters:

  • policyName: [string] Name of the policy, e.g. IsCompany

Query parameters:

  • update: [boolean] Specifies if existing policy with same name should be overridden (if mutable)

  • downloadPolicy: [boolean] When using an URL to reference the to created policy. Downloads and/or saves the policy definition locally, rather than keeping the reference to the original URL\

Body

{
    "name": "MyCustomPolicy",
    "description": "Test",
    "input": {},
    "policy": "package system

               default main = false

               main {
                 input.credentialData.issuer == \"did:key:z6MkrFtzYS5RW748vvAjARZ4CYjBMveV9LYfSAFov439Bm8Z\"
    }",
    "dataPath": "$",
    "policyQuery": "data.system.main",
    "policyEngine": "OPA",
    "applyToVC": true,
    "applyToVP": true
}
  • name: [string] Policy name, must not conflict with existing policies

  • description: [string] Optional policy description

  • input: [JSON] Input JSON object for rego query, which can be overridden/extended on verification. Can be a JSON string or JSON file

  • policy: [URL, REGO] Whole Policy or URL to policy definition.

  • dataPath: [JSON path] JSON path to the data in the credential which should be verified, default: "$" (whole credential object)

  • policyQuery: [string] The query string in the policy engine language. Defaults to "data.system.main".

  • policyEngine: [string] Policy engine type, default: OPA. Options, OPA

  • applyToVC: [boolean] Apply/Don't apply to verifiable credentials (default: apply)

  • applyToVP: [boolean] Apply/Don't apply to verifiable presentation (default: don't apply)

Using the endpoint above, you can save both policies.

Verifying the credential with all policies

Now with the custom policies created, we will use those and the two predefined ones to verify Emma's credential and enable access.

curl -X 'POST' \
  'http://127.0.0.1:7003/v1/verify' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -d '{
    "policies": [
        {
            "policy": "SignaturePolicy"
        },
        {
            "policy": "CredentialStatusPolicy"
        },
        {
            "policy": "IsRole",
            "argument": {"role": "Engineer"}
        },
        {
            "policy": "IsCompany"
        }
    ],
    "credentials": [{
  "type" : [ "VerifiableCredential", "EngineerEmployeeID" ],
  "@context" : [ "https://www.w3.org/2018/credentials/v1", "https://w3id.org/security/suites/jws-2020/v1" ],
  "id" : "urn:uuid:ae9cf1f3-8609-4685-9928-5073b6990af4",
  "issuer" : "did:key:z6MkrFtzYS5RW748vvAjARZ4CYjBMveV9LYfSAFov439Bm8Z",
  "issuanceDate" : "2023-06-28T13:55:15Z",
  "issued" : "2023-06-28T13:55:15Z",
  "validFrom" : "2023-06-28T13:55:15Z",
  "credentialSubject" : {
    "id" : "did:key:z6MkrFtzYS5RW748vvAjARZ4CYjBMveV9LYfSAFov439Bm8Z",
    "name" : "Emma",
    "role" : "Engineer",
    "joiningDate" : "2023-06-28"
  },
  "credentialStatus" : {
    "id" : "http://127.0.0.1:7001/v1/credentials/status/revocation#2",
    "statusListCredential" : "http://127.0.0.1:7001/v1/credentials/status/revocation",
    "statusListIndex" : "2",
    "statusPurpose" : "revocation",
    "type" : "StatusList2021Entry"
  },
  "proof" : {
    "type" : "JsonWebSignature2020",
    "created" : "2023-06-28T13:55:15Z",
    "verificationMethod" : "did:key:z6MkrFtzYS5RW748vvAjARZ4CYjBMveV9LYfSAFov439Bm8Z#z6MkrFtzYS5RW748vvAjARZ4CYjBMveV9LYfSAFov439Bm8Z",
    "jws" : "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9.._uFLlXHpNgFsUJFwahcIh_VeLsps8n5ZaifMMvAMqmOkESWN1eoJNNkGfAYY_R185ia-qkKRKwb2rsNzPUcvAA"
  }
}]
}
'

Body

{
    "policies": [
        {
            "policy": "SignaturePolicy"
        },
        {
            "policy": "CredentialStatusPolicy"
        },
        {
            "policy": "IsRole",
            "argument": {"role": "Engineer"}
        },
        {
            "policy": "IsCompany"
        }
    ],
    "credentials": [
      {... credential ... }
    ]
}
  • policies: [array] A list of policy definitions to verify against

    • policy: [string] The name/id of the policy

    • argument: [JSON] The argument needed by the policy (optional)

  • credentials: [array] An array of credentials in JWT, or LD_PROOF format

Congratulations, you've reached the finish line! 🎉 You have skillfully utilized an array of features to bring this use case to life. Now, you have the opportunity to explore further and deepen your understanding of the concepts introduced today. Happy building!

Next Steps

Create one DID for the company using the command above. In case you don't have done the My First VC tutorial and still have the DID for Emma, create another one for her. Make sure to save both, as we will be needing them later for the issuance of the EmployeID. You can also use to see all previously created DIDs.

The SSI-Kit supports the creation of , which are blueprints that establish reusable data structures based on which credentials can be issued.

In order to issue Emma's EmployeeID VC, we will use one of the credential templates. Additionally, we will include a credential status so that we have the option to revoke the credential if Emma leaves the company without needing to remove it from her ownership. For more information on credential status and the types we support, read .

For the additional cases, we will create custom policies, leveraging the Open Policy Agent (OPA) Engine and the REGO language. You can learn more about it .

Please install the Open Policy Agent as described , to ensure seamless verification.

- Dive deeper into credential templates and what you can do with them

- Learn more about the credential status property and what is enables.

- Explore our pre-build templates and learn more about how to build and leverage custom ones using OPA (Open Policy Agent) and the Rego language.

credential templates
our guide
here
here
Credential Templates
Credential Status
Verification Policies
"My First VC" tutorial
Establishing a Digital Identity (DID)
Creating an EmployeeID Template
Issuing a Verifiable Credential to Emma
Authenticating with Door Access System
the list DID endpoint