Architecture Overview
The identity layer consists of two ACA-Py agents operating in a peer-to-peer relationship:Issuer Agent
Issues verifiable credentials to citizens and verifies proof presentations during login
Holder Agent
Stores citizen credentials and responds to proof requests from the verifier
Credential Schema
Credentials issued by CCDigital contain the following attributes:id_type- Type of identification (CC, TI, CE, etc.)id_number- Identification numberfirst_name- First name(s)last_name- Last name(s)email- Email address
cred_def_id in the application configuration.
Verifiable Login Flow
CCDigital replaces traditional username/password authentication with a present-proof workflow that validates the user’s identity through their verifiable credential.Initiate Proof Request
The system constructs a proof request filtered by the user’s
id_number and sends it via /present-proof-2.0/send-request.Holder Presents Proof
The holder agent (user’s wallet) automatically responds to the proof request by selecting the matching credential and presenting the requested attributes.
Verify Presentation
The issuer agent verifies the cryptographic proof and extracts revealed attributes.
The proof request includes a restriction to ensure only credentials issued with the configured
cred_def_id and matching attr::id_number::value are accepted.Credential Issuance
Credentials are issued to registered citizens using a Python script that reads from the MySQL database: Script:issue_credentials_from_db.py (external Indy tools)
The script:
- Queries the
personstable for eligible citizens - Resolves or creates a connection with the holder agent
- Issues a credential with the person’s attributes
- Records the credential exchange ID for audit purposes
State Synchronization
User access states (ENABLED, SUSPENDED, DISABLED) are synchronized to the holder agent’s connection metadata to enable server-side access control decisions.Admin Changes State
Government admin updates a user’s
access_state via the admin dashboard.Service: UserAccessGovernanceService.java:85Proof Status Polling
After initiating a proof request, the client polls the backend to check completion:acapy.proof.poll-interval-ms(default: 1000ms)acapy.proof.poll-timeout-ms(default: 120000ms)
Connection Resolution
The system resolves the holder’sconnection_id in two modes:
- Fixed Mode: Uses
ccdigital.indy.holder-connection-idif configured - Auto Mode: Queries
/connections?state=activeand matches bytheir_labelagainstccdigital.indy.holder-label
IndyProofLoginService.java:376
Configuration Reference
| Variable | Purpose |
|---|---|
INDY_ISSUER_ADMIN_URL | Issuer agent admin API endpoint |
INDY_HOLDER_ADMIN_URL | Holder agent admin API endpoint |
INDY_HOLDER_CONNECTION_ID | Fixed connection ID or “auto” |
INDY_HOLDER_LABEL | Label to match holder connection in auto mode |
INDY_CRED_DEF_ID | Credential definition ID on Indy ledger |
INDY_ADMIN_API_KEY | API key for admin endpoints (optional) |
INDY_USER_ACCESS_SYNC_ENABLED | Enable state synchronization |
INDY_USER_ACCESS_SYNC_PATH | Metadata endpoint path template |
Key Services
IndyProofLoginService.java
IndyProofLoginService.java
Location:
src/main/java/co/edu/unbosque/ccdigital/service/IndyProofLoginService.javaImplements present-proof 2.0 login workflow, status polling, and attribute extraction from verified presentations.UserAccessGovernanceService.java
UserAccessGovernanceService.java
Location:
src/main/java/co/edu/unbosque/ccdigital/service/UserAccessGovernanceService.javaManages user access state lifecycle and synchronization to Indy connection metadata.IndyAdminClient.java
IndyAdminClient.java
Location:
src/main/java/co/edu/unbosque/ccdigital/service/IndyAdminClient.javaHTTP client wrapper for ACA-Py admin API calls with API key authentication.UserAuthFlowService.java
UserAuthFlowService.java
Location:
src/main/java/co/edu/unbosque/ccdigital/service/UserAuthFlowService.javaOrchestrates the complete authentication flow including proof request, polling, OTP verification, and session creation.Security Considerations
Cryptographic Verification: All proofs are verified cryptographically using Indy’s ZKP (Zero-Knowledge Proof) primitives. The backend never stores or transmits raw credential data.
Selective Disclosure: Only the requested attributes are revealed during proof presentation. Other credential attributes remain private.
