From f999f303f876d97287f217e00bdbc1bbcd193495 Mon Sep 17 00:00:00 2001 From: patlo-iog Date: Tue, 16 Jul 2024 22:14:42 +0700 Subject: [PATCH] docs: oid4vci example and docs [skip ci] (#1265) Signed-off-by: Pat Losoponkul Signed-off-by: patlo-iog Signed-off-by: Hyperledger Bot Co-authored-by: Yurii Shynbuiev - IOHK Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Hyperledger Bot --- docs/docusaurus/credentials/issue.md | 2 +- docs/docusaurus/credentials/oid4vci.md | 74 +++++++++++++++++++ docs/docusaurus/sidebars.js | 5 +- docs/general/authserver-oid4vci-contract.md | 72 ++++++++++++++++++ examples/.nickel/caddy.ncl | 2 +- examples/.nickel/root.ncl | 2 +- examples/.nickel/stack.ncl | 2 +- examples/.nickel/versions.ncl | 2 +- examples/mt-keycloak-vault/README.md | 2 +- examples/mt-keycloak-vault/compose.yaml | 8 +- .../hurl/01_create_users.hurl | 6 +- .../mt-keycloak-vault/hurl/02_jwt_flow.hurl | 40 +++++----- examples/mt-keycloak/README.md | 2 +- examples/mt-keycloak/compose.yaml | 8 +- .../mt-keycloak/hurl/01_create_users.hurl | 6 +- examples/mt-keycloak/hurl/02_jwt_flow.hurl | 44 +++++------ examples/mt/README.md | 2 +- examples/mt/compose.yaml | 8 +- examples/st-multi/README.me | 10 +-- examples/st-multi/compose.yaml | 24 +++--- examples/st-multi/hurl/01_jwt_flow.hurl | 44 +++++------ examples/st-oid4vci/README.md | 26 ++----- examples/st-oid4vci/compose.yaml | 10 +-- examples/st-oid4vci/demo/Dockerfile | 6 ++ examples/st-oid4vci/{demo.py => demo/main.py} | 49 ++++++------ examples/st-oid4vci/demo/requirements.txt | 11 +++ examples/st-vault/README.md | 2 +- examples/st-vault/compose.yaml | 8 +- examples/st/README.md | 6 +- examples/st/compose.yaml | 8 +- 30 files changed, 321 insertions(+), 170 deletions(-) create mode 100644 docs/docusaurus/credentials/oid4vci.md create mode 100644 docs/general/authserver-oid4vci-contract.md create mode 100644 examples/st-oid4vci/demo/Dockerfile rename examples/st-oid4vci/{demo.py => demo/main.py} (90%) create mode 100644 examples/st-oid4vci/demo/requirements.txt diff --git a/docs/docusaurus/credentials/issue.md b/docs/docusaurus/credentials/issue.md index 30646fa8e0..b392d310c2 100644 --- a/docs/docusaurus/credentials/issue.md +++ b/docs/docusaurus/credentials/issue.md @@ -1,7 +1,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Issue credentials +# Issue credentials (DIDComm) In the Identus Platform, the [Issue Credentials Protocol](/docs/concepts/glossary#issue-credentials-protocol) allows you to create, retrieve, and manage issued [verifiable credentials (VCs)](/docs/concepts/glossary#verifiable-credentials) between a VC issuer and a VC holder. diff --git a/docs/docusaurus/credentials/oid4vci.md b/docs/docusaurus/credentials/oid4vci.md new file mode 100644 index 0000000000..a84b7c7dfe --- /dev/null +++ b/docs/docusaurus/credentials/oid4vci.md @@ -0,0 +1,74 @@ +# Issue credentials (OID4VCI) + +[OID4VCI](/docs/concepts/glossary#oid4vci) (OpenID for Verifiable Credential Issuance) is a protocol that extends OAuth2 to issue credentials. +It involves a Credential Issuer server and an Authorization server working together, +using the authorization and token endpoints on the Authorization Server to grant holders access to credentials on the Credential Issuer server. +These servers may or may not be the same, depending on the implementation. + +The Identus Cloud Agent can act as a Credential Issuer server and integrate with any Authorization Server that follows the integration contract. The contract for the Authorization Server in the OID4VCI flow can be found [here](https://github.com/hyperledger/identus-cloud-agent/blob/main/docs/general/authserver-oid4vci-contract.md). + +## Example: OID4VCI Authorization Code Issuance + +Example is available [here](https://github.com/hyperledger/identus-cloud-agent/tree/main/examples/st-oid4vci). + +Following the instructions, the example demonstrates a single-tenant agent setup using an external Keycloak as the Issuer Authorization Server. The demo application walks through the authorization code issuance flow step-by-step. + +#### 1. Launching Local Example Stack + +```bash +docker-compose up +``` + +After running the `docker-compose up` command, all the containers should be running and initialized with the necessary configurations. The following logs should appear indicating that the stack is ready to execute the flow + +``` + _ _ _ _ _ + | |_| |_| |_ _ __| | | ___ + | ' \ _| _| '_ \_ _(_-< + |_||_\__|\__| .__/ |_|/__/ + |_| + 2024-07-16_11:51:01.301 INFO o.h.b.s.BlazeServerBuilder@L424:[ZScheduler-Worker-5] {} - http4s v0.23.23 on blaze v0.23.15 started at http://0.0.0.0:8085/ + +``` + +#### 2. Building the demo application + +```bash +docker build -t identus-oid4vci-demo:latest ./demo +``` + +#### 3. Running the demo application + +```bash +docker run --network -it identus-oid4vci-demo:latest +``` +The parameter `NETWORK_NAME` should be the same as the network name in docker-compose. +This name can be discovered by running the `docker network ls` command. + +The demo application acts as both issuer and Holder in the same script. +See the source code for detailed steps on how to implement this flow. +The demo application will interactively prompt the next step in the issuance flow. +Keep continuing until this log appears asking the user to log in using the browser. + +``` +############################## + +Open this link in the browser to login + +http://localhost:9980/realms/students/protocol/openid-connect/auth?redirect_uri=..... + +############################## + +wating for authorization redirect ... +``` + +Open this URL in the browser. Enter `alice` for the username and `1234` for the password. + +After a successful login, this log should appear indicating the demo application has received the credentials. + +``` +::::: Credential Received ::::: +{ + "credential": "eyJ0eXAiOiJKV1QiLC...SK1vJK-fx6zjXw" +} +``` diff --git a/docs/docusaurus/sidebars.js b/docs/docusaurus/sidebars.js index 7e1712fa68..b746ea93f5 100644 --- a/docs/docusaurus/sidebars.js +++ b/docs/docusaurus/sidebars.js @@ -20,8 +20,9 @@ const sidebars = { }, items: [ 'credentials/issue', + 'credentials/oid4vci', 'credentials/present-proof', - 'credentials/revocation', + 'credentials/revocation' ] }, { @@ -96,7 +97,7 @@ const sidebars = { 'multitenancy/tenant-onboarding-ext-iam', 'multitenancy/tenant-onboarding-self-service', 'multitenancy/tenant-migration', - 'multitenancy/admin-authz-ext-iam', + 'multitenancy/admin-authz-ext-iam' ] } ] diff --git a/docs/general/authserver-oid4vci-contract.md b/docs/general/authserver-oid4vci-contract.md new file mode 100644 index 0000000000..3260389333 --- /dev/null +++ b/docs/general/authserver-oid4vci-contract.md @@ -0,0 +1,72 @@ +# OID4VCI Authorization Server contract + +Identus Cloud Agent supports OID4VCI while allowing users to plug-in their authorization server. +The agent provides a credential endpoint, while the authorization server handles the authorization and token endpoints. +This flexibility enables integration with any existing authorization server potentially containing the holder user base. +The issuance flow implementation requires the authorization server to adhere to the contract, ensuring the agent can manage the issuance session and coordinate the process. + +The Identus platform also provides the [Keycloak plugin reference implementation](https://github.com/hyperledger/identus-keycloak-plugins) showcasing the agent capability. +However, the authorization server is not limited to only Keycloak. + +## Contract for Authorization Code issuance flow + +The sequence diagram is largely based on [OID4VCI spec](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#name-authorization-code-flow) +with slight modification to the __TokenEndpoint__. + +```mermaid +sequenceDiagram + participant Holder + participant Issuer + participant AuthServer + participant CloudAgent + + Issuer ->>+ CloudAgent: Create CredentialOffer + CloudAgent ->>- Issuer: CredentialOffer
(issuer_state) + Issuer -->> Holder: Present offer
(issuer_state) + Holder ->>+ CloudAgent: Discover Metadata + CloudAgent ->>- Holder: IssuerMetadata + Holder ->>+ AuthServer: Discover Metadata + AuthServer ->>- Holder: AuthServerMetadata + Holder ->>+ AuthServer: AuthorizationRequest
(issuer_state) + AuthServer ->>- Holder: AuthorizationResponse
(code) + Holder ->>+ AuthServer: TokenRequest
(code) + AuthServer ->>+ CloudAgent: NonceRequest
(issuer_state) + CloudAgent ->>- AuthServer: NonceResponse
(c_nonce) + AuthServer ->>- Holder: TokenResponse
(c_nonce) + Holder ->>+ CloudAgent: CredentialRequest
(proof) + CloudAgent ->>- Holder: CredentialResponse +``` + + +### Authorization Endpoint + +1. Authorization `scope` MUST be configured in the Authorization Server to the same value as in Credential Issuer Metadata +2. The endpoint MUST accept the parameter `issuer_state` in the [__AuthorizationRequest__](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#section-5.1.3-2.3) and recall this value in the subsequent call on the __TokenEndpoint__ + +### Token Endpoint + +1. When the holder makes a __TokenRequest__ to the __TokenEndpoint__, the __AuthorizationServer__ MUST recall the `issuer_state` parameter and make an HTTP call to the `/oid4vci/nonces` endpoint in the Cloud Agent using the following format. + +__NonceRequest__ + +``` +POST /oid4vci/nonces +Authorization: Bearer + +{ + "issuerState": "" +} +``` +Where `JWT_TOKEN` is a valid token issued by the __AuthorizationServer__. + +__NonceResponse__ + +``` +{ + "nonce": "", + "nonceExpiresIn": +} +``` + +2. The [__TokenResponse__](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#name-successful-token-response) must include `c_nonce` and `c_nonce_expires_in` parameter in the __TokenResponse__ + diff --git a/examples/.nickel/caddy.ncl b/examples/.nickel/caddy.ncl index 03aa4e0bd7..153ce9c879 100644 --- a/examples/.nickel/caddy.ncl +++ b/examples/.nickel/caddy.ncl @@ -25,7 +25,7 @@ in handle_path /didcomm* { reverse_proxy %{args.agent.host}:%{std.to_string args.agent.didcommPort} } - handle_path /agent* { + handle_path /cloud-agent* { reverse_proxy %{args.agent.host}:%{std.to_string args.agent.restPort} } handle_path /keycloak* { diff --git a/examples/.nickel/root.ncl b/examples/.nickel/root.ncl index 1276ba261b..5fa174acc2 100644 --- a/examples/.nickel/root.ncl +++ b/examples/.nickel/root.ncl @@ -21,7 +21,7 @@ in name = "issuer", port = 9980, realm = "students", - extraEnvs = { IDENTUS_URL = "http://caddy-issuer:8080/prism-agent" } + extraEnvs = { IDENTUS_URL = "http://caddy-issuer:8080/cloud-agent" } } ), diff --git a/examples/.nickel/stack.ncl b/examples/.nickel/stack.ncl index e722ae0551..323ec5d6ce 100644 --- a/examples/.nickel/stack.ncl +++ b/examples/.nickel/stack.ncl @@ -159,7 +159,7 @@ in agentDb = makeSharedDbConfig "agent", node = { host = "node" }, didcommServiceUrl = "http://%{hosts.caddy}:%{std.to_string args.port}/didcomm", - restServiceUrl = "http://%{hosts.caddy}:%{std.to_string args.port}/agent", + restServiceUrl = "http://%{hosts.caddy}:%{std.to_string args.port}/cloud-agent", apikeyEnabled = args.apikeyEnabled, } & ( diff --git a/examples/.nickel/versions.ncl b/examples/.nickel/versions.ncl index 5fd5259c61..7ff18ae327 100644 --- a/examples/.nickel/versions.ncl +++ b/examples/.nickel/versions.ncl @@ -1,6 +1,6 @@ { # identus - agent = "1.37.0", + agent = "1.38.0", node = "2.4.0", identusKeycloak = "0.2.0", # 3rd party diff --git a/examples/mt-keycloak-vault/README.md b/examples/mt-keycloak-vault/README.md index fc6d4a2ac2..207927dfcd 100644 --- a/examples/mt-keycloak-vault/README.md +++ b/examples/mt-keycloak-vault/README.md @@ -2,7 +2,7 @@ | Exposed Service | Description | |---------------------------------|--------------------------| -| `localhost:8080/prism-agent` | Multi-tenant Cloud Agent | +| `localhost:8080/cloudagent` | Multi-tenant Cloud Agent | | `localhost:8080/keycloak/admin` | Keycloak | | `localhost:8200` | Vault | diff --git a/examples/mt-keycloak-vault/compose.yaml b/examples/mt-keycloak-vault/compose.yaml index f86bdffcd3..6a313e1e19 100644 --- a/examples/mt-keycloak-vault/compose.yaml +++ b/examples/mt-keycloak-vault/compose.yaml @@ -5,7 +5,7 @@ configs: handle_path /didcomm* { reverse_proxy agent-default:8090 } - handle_path /agent* { + handle_path /cloud-agent* { reverse_proxy agent-default:8085 } handle_path /keycloak* { @@ -46,14 +46,14 @@ services: POLLUX_DB_PASSWORD: postgres POLLUX_DB_PORT: '5432' POLLUX_DB_USER: postgres - POLLUX_STATUS_LIST_REGISTRY_PUBLIC_URL: http://caddy-default:8080/agent + POLLUX_STATUS_LIST_REGISTRY_PUBLIC_URL: http://caddy-default:8080/cloud-agent PRISM_NODE_HOST: node PRISM_NODE_PORT: '50053' - REST_SERVICE_URL: http://caddy-default:8080/agent + REST_SERVICE_URL: http://caddy-default:8080/cloud-agent SECRET_STORAGE_BACKEND: vault VAULT_ADDR: http://vault-default:8200 VAULT_TOKEN: admin - image: ghcr.io/hyperledger/identus-cloud-agent:1.37.0 + image: ghcr.io/hyperledger/identus-cloud-agent:1.38.0 restart: always caddy-default: configs: diff --git a/examples/mt-keycloak-vault/hurl/01_create_users.hurl b/examples/mt-keycloak-vault/hurl/01_create_users.hurl index 2576c26564..0e5d13854a 100644 --- a/examples/mt-keycloak-vault/hurl/01_create_users.hurl +++ b/examples/mt-keycloak-vault/hurl/01_create_users.hurl @@ -66,7 +66,7 @@ HTTP 200 issuer_access_token: jsonpath "$.access_token" # Create Issuer wallet -POST {{ agent_url }}/agent/wallets +POST {{ agent_url }}/cloud-agent/wallets Authorization: Bearer {{ issuer_access_token }} { "name": "issuer-wallet" @@ -85,7 +85,7 @@ HTTP 200 holder_access_token: jsonpath "$.access_token" # Create Holder wallet -POST {{ agent_url }}/agent/wallets +POST {{ agent_url }}/cloud-agent/wallets Authorization: Bearer {{ holder_access_token }} { "name": "holder-wallet" @@ -104,7 +104,7 @@ HTTP 200 verifier_access_token: jsonpath "$.access_token" # Create Verifier wallet -POST {{ agent_url }}/agent/wallets +POST {{ agent_url }}/cloud-agent/wallets Authorization: Bearer {{ verifier_access_token }} { "name": "verifier-wallet" diff --git a/examples/mt-keycloak-vault/hurl/02_jwt_flow.hurl b/examples/mt-keycloak-vault/hurl/02_jwt_flow.hurl index 4f7ca2e697..6e0c8edcab 100644 --- a/examples/mt-keycloak-vault/hurl/02_jwt_flow.hurl +++ b/examples/mt-keycloak-vault/hurl/02_jwt_flow.hurl @@ -39,7 +39,7 @@ verifier_access_token: jsonpath "$.access_token" # Prerequisites ############################## # Issuer create DID -POST {{ agent_url }}/agent/did-registrar/dids +POST {{ agent_url }}/cloud-agent/did-registrar/dids Authorization: Bearer {{ issuer_access_token }} { "documentTemplate": { @@ -57,7 +57,7 @@ HTTP 201 issuer_did: jsonpath "$.longFormDid" # regex "(did:prism:[a-z0-9]+):.+$" # Holder create DID -POST {{ agent_url }}/agent/did-registrar/dids +POST {{ agent_url }}/cloud-agent/did-registrar/dids Authorization: Bearer {{ holder_access_token }} { "documentTemplate": { @@ -78,7 +78,7 @@ holder_did: jsonpath "$.longFormDid" regex "(did:prism:[a-z0-9]+):.+$" # Issuance Connection ############################## # Inviter create connection -POST {{ agent_url }}/agent/connections +POST {{ agent_url }}/cloud-agent/connections Authorization: Bearer {{ issuer_access_token }} { "label": "My Connection" @@ -89,7 +89,7 @@ raw_invitation: jsonpath "$.invitation.invitationUrl" regex ".*_oob=(.*)$" issuer_connection_id: jsonpath "$.connectionId" # Invitee accept connection -POST {{ agent_url }}/agent/connection-invitations +POST {{ agent_url }}/cloud-agent/connection-invitations Authorization: Bearer {{ holder_access_token }} { "invitation": "{{ raw_invitation }}" @@ -99,7 +99,7 @@ HTTP 200 holder_connection_id: jsonpath "$.connectionId" # Wait for inviter connection status -GET {{ agent_url }}/agent/connections/{{ issuer_connection_id }} +GET {{ agent_url }}/cloud-agent/connections/{{ issuer_connection_id }} Authorization: Bearer {{ issuer_access_token }} [Options] retry: -1 @@ -108,7 +108,7 @@ HTTP 200 jsonpath "$.state" == "ConnectionResponseSent" # Wait for invitee connection status -GET {{ agent_url }}/agent/connections/{{ holder_connection_id }} +GET {{ agent_url }}/cloud-agent/connections/{{ holder_connection_id }} Authorization: Bearer {{ holder_access_token }} [Options] retry: -1 @@ -120,7 +120,7 @@ jsonpath "$.state" == "ConnectionResponseReceived" # Issuance ############################## # Issuer create credential offer -POST {{ agent_url }}/agent/issue-credentials/credential-offers +POST {{ agent_url }}/cloud-agent/issue-credentials/credential-offers Authorization: Bearer {{ issuer_access_token }} { "claims": { @@ -138,7 +138,7 @@ issuer_cred_record_id: jsonpath "$.recordId" didcomm_issuing_thid: jsonpath "$.thid" # Holder wait for OfferReceived state -GET {{ agent_url }}/agent/issue-credentials/records +GET {{ agent_url }}/cloud-agent/issue-credentials/records Authorization: Bearer {{ holder_access_token }} [QueryStringParams] thid: {{ didcomm_issuing_thid }} @@ -151,7 +151,7 @@ jsonpath "$.contents[0].protocolState" == "OfferReceived" holder_cred_record_id: jsonpath "$.contents[0].recordId" # Holder accept a credential-offer -POST {{ agent_url }}/agent/issue-credentials/records/{{ holder_cred_record_id }}/accept-offer +POST {{ agent_url }}/cloud-agent/issue-credentials/records/{{ holder_cred_record_id }}/accept-offer Authorization: Bearer {{ holder_access_token }} { "subjectId": "{{ holder_did }}" @@ -159,7 +159,7 @@ Authorization: Bearer {{ holder_access_token }} HTTP 200 # Holder wait for CredentialReceived state -GET {{ agent_url }}/agent/issue-credentials/records/{{ holder_cred_record_id }} +GET {{ agent_url }}/cloud-agent/issue-credentials/records/{{ holder_cred_record_id }} Authorization: Bearer {{ holder_access_token }} [Options] retry: -1 @@ -168,7 +168,7 @@ HTTP 200 jsonpath "$.protocolState" == "CredentialReceived" # Issuer wait for CredentialSent state -GET {{ agent_url }}/agent/issue-credentials/records/{{ issuer_cred_record_id }} +GET {{ agent_url }}/cloud-agent/issue-credentials/records/{{ issuer_cred_record_id }} Authorization: Bearer {{ issuer_access_token }} [Options] retry: -1 @@ -180,7 +180,7 @@ jsonpath "$.protocolState" == "CredentialSent" # Presentation Connection ############################## # Inviter create connection -POST {{ agent_url }}/agent/connections +POST {{ agent_url }}/cloud-agent/connections Authorization: Bearer {{ verifier_access_token }} { "label": "My Connection" @@ -191,7 +191,7 @@ raw_invitation: jsonpath "$.invitation.invitationUrl" regex ".*_oob=(.*)$" verifier_connection_id: jsonpath "$.connectionId" # Invitee accept connection -POST {{ agent_url }}/agent/connection-invitations +POST {{ agent_url }}/cloud-agent/connection-invitations Authorization: Bearer {{ holder_access_token }} { "invitation": "{{ raw_invitation }}" @@ -201,7 +201,7 @@ HTTP 200 holder_connection_id: jsonpath "$.connectionId" # Wait for inviter connection status -GET {{ agent_url }}/agent/connections/{{ verifier_connection_id }} +GET {{ agent_url }}/cloud-agent/connections/{{ verifier_connection_id }} Authorization: Bearer {{ verifier_access_token }} [Options] retry: -1 @@ -210,7 +210,7 @@ HTTP 200 jsonpath "$.state" == "ConnectionResponseSent" # Wait for invitee connection status -GET {{ agent_url }}/agent/connections/{{ holder_connection_id }} +GET {{ agent_url }}/cloud-agent/connections/{{ holder_connection_id }} Authorization: Bearer {{ holder_access_token }} [Options] retry: -1 @@ -222,7 +222,7 @@ jsonpath "$.state" == "ConnectionResponseReceived" # Presentation ############################## # Verifier create presentation request -POST {{ agent_url }}/agent/present-proof/presentations +POST {{ agent_url }}/cloud-agent/present-proof/presentations Authorization: Bearer {{ verifier_access_token }} { "connectionId": "{{ verifier_connection_id }}", @@ -238,7 +238,7 @@ verifier_presentation_id: jsonpath "$.presentationId" didcomm_presentation_thid: jsonpath "$.thid" # Holder wait for RequestReceived state -GET {{ agent_url }}/agent/present-proof/presentations +GET {{ agent_url }}/cloud-agent/present-proof/presentations Authorization: Bearer {{ holder_access_token }} [QueryStringParams] thid: {{ didcomm_presentation_thid }} @@ -251,7 +251,7 @@ jsonpath "$.contents[0].status" == "RequestReceived" holder_presentation_id: jsonpath "$.contents[0].presentationId" # Holder accept presentation request -PATCH {{ agent_url }}/agent/present-proof/presentations/{{ holder_presentation_id }} +PATCH {{ agent_url }}/cloud-agent/present-proof/presentations/{{ holder_presentation_id }} Authorization: Bearer {{ holder_access_token }} { "action": "request-accept", @@ -260,7 +260,7 @@ Authorization: Bearer {{ holder_access_token }} HTTP 200 # Holder wait for PresentationSent state -GET {{ agent_url }}/agent/present-proof/presentations +GET {{ agent_url }}/cloud-agent/present-proof/presentations Authorization: Bearer {{ holder_access_token }} [QueryStringParams] thid: {{ didcomm_presentation_thid }} @@ -271,7 +271,7 @@ HTTP 200 jsonpath "$.contents[0].status" == "PresentationSent" # Verfiier wait for PresentationVerified state -GET {{ agent_url }}/agent/present-proof/presentations +GET {{ agent_url }}/cloud-agent/present-proof/presentations Authorization: Bearer {{ verifier_access_token }} [QueryStringParams] thid: {{ didcomm_presentation_thid }} diff --git a/examples/mt-keycloak/README.md b/examples/mt-keycloak/README.md index 2e1d454908..373b8a4bfa 100644 --- a/examples/mt-keycloak/README.md +++ b/examples/mt-keycloak/README.md @@ -2,7 +2,7 @@ | Exposed Service | Description | |---------------------------------|--------------------------| -| `localhost:8080/prism-agent` | Multi-tenant Cloud Agent | +| `localhost:8080/cloud-agent` | Multi-tenant Cloud Agent | | `localhost:8080/keycloak/admin` | Keycloak | __Keycloak__ diff --git a/examples/mt-keycloak/compose.yaml b/examples/mt-keycloak/compose.yaml index 8672828e72..ea2b55a150 100644 --- a/examples/mt-keycloak/compose.yaml +++ b/examples/mt-keycloak/compose.yaml @@ -5,7 +5,7 @@ configs: handle_path /didcomm* { reverse_proxy agent-default:8090 } - handle_path /agent* { + handle_path /cloud-agent* { reverse_proxy agent-default:8085 } handle_path /keycloak* { @@ -46,12 +46,12 @@ services: POLLUX_DB_PASSWORD: postgres POLLUX_DB_PORT: '5432' POLLUX_DB_USER: postgres - POLLUX_STATUS_LIST_REGISTRY_PUBLIC_URL: http://caddy-default:8080/agent + POLLUX_STATUS_LIST_REGISTRY_PUBLIC_URL: http://caddy-default:8080/cloud-agent PRISM_NODE_HOST: node PRISM_NODE_PORT: '50053' - REST_SERVICE_URL: http://caddy-default:8080/agent + REST_SERVICE_URL: http://caddy-default:8080/cloud-agent SECRET_STORAGE_BACKEND: postgres - image: ghcr.io/hyperledger/identus-cloud-agent:1.37.0 + image: ghcr.io/hyperledger/identus-cloud-agent:1.38.0 restart: always caddy-default: configs: diff --git a/examples/mt-keycloak/hurl/01_create_users.hurl b/examples/mt-keycloak/hurl/01_create_users.hurl index 2576c26564..0e5d13854a 100644 --- a/examples/mt-keycloak/hurl/01_create_users.hurl +++ b/examples/mt-keycloak/hurl/01_create_users.hurl @@ -66,7 +66,7 @@ HTTP 200 issuer_access_token: jsonpath "$.access_token" # Create Issuer wallet -POST {{ agent_url }}/agent/wallets +POST {{ agent_url }}/cloud-agent/wallets Authorization: Bearer {{ issuer_access_token }} { "name": "issuer-wallet" @@ -85,7 +85,7 @@ HTTP 200 holder_access_token: jsonpath "$.access_token" # Create Holder wallet -POST {{ agent_url }}/agent/wallets +POST {{ agent_url }}/cloud-agent/wallets Authorization: Bearer {{ holder_access_token }} { "name": "holder-wallet" @@ -104,7 +104,7 @@ HTTP 200 verifier_access_token: jsonpath "$.access_token" # Create Verifier wallet -POST {{ agent_url }}/agent/wallets +POST {{ agent_url }}/cloud-agent/wallets Authorization: Bearer {{ verifier_access_token }} { "name": "verifier-wallet" diff --git a/examples/mt-keycloak/hurl/02_jwt_flow.hurl b/examples/mt-keycloak/hurl/02_jwt_flow.hurl index 4565f4e877..41999eeb87 100644 --- a/examples/mt-keycloak/hurl/02_jwt_flow.hurl +++ b/examples/mt-keycloak/hurl/02_jwt_flow.hurl @@ -39,7 +39,7 @@ verifier_access_token: jsonpath "$.access_token" # Prerequisites ############################## # Issuer create DID -POST {{ agent_url }}/agent/did-registrar/dids +POST {{ agent_url }}/cloud-agent/did-registrar/dids Authorization: Bearer {{ issuer_access_token }} { "documentTemplate": { @@ -57,12 +57,12 @@ HTTP 201 issuer_did: jsonpath "$.longFormDid" regex "(did:prism:[a-z0-9]+):.+$" # Issuer publish DID -POST {{ agent_url }}/agent/did-registrar/dids/{{ issuer_did }}/publications +POST {{ agent_url }}/cloud-agent/did-registrar/dids/{{ issuer_did }}/publications Authorization: Bearer {{ issuer_access_token }} HTTP 202 # Issuer wait for DID to be published -GET {{ agent_url }}/agent/did-registrar/dids/{{ issuer_did }} +GET {{ agent_url }}/cloud-agent/did-registrar/dids/{{ issuer_did }} Authorization: Bearer {{ issuer_access_token }} [Options] retry: -1 @@ -71,7 +71,7 @@ HTTP 200 jsonpath "$.status" == "PUBLISHED" # Holder create DID -POST {{ agent_url }}/agent/did-registrar/dids +POST {{ agent_url }}/cloud-agent/did-registrar/dids Authorization: Bearer {{ holder_access_token }} { "documentTemplate": { @@ -92,7 +92,7 @@ holder_did: jsonpath "$.longFormDid" # Issuance Connection ############################## # Inviter create connection -POST {{ agent_url }}/agent/connections +POST {{ agent_url }}/cloud-agent/connections Authorization: Bearer {{ issuer_access_token }} { "label": "My Connection" @@ -103,7 +103,7 @@ raw_invitation: jsonpath "$.invitation.invitationUrl" regex ".*_oob=(.*)$" issuer_connection_id: jsonpath "$.connectionId" # Invitee accept connection -POST {{ agent_url }}/agent/connection-invitations +POST {{ agent_url }}/cloud-agent/connection-invitations Authorization: Bearer {{ holder_access_token }} { "invitation": "{{ raw_invitation }}" @@ -113,7 +113,7 @@ HTTP 200 holder_connection_id: jsonpath "$.connectionId" # Wait for inviter connection status -GET {{ agent_url }}/agent/connections/{{ issuer_connection_id }} +GET {{ agent_url }}/cloud-agent/connections/{{ issuer_connection_id }} Authorization: Bearer {{ issuer_access_token }} [Options] retry: -1 @@ -122,7 +122,7 @@ HTTP 200 jsonpath "$.state" == "ConnectionResponseSent" # Wait for invitee connection status -GET {{ agent_url }}/agent/connections/{{ holder_connection_id }} +GET {{ agent_url }}/cloud-agent/connections/{{ holder_connection_id }} Authorization: Bearer {{ holder_access_token }} [Options] retry: -1 @@ -134,7 +134,7 @@ jsonpath "$.state" == "ConnectionResponseReceived" # Issuance ############################## # Issuer create credential offer -POST {{ agent_url }}/agent/issue-credentials/credential-offers +POST {{ agent_url }}/cloud-agent/issue-credentials/credential-offers Authorization: Bearer {{ issuer_access_token }} { "claims": { @@ -152,7 +152,7 @@ issuer_cred_record_id: jsonpath "$.recordId" didcomm_issuing_thid: jsonpath "$.thid" # Holder wait for OfferReceived state -GET {{ agent_url }}/agent/issue-credentials/records +GET {{ agent_url }}/cloud-agent/issue-credentials/records Authorization: Bearer {{ holder_access_token }} [QueryStringParams] thid: {{ didcomm_issuing_thid }} @@ -165,7 +165,7 @@ jsonpath "$.contents[0].protocolState" == "OfferReceived" holder_cred_record_id: jsonpath "$.contents[0].recordId" # Holder accept a credential-offer -POST {{ agent_url }}/agent/issue-credentials/records/{{ holder_cred_record_id }}/accept-offer +POST {{ agent_url }}/cloud-agent/issue-credentials/records/{{ holder_cred_record_id }}/accept-offer Authorization: Bearer {{ holder_access_token }} { "subjectId": "{{ holder_did }}" @@ -173,7 +173,7 @@ Authorization: Bearer {{ holder_access_token }} HTTP 200 # Holder wait for CredentialReceived state -GET {{ agent_url }}/agent/issue-credentials/records/{{ holder_cred_record_id }} +GET {{ agent_url }}/cloud-agent/issue-credentials/records/{{ holder_cred_record_id }} Authorization: Bearer {{ holder_access_token }} [Options] retry: -1 @@ -182,7 +182,7 @@ HTTP 200 jsonpath "$.protocolState" == "CredentialReceived" # Issuer wait for CredentialSent state -GET {{ agent_url }}/agent/issue-credentials/records/{{ issuer_cred_record_id }} +GET {{ agent_url }}/cloud-agent/issue-credentials/records/{{ issuer_cred_record_id }} Authorization: Bearer {{ issuer_access_token }} [Options] retry: -1 @@ -194,7 +194,7 @@ jsonpath "$.protocolState" == "CredentialSent" # Presentation Connection ############################## # Inviter create connection -POST {{ agent_url }}/agent/connections +POST {{ agent_url }}/cloud-agent/connections Authorization: Bearer {{ verifier_access_token }} { "label": "My Connection" @@ -205,7 +205,7 @@ raw_invitation: jsonpath "$.invitation.invitationUrl" regex ".*_oob=(.*)$" verifier_connection_id: jsonpath "$.connectionId" # Invitee accept connection -POST {{ agent_url }}/agent/connection-invitations +POST {{ agent_url }}/cloud-agent/connection-invitations Authorization: Bearer {{ holder_access_token }} { "invitation": "{{ raw_invitation }}" @@ -215,7 +215,7 @@ HTTP 200 holder_connection_id: jsonpath "$.connectionId" # Wait for inviter connection status -GET {{ agent_url }}/agent/connections/{{ verifier_connection_id }} +GET {{ agent_url }}/cloud-agent/connections/{{ verifier_connection_id }} Authorization: Bearer {{ verifier_access_token }} [Options] retry: -1 @@ -224,7 +224,7 @@ HTTP 200 jsonpath "$.state" == "ConnectionResponseSent" # Wait for invitee connection status -GET {{ agent_url }}/agent/connections/{{ holder_connection_id }} +GET {{ agent_url }}/cloud-agent/connections/{{ holder_connection_id }} Authorization: Bearer {{ holder_access_token }} [Options] retry: -1 @@ -236,7 +236,7 @@ jsonpath "$.state" == "ConnectionResponseReceived" # Presentation ############################## # Verifier create presentation request -POST {{ agent_url }}/agent/present-proof/presentations +POST {{ agent_url }}/cloud-agent/present-proof/presentations Authorization: Bearer {{ verifier_access_token }} { "connectionId": "{{ verifier_connection_id }}", @@ -252,7 +252,7 @@ verifier_presentation_id: jsonpath "$.presentationId" didcomm_presentation_thid: jsonpath "$.thid" # Holder wait for RequestReceived state -GET {{ agent_url }}/agent/present-proof/presentations +GET {{ agent_url }}/cloud-agent/present-proof/presentations Authorization: Bearer {{ holder_access_token }} [QueryStringParams] thid: {{ didcomm_presentation_thid }} @@ -265,7 +265,7 @@ jsonpath "$.contents[0].status" == "RequestReceived" holder_presentation_id: jsonpath "$.contents[0].presentationId" # Holder accept presentation request -PATCH {{ agent_url }}/agent/present-proof/presentations/{{ holder_presentation_id }} +PATCH {{ agent_url }}/cloud-agent/present-proof/presentations/{{ holder_presentation_id }} Authorization: Bearer {{ holder_access_token }} { "action": "request-accept", @@ -274,7 +274,7 @@ Authorization: Bearer {{ holder_access_token }} HTTP 200 # Holder wait for PresentationSent state -GET {{ agent_url }}/agent/present-proof/presentations +GET {{ agent_url }}/cloud-agent/present-proof/presentations Authorization: Bearer {{ holder_access_token }} [QueryStringParams] thid: {{ didcomm_presentation_thid }} @@ -285,7 +285,7 @@ HTTP 200 jsonpath "$.contents[0].status" == "PresentationSent" # Verfiier wait for PresentationVerified state -GET {{ agent_url }}/agent/present-proof/presentations +GET {{ agent_url }}/cloud-agent/present-proof/presentations Authorization: Bearer {{ verifier_access_token }} [QueryStringParams] thid: {{ didcomm_presentation_thid }} diff --git a/examples/mt/README.md b/examples/mt/README.md index 7cb3752063..030af3b4bd 100644 --- a/examples/mt/README.md +++ b/examples/mt/README.md @@ -2,4 +2,4 @@ | Exposed Service | Description | |------------------------------|--------------------------| -| `localhost:8080/prism-agent` | Multi-tenant Cloud Agent | +| `localhost:8080/cloud-agent` | Multi-tenant Cloud Agent | diff --git a/examples/mt/compose.yaml b/examples/mt/compose.yaml index bc1858a68f..0b355b8049 100644 --- a/examples/mt/compose.yaml +++ b/examples/mt/compose.yaml @@ -5,7 +5,7 @@ configs: handle_path /didcomm* { reverse_proxy agent-default:8090 } - handle_path /agent* { + handle_path /cloud-agent* { reverse_proxy agent-default:8085 } handle_path /keycloak* { @@ -39,12 +39,12 @@ services: POLLUX_DB_PASSWORD: postgres POLLUX_DB_PORT: '5432' POLLUX_DB_USER: postgres - POLLUX_STATUS_LIST_REGISTRY_PUBLIC_URL: http://caddy-default:8080/agent + POLLUX_STATUS_LIST_REGISTRY_PUBLIC_URL: http://caddy-default:8080/cloud-agent PRISM_NODE_HOST: node PRISM_NODE_PORT: '50053' - REST_SERVICE_URL: http://caddy-default:8080/agent + REST_SERVICE_URL: http://caddy-default:8080/cloud-agent SECRET_STORAGE_BACKEND: postgres - image: ghcr.io/hyperledger/identus-cloud-agent:1.37.0 + image: ghcr.io/hyperledger/identus-cloud-agent:1.38.0 restart: always caddy-default: configs: diff --git a/examples/st-multi/README.me b/examples/st-multi/README.me index 9483ed9d44..da8c69f181 100644 --- a/examples/st-multi/README.me +++ b/examples/st-multi/README.me @@ -1,7 +1,7 @@ ## Configuration -|Exposed Service|Description| -|-|-| -|`localhost:8080/prism-agent`|Single-tenant Cloud Agent#1 (issuer)| -|`localhost:8081/prism-agent`|Single-tenant Cloud Agent#2 (holder)| -|`localhost:8082/prism-agent`|Single-tenant Cloud Agent#3 (verifier)| +|Exposed Service |Description | +|----------------------------|--------------------------------------| +|`localhost:8080/cloud-agent`|Single-tenant Cloud Agent#1 (issuer) | +|`localhost:8081/cloud-agent`|Single-tenant Cloud Agent#2 (holder) | +|`localhost:8082/cloud-agent`|Single-tenant Cloud Agent#3 (verifier)| diff --git a/examples/st-multi/compose.yaml b/examples/st-multi/compose.yaml index 54f501fce6..88771d576a 100644 --- a/examples/st-multi/compose.yaml +++ b/examples/st-multi/compose.yaml @@ -5,7 +5,7 @@ configs: handle_path /didcomm* { reverse_proxy agent-holder:8090 } - handle_path /agent* { + handle_path /cloud-agent* { reverse_proxy agent-holder:8085 } handle_path /keycloak* { @@ -21,7 +21,7 @@ configs: handle_path /didcomm* { reverse_proxy agent-issuer:8090 } - handle_path /agent* { + handle_path /cloud-agent* { reverse_proxy agent-issuer:8085 } handle_path /keycloak* { @@ -37,7 +37,7 @@ configs: handle_path /didcomm* { reverse_proxy agent-verifier:8090 } - handle_path /agent* { + handle_path /cloud-agent* { reverse_proxy agent-verifier:8085 } handle_path /keycloak* { @@ -71,12 +71,12 @@ services: POLLUX_DB_PASSWORD: postgres POLLUX_DB_PORT: '5432' POLLUX_DB_USER: postgres - POLLUX_STATUS_LIST_REGISTRY_PUBLIC_URL: http://caddy-holder:8081/agent + POLLUX_STATUS_LIST_REGISTRY_PUBLIC_URL: http://caddy-holder:8081/cloud-agent PRISM_NODE_HOST: node PRISM_NODE_PORT: '50053' - REST_SERVICE_URL: http://caddy-holder:8081/agent + REST_SERVICE_URL: http://caddy-holder:8081/cloud-agent SECRET_STORAGE_BACKEND: postgres - image: ghcr.io/hyperledger/identus-cloud-agent:1.37.0 + image: ghcr.io/hyperledger/identus-cloud-agent:1.38.0 restart: always agent-issuer: depends_on: @@ -101,12 +101,12 @@ services: POLLUX_DB_PASSWORD: postgres POLLUX_DB_PORT: '5432' POLLUX_DB_USER: postgres - POLLUX_STATUS_LIST_REGISTRY_PUBLIC_URL: http://caddy-issuer:8080/agent + POLLUX_STATUS_LIST_REGISTRY_PUBLIC_URL: http://caddy-issuer:8080/cloud-agent PRISM_NODE_HOST: node PRISM_NODE_PORT: '50053' - REST_SERVICE_URL: http://caddy-issuer:8080/agent + REST_SERVICE_URL: http://caddy-issuer:8080/cloud-agent SECRET_STORAGE_BACKEND: postgres - image: ghcr.io/hyperledger/identus-cloud-agent:1.37.0 + image: ghcr.io/hyperledger/identus-cloud-agent:1.38.0 restart: always agent-verifier: depends_on: @@ -131,12 +131,12 @@ services: POLLUX_DB_PASSWORD: postgres POLLUX_DB_PORT: '5432' POLLUX_DB_USER: postgres - POLLUX_STATUS_LIST_REGISTRY_PUBLIC_URL: http://caddy-verifier:8082/agent + POLLUX_STATUS_LIST_REGISTRY_PUBLIC_URL: http://caddy-verifier:8082/cloud-agent PRISM_NODE_HOST: node PRISM_NODE_PORT: '50053' - REST_SERVICE_URL: http://caddy-verifier:8082/agent + REST_SERVICE_URL: http://caddy-verifier:8082/cloud-agent SECRET_STORAGE_BACKEND: postgres - image: ghcr.io/hyperledger/identus-cloud-agent:1.37.0 + image: ghcr.io/hyperledger/identus-cloud-agent:1.38.0 restart: always caddy-holder: configs: diff --git a/examples/st-multi/hurl/01_jwt_flow.hurl b/examples/st-multi/hurl/01_jwt_flow.hurl index 7e5e1b9823..4752a1adb1 100644 --- a/examples/st-multi/hurl/01_jwt_flow.hurl +++ b/examples/st-multi/hurl/01_jwt_flow.hurl @@ -2,7 +2,7 @@ # Prerequisites ############################## # Issuer create DID -POST {{ issuer_url }}/agent/did-registrar/dids +POST {{ issuer_url }}/cloud-agent/did-registrar/dids { "documentTemplate": { "publicKeys": [ @@ -19,11 +19,11 @@ HTTP 201 issuer_did: jsonpath "$.longFormDid" regex "(did:prism:[a-z0-9]+):.+$" # Issuer publish DID -POST {{ issuer_url }}/agent/did-registrar/dids/{{ issuer_did }}/publications +POST {{ issuer_url }}/cloud-agent/did-registrar/dids/{{ issuer_did }}/publications HTTP 202 # Issuer wait for DID to be published -GET {{ issuer_url }}/agent/did-registrar/dids/{{ issuer_did }} +GET {{ issuer_url }}/cloud-agent/did-registrar/dids/{{ issuer_did }} [Options] retry: -1 HTTP 200 @@ -31,7 +31,7 @@ HTTP 200 jsonpath "$.status" == "PUBLISHED" # Holder create DID -POST {{ holder_url }}/agent/did-registrar/dids +POST {{ holder_url }}/cloud-agent/did-registrar/dids { "documentTemplate": { "publicKeys": [ @@ -51,7 +51,7 @@ holder_did: jsonpath "$.longFormDid" # Issuance Connection ############################## # Inviter create connection -POST {{ issuer_url }}/agent/connections +POST {{ issuer_url }}/cloud-agent/connections { "label": "My Connection" } @@ -61,7 +61,7 @@ raw_invitation: jsonpath "$.invitation.invitationUrl" regex ".*_oob=(.*)$" issuer_connection_id: jsonpath "$.connectionId" # Invitee accept connection -POST {{ holder_url }}/agent/connection-invitations +POST {{ holder_url }}/cloud-agent/connection-invitations { "invitation": "{{ raw_invitation }}" } @@ -70,7 +70,7 @@ HTTP 200 holder_connection_id: jsonpath "$.connectionId" # Wait for inviter connection status -GET {{ issuer_url }}/agent/connections/{{ issuer_connection_id }} +GET {{ issuer_url }}/cloud-agent/connections/{{ issuer_connection_id }} [Options] retry: -1 HTTP 200 @@ -78,7 +78,7 @@ HTTP 200 jsonpath "$.state" == "ConnectionResponseSent" # Wait for invitee connection status -GET {{ holder_url }}/agent/connections/{{ holder_connection_id }} +GET {{ holder_url }}/cloud-agent/connections/{{ holder_connection_id }} [Options] retry: -1 HTTP 200 @@ -89,7 +89,7 @@ jsonpath "$.state" == "ConnectionResponseReceived" # Issuance ############################## # Issuer create credential offer -POST {{ issuer_url }}/agent/issue-credentials/credential-offers +POST {{ issuer_url }}/cloud-agent/issue-credentials/credential-offers { "claims": { "emailAddress": "alice@wonderland.com", @@ -106,7 +106,7 @@ issuer_cred_record_id: jsonpath "$.recordId" didcomm_issuing_thid: jsonpath "$.thid" # Holder wait for OfferReceived state -GET {{ holder_url }}/agent/issue-credentials/records +GET {{ holder_url }}/cloud-agent/issue-credentials/records [QueryStringParams] thid: {{ didcomm_issuing_thid }} [Options] @@ -118,14 +118,14 @@ jsonpath "$.contents[0].protocolState" == "OfferReceived" holder_cred_record_id: jsonpath "$.contents[0].recordId" # Holder accept a credential-offer -POST {{ holder_url }}/agent/issue-credentials/records/{{ holder_cred_record_id }}/accept-offer +POST {{ holder_url }}/cloud-agent/issue-credentials/records/{{ holder_cred_record_id }}/accept-offer { "subjectId": "{{ holder_did }}" } HTTP 200 # Holder wait for CredentialReceived state -GET {{ holder_url }}/agent/issue-credentials/records/{{ holder_cred_record_id }} +GET {{ holder_url }}/cloud-agent/issue-credentials/records/{{ holder_cred_record_id }} [Options] retry: -1 HTTP 200 @@ -133,7 +133,7 @@ HTTP 200 jsonpath "$.protocolState" == "CredentialReceived" # Issuer wait for CredentialSent state -GET {{ issuer_url }}/agent/issue-credentials/records/{{ issuer_cred_record_id }} +GET {{ issuer_url }}/cloud-agent/issue-credentials/records/{{ issuer_cred_record_id }} [Options] retry: -1 HTTP 200 @@ -144,7 +144,7 @@ jsonpath "$.protocolState" == "CredentialSent" # Presentation Connection ############################## # Inviter create connection -POST {{ verifier_url }}/agent/connections +POST {{ verifier_url }}/cloud-agent/connections { "label": "My Connection" } @@ -154,7 +154,7 @@ raw_invitation: jsonpath "$.invitation.invitationUrl" regex ".*_oob=(.*)$" verifier_connection_id: jsonpath "$.connectionId" # Invitee accept connection -POST {{ holder_url }}/agent/connection-invitations +POST {{ holder_url }}/cloud-agent/connection-invitations { "invitation": "{{ raw_invitation }}" } @@ -163,7 +163,7 @@ HTTP 200 holder_connection_id: jsonpath "$.connectionId" # Wait for inviter connection status -GET {{ verifier_url }}/agent/connections/{{ verifier_connection_id }} +GET {{ verifier_url }}/cloud-agent/connections/{{ verifier_connection_id }} [Options] retry: -1 HTTP 200 @@ -171,7 +171,7 @@ HTTP 200 jsonpath "$.state" == "ConnectionResponseSent" # Wait for invitee connection status -GET {{ holder_url }}/agent/connections/{{ holder_connection_id }} +GET {{ holder_url }}/cloud-agent/connections/{{ holder_connection_id }} [Options] retry: -1 HTTP 200 @@ -182,7 +182,7 @@ jsonpath "$.state" == "ConnectionResponseReceived" # Presentation ############################## # Verifier create presentation request -POST {{ verifier_url }}/agent/present-proof/presentations +POST {{ verifier_url }}/cloud-agent/present-proof/presentations { "connectionId": "{{ verifier_connection_id }}", "proofs":[], @@ -197,7 +197,7 @@ verifier_presentation_id: jsonpath "$.presentationId" didcomm_presentation_thid: jsonpath "$.thid" # Holder wait for RequestReceived state -GET {{ holder_url }}/agent/present-proof/presentations +GET {{ holder_url }}/cloud-agent/present-proof/presentations [QueryStringParams] thid: {{ didcomm_presentation_thid }} [Options] @@ -209,7 +209,7 @@ jsonpath "$.contents[0].status" == "RequestReceived" holder_presentation_id: jsonpath "$.contents[0].presentationId" # Holder accept presentation request -PATCH {{ holder_url }}/agent/present-proof/presentations/{{ holder_presentation_id }} +PATCH {{ holder_url }}/cloud-agent/present-proof/presentations/{{ holder_presentation_id }} { "action": "request-accept", "proofId": ["{{ holder_cred_record_id }}"] @@ -217,7 +217,7 @@ PATCH {{ holder_url }}/agent/present-proof/presentations/{{ holder_presentation_ HTTP 200 # Holder wait for PresentationSent state -GET {{ holder_url }}/agent/present-proof/presentations +GET {{ holder_url }}/cloud-agent/present-proof/presentations [QueryStringParams] thid: {{ didcomm_presentation_thid }} [Options] @@ -227,7 +227,7 @@ HTTP 200 jsonpath "$.contents[0].status" == "PresentationSent" # Verfiier wait for PresentationVerified state -GET {{ verifier_url }}/agent/present-proof/presentations +GET {{ verifier_url }}/cloud-agent/present-proof/presentations [QueryStringParams] thid: {{ didcomm_presentation_thid }} [Options] diff --git a/examples/st-oid4vci/README.md b/examples/st-oid4vci/README.md index 85b357d0a3..956da6a0db 100644 --- a/examples/st-oid4vci/README.md +++ b/examples/st-oid4vci/README.md @@ -3,24 +3,6 @@ ## Prerequisites - Docker installed v2.24.0 or later -- Python 3 with the following packages installed - - [requests](https://pypi.org/project/requests/) - - [pyjwt](https://pyjwt.readthedocs.io/en/stable/) - - [cryptography](https://cryptography.io/en/latest/) -- Virtual environment (optional) - -Example of the script to install the required packages in a virtual environment: -```shell -python -m venv {path-to-the-project-dir}/identus-cloud-agent/examples/st-oid4vci/python-env -source {path-to-the-project-dir}/identus-cloud-agent/examples/st-oid4vci/python-env/bin/activate -pip install requests pyjwt cryptography -``` - -- the latest Cloud Agent image is built and available in the local Docker registry - -```shell -sbt docker:publishLocal -``` ### 1. Spin up the agent stack with pre-configured Keycloak @@ -32,10 +14,16 @@ The Keycloak UI is available at `http://localhost:9980` and the admin username i ### 2. Run the issuance demo script +Build the demo application and run it using + ```bash -python demo.py +docker build -t identus-oid4vci-demo:latest ./demo +docker run --network -it identus-oid4vci-demo:latest ``` +where `NETWORK_NAME` is the docker-compose network name from agent stack. +By default, this value should be `st-oid4vci_default`. + - 2.1 Follow the instructions in the terminal. The holder will then be asked to log in via a browser - 2.2 Enter the username `alice` and password `1234` to log in - 2.3 Grant access for the scopes displayed on the consent UI diff --git a/examples/st-oid4vci/compose.yaml b/examples/st-oid4vci/compose.yaml index 5de842daa2..adc542a455 100644 --- a/examples/st-oid4vci/compose.yaml +++ b/examples/st-oid4vci/compose.yaml @@ -5,7 +5,7 @@ configs: handle_path /didcomm* { reverse_proxy agent-issuer:8090 } - handle_path /agent* { + handle_path /cloud-agent* { reverse_proxy agent-issuer:8085 } handle_path /keycloak* { @@ -39,12 +39,12 @@ services: POLLUX_DB_PASSWORD: postgres POLLUX_DB_PORT: '5432' POLLUX_DB_USER: postgres - POLLUX_STATUS_LIST_REGISTRY_PUBLIC_URL: http://caddy-issuer:8080/agent + POLLUX_STATUS_LIST_REGISTRY_PUBLIC_URL: http://caddy-issuer:8080/cloud-agent PRISM_NODE_HOST: node PRISM_NODE_PORT: '50053' - REST_SERVICE_URL: http://caddy-issuer:8080/agent + REST_SERVICE_URL: http://caddy-issuer:8080/cloud-agent SECRET_STORAGE_BACKEND: postgres - image: ghcr.io/hyperledger/identus-cloud-agent:1.37.0 + image: ghcr.io/hyperledger/identus-cloud-agent:1.38.0 restart: always caddy-issuer: configs: @@ -102,7 +102,7 @@ services: - --hostname-url=http://localhost:9980 - --hostname-admin-url=http://localhost:9980 environment: - IDENTUS_URL: http://caddy-issuer:8080/prism-agent + IDENTUS_URL: http://caddy-issuer:8080/cloud-agent KEYCLOAK_ADMIN: admin KEYCLOAK_ADMIN_PASSWORD: admin image: ghcr.io/hyperledger/identus-keycloak-plugins:0.2.0 diff --git a/examples/st-oid4vci/demo/Dockerfile b/examples/st-oid4vci/demo/Dockerfile new file mode 100644 index 0000000000..b68166517b --- /dev/null +++ b/examples/st-oid4vci/demo/Dockerfile @@ -0,0 +1,6 @@ +FROM python:3.12 +WORKDIR /workspace +COPY requirements.txt /workspace/requirements.txt +RUN pip install -r requirements.txt +COPY . /workspace +CMD ["python", "main.py"] diff --git a/examples/st-oid4vci/demo.py b/examples/st-oid4vci/demo/main.py similarity index 90% rename from examples/st-oid4vci/demo.py rename to examples/st-oid4vci/demo/main.py index 0dd12acf4d..b48239a161 100755 --- a/examples/st-oid4vci/demo.py +++ b/examples/st-oid4vci/demo/main.py @@ -6,14 +6,14 @@ import requests from cryptography.hazmat.primitives.asymmetric import ec -MOCKSERVER_URL = "http://localhost:7777" +MOCKSERVER_URL = "http://mockserver:1080" LOGIN_REDIRECT_URL = "http://localhost:7777/cb" -AGENT_URL = "http://localhost:8080/prism-agent" +AGENT_URL = "http://caddy-issuer:8080/cloud-agent" CREDENTIAL_ISSUER = None CREDENTIAL_ISSUER_DID = None CREDENTIAL_CONFIGURATION_ID = "UniversityDegreeCredential" -AUTHORIZATION_SERVER = "http://localhost:9980/realms/students" +AUTHORIZATION_SERVER = "http://external-keycloak-issuer:8080/realms/students" ALICE_CLIENT_ID = "alice-wallet" @@ -24,10 +24,11 @@ def prepare_mock_server(): - # reset mock server - requests.put(f"{MOCKSERVER_URL}/mockserver/reset") + """ + Prepare mock server for authorization redirect from front-end channel + """ - # mock wallet authorization callback endpoint + requests.put(f"{MOCKSERVER_URL}/mockserver/reset") requests.put( f"{MOCKSERVER_URL}/mockserver/expectation", json={ @@ -41,7 +42,16 @@ def prepare_mock_server(): def prepare_issuer(): - # prepare issuging DID + """ + Prepare an oid4vci issuer + 1. Create issuing DID + 2. Publish issuing DID + 3. Create credential schema + 4. Create oid4vci issuer + 5. Create oid4vci credential configuration from schema + """ + + # 1. Create issuing DID dids = requests.get(f"{AGENT_URL}/did-registrar/dids").json()["contents"] if len(dids) == 0: requests.post( @@ -55,6 +65,7 @@ def prepare_issuer(): ) dids = requests.get(f"{AGENT_URL}/did-registrar/dids").json()["contents"] + # 2. Publish issuing DID issuer_did = dids[0] while issuer_did["status"] != "PUBLISHED": time.sleep(2) @@ -72,7 +83,7 @@ def prepare_issuer(): global CREDENTIAL_ISSUER_DID CREDENTIAL_ISSUER_DID = canonical_did - # prepare schema + # 3. Create credential schema schema = requests.post( f"{AGENT_URL}/schema-registry/schemas", json={ @@ -97,7 +108,7 @@ def prepare_issuer(): ).json() schema_guid = schema["guid"] - # prepare issuer + # 4. Create oid4vci issuer credential_issuer = requests.post( f"{AGENT_URL}/oid4vci/issuers", json={ @@ -112,14 +123,13 @@ def prepare_issuer(): global CREDENTIAL_ISSUER CREDENTIAL_ISSUER = f"{AGENT_URL}/oid4vci/issuers/{issuer_id}" - # prepare credential configuration + # 5. Create oid4vci credential configuration from schema cred_config = requests.post( f"{CREDENTIAL_ISSUER}/credential-configurations", json={ "configurationId": CREDENTIAL_CONFIGURATION_ID, "format": "jwt_vc_json", - # TODO: align docker host URL - "schemaId": f"http://localhost:8085/schema-registry/schemas/{schema_guid}/schema", + "schemaId": f"{AGENT_URL}/schema-registry/schemas/{schema_guid}/schema", }, ).json() @@ -137,19 +147,8 @@ def issuer_create_credential_offer(claims): def holder_get_issuer_metadata(credential_issuer: str): - # FIXME: override this just to make url reachable from host - def override_host(url): - return url.replace("http://caddy-issuer:8080/prism-agent", AGENT_URL) - - metadata_url = override_host( - f"{credential_issuer}/.well-known/openid-credential-issuer" - ) + metadata_url = f"{credential_issuer}/.well-known/openid-credential-issuer" response = requests.get(metadata_url).json() - response["credential_endpoint"] = override_host(response["credential_endpoint"]) - response["credential_issuer"] = override_host(response["credential_issuer"]) - response["authorization_servers"] = [ - AUTHORIZATION_SERVER for s in response["authorization_servers"] - ] return response @@ -157,7 +156,6 @@ def holder_get_issuer_as_metadata(authorization_server: str): metadata_url = f"{authorization_server}/.well-known/openid-configuration" response = requests.get(metadata_url) metadata = response.json() - print(f"Metadata: {metadata}") return metadata @@ -293,6 +291,7 @@ def holder_get_credential(credential_endpoint: str, token_response): issuer_as_token_endpoint = issuer_as_metadata["token_endpoint"] issuer_as_authorization_endpoint = issuer_as_metadata["authorization_endpoint"] print("\n::::: Issuer Authorization Server Metadata :::::") + print(json.dumps(issuer_as_metadata, indent=2)) print(f"issuer_as_auth_endpoint: {issuer_as_authorization_endpoint}") print(f"issuer_as_token_endpoint: {issuer_as_token_endpoint}") input("\nEnter to continue ...") diff --git a/examples/st-oid4vci/demo/requirements.txt b/examples/st-oid4vci/demo/requirements.txt new file mode 100644 index 0000000000..791e544886 --- /dev/null +++ b/examples/st-oid4vci/demo/requirements.txt @@ -0,0 +1,11 @@ +certifi==2024.7.4 +cffi==1.16.0 +charset-normalizer==3.3.2 +cryptography==42.0.8 +idna==3.7 +pycparser==2.22 +PyJWT==2.8.0 +requests==2.32.3 +setuptools==70.3.0 +urllib3==2.2.2 +wheel==0.43.0 diff --git a/examples/st-vault/README.md b/examples/st-vault/README.md index 338d74d18b..782bea7136 100644 --- a/examples/st-vault/README.md +++ b/examples/st-vault/README.md @@ -2,7 +2,7 @@ | Exposed Service | Description | |------------------------------|---------------------------| -| `localhost:8080/prism-agent` | Single-tenant Cloud Agent | +| `localhost:8080/cloud-agent` | Single-tenant Cloud Agent | | `localhost:8200` | Vault | __Vault__ diff --git a/examples/st-vault/compose.yaml b/examples/st-vault/compose.yaml index a903091b13..fdbb1909e7 100644 --- a/examples/st-vault/compose.yaml +++ b/examples/st-vault/compose.yaml @@ -5,7 +5,7 @@ configs: handle_path /didcomm* { reverse_proxy agent-issuer:8090 } - handle_path /agent* { + handle_path /cloud-agent* { reverse_proxy agent-issuer:8085 } handle_path /keycloak* { @@ -39,14 +39,14 @@ services: POLLUX_DB_PASSWORD: postgres POLLUX_DB_PORT: '5432' POLLUX_DB_USER: postgres - POLLUX_STATUS_LIST_REGISTRY_PUBLIC_URL: http://caddy-issuer:8080/agent + POLLUX_STATUS_LIST_REGISTRY_PUBLIC_URL: http://caddy-issuer:8080/cloud-agent PRISM_NODE_HOST: node PRISM_NODE_PORT: '50053' - REST_SERVICE_URL: http://caddy-issuer:8080/agent + REST_SERVICE_URL: http://caddy-issuer:8080/cloud-agent SECRET_STORAGE_BACKEND: vault VAULT_ADDR: http://vault-issuer:8200 VAULT_TOKEN: admin - image: ghcr.io/hyperledger/identus-cloud-agent:1.37.0 + image: ghcr.io/hyperledger/identus-cloud-agent:1.38.0 restart: always caddy-issuer: configs: diff --git a/examples/st/README.md b/examples/st/README.md index 703a0bc6ad..1575a89961 100644 --- a/examples/st/README.md +++ b/examples/st/README.md @@ -1,5 +1,5 @@ ## Configuration -| Exposed Service | Description | -|------------------------|---------------------------| -| `localhost:8080/agent` | Single-tenant Cloud Agent | +| Exposed Service | Description | +|------------------------------|---------------------------| +| `localhost:8080/cloud-agent` | Single-tenant Cloud Agent | diff --git a/examples/st/compose.yaml b/examples/st/compose.yaml index 9efa65e481..0b2b1dc541 100644 --- a/examples/st/compose.yaml +++ b/examples/st/compose.yaml @@ -5,7 +5,7 @@ configs: handle_path /didcomm* { reverse_proxy agent-issuer:8090 } - handle_path /agent* { + handle_path /cloud-agent* { reverse_proxy agent-issuer:8085 } handle_path /keycloak* { @@ -39,12 +39,12 @@ services: POLLUX_DB_PASSWORD: postgres POLLUX_DB_PORT: '5432' POLLUX_DB_USER: postgres - POLLUX_STATUS_LIST_REGISTRY_PUBLIC_URL: http://caddy-issuer:8080/agent + POLLUX_STATUS_LIST_REGISTRY_PUBLIC_URL: http://caddy-issuer:8080/cloud-agent PRISM_NODE_HOST: node PRISM_NODE_PORT: '50053' - REST_SERVICE_URL: http://caddy-issuer:8080/agent + REST_SERVICE_URL: http://caddy-issuer:8080/cloud-agent SECRET_STORAGE_BACKEND: postgres - image: ghcr.io/hyperledger/identus-cloud-agent:1.37.0 + image: ghcr.io/hyperledger/identus-cloud-agent:1.38.0 restart: always caddy-issuer: configs: