This application explores an approach for issuing Verifiable Credentials to companies and their employees in a Gaia-X ecosystem. Employees could then use these credentials to authenticate with different services in the ecosystem. A key feature is that the signature process necessary for issuance is done on personal devices of administrative staff. That way, no keys are ever in the system.
The operator of this web application hosts it as a trust anchor to enable identity management among a dataspace or consortium. The operator only directly certifies company identities. This application supports companies in employee credential issuance, but that could be done entirely inside each company with custom software.
Component | Generic Role | Explanation |
---|---|---|
React Website | Frontend | Website provides a basic user interface. |
Express API Server | Backend | Provides an API for authentication and database operations. Also supports OID4VCI to issue credentials. |
MongoDB | Database | Stores applications for credentials and the credentials themselves. |
Registry Smart Contract | Smart Contract | Securely administrates issuer keys for the trust anchor. |
Note
The backend is designed to be as versatile as possible. While most organizations will want to build a custom frontend, the intention is to have them develop and maintain the backend collaboratively.
Role | Explanation |
---|---|
Operator & Trust Anchor | Operates this web application and functions as a trusted entity within an ecosystem. |
Company | Companies apply to be certified by the trust anchor. If accepted, they receive a company credential. |
Employee | Employees work at certified companies and can receive employee credentials from their company through the web app. |
Company starts by applying for consortium membership:
- Company sets up a wallet app and generates a DID
- Company navigates to the website and uses their smartphone wallet app to log in
- Company fills in a company application form on the website
- Company logs out
Trust Anchor issues a company credential:
- Trust Anchor has a wallet and key that is registered in the smart contract
- Trust Anchor navigates to the website and uses a wallet to log in
- Trust Anchor reviews list of new company applications and sees Company's application
- Trust Anchor contacts Company out of band to confirm suitability for membership, identity, and intent
- Trust Anchor clicks the corresponding button on the website to approve credential issuance for the application
- Trust Anchor reviews new signing request for the company credential on his wallet and confirms
- Trust Anchor reviews new transaction request to log the company credential issuance to the blockchain (as a trusted issuer directory for employee credentials) and confirms
- Trust Anchor sees confirmation of issuance on the website and logs out
Company returns to receive credential:
- Company navigates to the website and uses their wallet to log in
- Company sees their credential was issued and clicks to take out the credential via OID4VCI protocol
- Company scans the QR code and confirms the credential preview on the wallet
- Company has the company credential in the wallet
- Company logs out
This use case parallels the previous one. Now, an Employee applies through the website. The Company issues him a credential, which he can download.
This software is experimental. Anyone attempting to use it in production should have good technical understanding and be willing to open issues and PRs if necessary.
The data fields used for application forms and subsequent credential creation are just placeholder data. Since they are written to the database as JSON, frontends can just choose different ones (except for name
).
The verifiable credential format used is jwt
, more specifically jwt_vc_json
, but jwt_vc_json-ld
should be possible with no changes (assuming the JSON-LD does not need to be validated). The frontend dictates how the application data is transformed into a credential, keeping the backend generic.
The signature is making the credentials technically not true JWTs. For security reasons, wallets only allow signing data with prefixes. A generic JWT verifier that does not know this, will fail to verify the signature. But transport protocols and wallets seem to have no issues.
This version has no built-in revocation mechanism.
The API enforces a maximum of one company credential per public key. Registrars are not allowed to have companies on the same key.
Currently, the issued credentials are not compatible with the Gaia-X Digital Clearing House, because that demands a signature performed with a did:web
.
Since the project consists of two different subprojects, using docker for development is easiest.
Install a tunneling tool like ngrok. You will need it to easily use a smartphone wallet with the application or to demo the application to someone outside your local network.
Install a wallet software that supports Tezos and the Beacon protocol. For the best experience, we currently recommend using Altme. Be aware that you can choose a wallet that is not an SSI wallet here.
Install an SSI wallet software that supports the OID4VCI protocol, if your previous wallet choice does not support it already.
This project uses the Tezos blockchain to provide secure timestamped consensus on valid issuers. The registry smart contract in the tezos
directory needs to be deployed on your preferred testnet. For quick deployment, refer to the README.md
file in the same directory.
An environment file .env
is required. Copy .env.example
and fill it in according to the comments.
First, run the tunnel to get a globally accessible URL for the development server:
ngrok http 8080
Enter the resulting URL into the .env
file where stated.
Then, run the docker-compose file to start the development server:
docker compose up --build
Open http://localhost:3000 with your browser to see the result.
If you would like to use hot-reloading, press w
in the running docker compose process to activate watch mode. Or run it with the corresponding argument initially (assuming you already built using docker compose build
):
docker compose watch