External DID Web Hosting
This guide explains how to make DIDs available at a custom domain (e.g., dids.waltid.org) instead of the default enterprise domain.
Overview
By default, DIDs in the walt.id Enterprise Stack are hosted at the enterprise domain (e.g., waltid.enterprise.cloud
). However, you may want to make these DIDs available at your own custom domain (e.g., dids.waltid.org
). This guide explains how to set up external DID web hosting to achieve this.
Prerequisites
- Access to a walt.id Enterprise Stack organization
- A tenant with DID registry service
- A custom domain that you control (e.g.,
dids.waltid.org
) - Access to configure DNS settings for your custom domain
Step 1: Configure Organization-Level Root DID Registry
Before configuring the tenant-level DID registry, you need to set up an organization-level root DID registry:
- Create Organization-Level DID Registry Service:
Endpoint: /v1/{target}/resource-api/services/create
| API Reference
Example Request
curl -X 'POST' \
'https://{orgID}.enterprise.cloud/v1/{target}/resource-api/services/create' \
-H 'accept: */*' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"type": "did-registry"
}'
Path Parameters
orgID
: - When performing operations within an organization, it is essential to use the organization's Base URL or another valid host alias. For example, if your organization is namedwaltid
, your default Base URL will bewaltid.enterprise.cloud
.target
: resourceIdentifier - The target indicates the organization in which to create the new organization level DID Registry service, e.g.waltid.tenant.didregistry
Body Parameters
type
: serviceType - Specifies the type of service to create. In our casedid-registry
- Set Up Root DID Registry:
Endpoint: /v1/organization/update-config
| API Reference
Example Request
curl -X 'POST' \
'https://{orgID}.enterprise.cloud/v1/organization/update-config' \
-H 'accept: */*' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"rootDidRegistry": "waltid.tenant.didregistry"
}'
Path Parameters
orgID
: - When performing operations within an organization, it is essential to use the organization's Base URL or another valid host alias. For example, if your organization is namedwaltid
, your default Base URL will bewaltid.enterprise.cloud
.
Body Parameters
rootDidRegistry
: resourceIdentifier - The ID of the DID Registry Service to be used for organization-level DIDs, e.g.waltid.tenant.didregistry
Step 2: Configure Tenant-Level DID Registry
First, ensure that your tenant has the DID registry service properly configured:
Endpoint:/v1/{target}/tenant-api/tenants/config/update
| API Reference
Example Request
curl -X 'POST' \
'https://{orgID}.enterprise.cloud/v1/{target}/tenant-api/tenants/config/update' \
-H 'accept: */*' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"didRegistry": "waltid.tenant.didregistry"
}'
Body
{
"didRegistry": "waltid.tenant.didregistry"
}
Path Parameters
orgID
: - When performing operations within an organization, it is essential to use the organization's Base URL or another valid host alias. For example, if your organization is namedwaltid
, your default Base URL will bewaltid.enterprise.cloud
.target
: resourceIdentifier - The target indicates the tenant for which to update the configuration ({organizationID}.{tenantID}
), e.g.waltid.tenant
Body Parameters
didRegistry
: String - The ID of the DID Registry service to be associated with the tenant. This should be the fully qualified ID of your DID registry service.
Step 3: Create Host Alias for Tenant
Create a host alias for your tenant that points to your custom domain:
Endpoint:/v1/{target}/resource-api/host-aliases/create
| API Reference
Example Request
curl -X 'POST' \
'https://{orgID}.enterprise.cloud/v1/{target}/resource-api/host-aliases/create' \
-H 'accept: */*' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"domain": "dids.waltid.org"
}'
Body
{
"domain": "dids.waltid.org"
}
Path Parameters
orgID
: - When performing operations within an organization, it is essential to use the organization's Base URL or another valid host alias. For example, if your organization is namedwaltid
, your default Base URL will bewaltid.enterprise.cloud
.target
: resourceIdentifier - The target indicates the tenant for which to create the host alias ({organizationID}.{tenantID}.{host_alias_id}), e.g.
waltid.tenant.my_alias`
Body Parameters
domain
: String - The custom domain that you want to use for your tenant. This is the domain where your DIDs will be available.
Step 4: Configure DNS and Reverse Proxy (Customer Side)
On the customer side, you need to configure your DNS and set up a reverse proxy to point your custom domain to the enterprise stack server:
- DNS Configuration:
- Create a DNS record for your custom domain (e.g.,
dids.waltid.org
) pointing to your reverse proxy server.
- Create a DNS record for your custom domain (e.g.,
- Reverse Proxy Setup:
- Set up a reverse proxy (e.g., Nginx, Apache, Traefik) on your server.
- Configure SSL/TLS for your custom domain.
- Configure the reverse proxy to forward requests from your custom domain to the enterprise stack server.
Example Nginx Configuration:
server {
listen 443 ssl;
server_name dids.waltid.org;
ssl_certificate /path/to/your/certificate.crt;
ssl_certificate_key /path/to/your/private.key;
location / {
proxy_pass https://waltid.enterprise.cloud;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Example Kubernetes Ingress Configuration:
If you're using Kubernetes, you can set up an Ingress resource to route traffic to your enterprise API service:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: dids-waltid-org-enterprise-ingress
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
ingressClassName: "nginx"
tls:
- hosts:
- dids.waltid.org
secretName: did-waltid-org-tls
rules:
- host: dids.waltid.org
http:
paths:
- path: /auth/
pathType: Prefix
backend:
service:
name: waltid-enterprise-api
port:
name: http
- path: /v1/
pathType: Prefix
backend:
service:
name: waltid-enterprise-api
port:
name: http
- path: /.well-known/vct/v1/
pathType: ImplementationSpecific
backend:
service:
name: waltid-enterprise-api
port:
name: http
- path: /swagger
pathType: Prefix
backend:
service:
name: waltid-enterprise-api
port:
name: http
- path: /api.json
pathType: ImplementationSpecific
backend:
service:
name: waltid-enterprise-api
port:
name: http
- path: /.*/did\.json$
pathType: ImplementationSpecific
backend:
service:
name: waltid-enterprise-api
port:
name: http
- path: /livez
pathType: Prefix
backend:
service:
name: waltid-enterprise-api
port:
name: http
- path: /features/
pathType: Prefix
backend:
service:
name: waltid-enterprise-api
port:
name: http
- path: /debug/
pathType: Prefix
backend:
service:
name: waltid-enterprise-api
port:
name: http
This Ingress configuration:
- Sets up TLS for the dids.waltid.org domain using cert-manager
- Routes various API paths to the waltid-enterprise-api service
- Includes a regex path for DID documents (/.*/did.json$)
Step 5: Create DID in DID Store
Create a DID in the DID Store, making sure to use your custom domain in the domain parameter:
Endpoint: /v1/{target}/did-service-api/dids/create/web
| API Reference
Example Request
curl -X 'POST' \
'https://{orgID}.enterprise.cloud/v1/{target}/did-service-api/dids/create/web' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"type": "single_key_id",
"keyId": "waltid.tenant.kms1.secp256r1",
"domain": "dids.waltid.org",
"path" : "user1"
}'
Body
{
"type": "single_key_id",
"keyId": "waltid.tenant.kms1.secp256r1",
"domain": "dids.waltid.org",
"path" : "user1"
}
Path Parameters
orgID
: - When performing operations within an organization, it is essential to use the organization's Base URL or another valid host alias. For example, if your organization is namedwaltid
, your default Base URL will bewaltid.enterprise.cloud
.target
: resourceIdentifier - The target indicates the organization + tenant + DID service in which to execute the DID creation ({organizationID}.{tenantID}.{subtenantID}.{didServiceID}
), e.g.waltid.tenant.did1
Body Parameters
keyId
: resourceIdentifier - Specifies the key for which to generate a DID + DID Document. Please make sure that the key is stored in a KMS service under the same tenant as the DID service.domain
: string - The domain name to be used for the DID:web. This should be your custom domain (e.g.,dids.waltid.org
).path
: string - The path to be used for the DID:web (e.g.,user1
).
Response
201
- DID created successfully.
{
"did": "did:web:dids.waltid.org:user1",
"document": {
"context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/suites/jws-2020/v1"
],
"id": "did:web:dids.waltid.org:user1",
"verificationMethod": [
{
"id": "did:web:dids.waltid.org:user1#key1",
"type": "JsonWebKey2020",
"controller": "did:web:dids.waltid.org:user1",
"publicKeyJwk": {
"kty": "EC",
"crv": "P-256",
"kid": "key1",
"x": "...",
"y": "..."
}
}
],
"assertionMethod": [
"did:web:dids.waltid.org:user1#key1"
],
"authentication": [
"did:web:dids.waltid.org:user1#key1"
],
"capabilityDelegation": [
"did:web:dids.waltid.org:user1#key1"
],
"capabilityInvocation": [
"did:web:dids.waltid.org:user1#key1"
],
"keyAgreement": [
"did:web:dids.waltid.org:user1#key1"
]
}
}
Step 6: Verify DID Resolution
Once you've completed the above steps, your DID should be available to resolve at your custom domain:
did:web:dids.waltid.org:user1
You can verify this by accessing the DID document directly at:
https://dids.waltid.org/user1/did.json
Troubleshooting
If you're having issues with external DID web hosting, check the following:
- Organization-Level DID Registry: Ensure that your organization has the correct root DID registry configured.
- Tenant Configuration: Ensure that your tenant has the correct DID registry configured.
- Host Alias: Verify that the host alias has been created correctly with your custom domain.
- DNS Configuration: Check that your DNS records are pointing to the correct server.
- Reverse Proxy: Ensure that your reverse proxy is correctly configured to forward requests to the enterprise stack server.
- DID Creation: Make sure you used your custom domain when creating the DID.