Sessions
EUDIPLO tracks issuance and verification sessions to correlate multi-step protocol flows, enforce security policies, and maintain audit logs. Sessions are ephemeral state records that exist only while a credential flow is active.
OID4VP Security Fieldsโ
Each verification session includes security fields defined by the OpenID4VP specification (ยง13.3):
| Field | Purpose |
|---|---|
walletNonce | Wallet-facing nonce, included in presentation requests |
sessionId | Internal correlation ID, never exposed to the wallet |
nonce | Server-side replay prevention nonce (deprecated in favor of walletNonce for clarity) |
state | Same-device state parameter (optional, for redirect-based flows) |
responseCode | One-time code for same-device redirect flow (appended to redirect_uri to prevent session fixation) |
Security Rationale:
walletNonceis the ONLY nonce value sent to the wallet and included in VP tokenssessionIdremains internal and is used only for backend correlation (e.g., mapping toresponse_code)- This separation prevents session fixation attacks where an attacker could substitute their own session identifier
For technical background, see OID4VP ยง13.3 (Security Considerations).
Single-Use Validationโ
All sessions enforce single-use semantics:
- Once a credential is issued or a presentation is verified, the session is marked as completed
- Subsequent attempts using the same session identifier are rejected with
invalid_grantorinvalid_request - This prevents replay attacks and credential duplication
Session Cleanupโ
Sessions are automatically cleaned up after expiration or completion. EUDIPLO supports two cleanup modes:
Full Deletionโ
Removes the session record entirely from the database:
await this.sessionRepository.delete({ id: sessionId });
Use when: Ephemeral flows (e.g., one-time presentations) where no audit trail is required.
Anonymizationโ
Preserves the session record but removes PII and credential claims:
await this.sessionRepository.update(sessionId, {
anonymizedAt: new Date(),
credentialClaims: null,
presentedCredentials: null,
// ... nullify all sensitive fields
});
Use when: Audit compliance requires retention of flow metadata (timestamps, protocol details) but not credential data.
Per-Tenant Configurationโ
Session cleanup is configured per-tenant via the tenant configuration:
{
"sessionConfig": {
"cleanupMode": "anonymize",
"retentionDays": 90
}
}
| Field | Type | Default | Description |
|---|---|---|---|
cleanupMode | "delete" | "anonymize" | "delete" | Whether to fully delete or anonymize sessions |
retentionDays | number | 30 | Days to retain completed sessions before cleanup |
Note: The cleanup cron runs hourly and processes sessions older than retentionDays since completion.
Session Logsโ
Session events (authorization, token exchange, credential issuance, presentation submission) are logged using the PinoLogger:
this.logger.log(
`Credential issued for session ${sessionId}`,
{ sessionId, credentialType, format }
);
Logs include correlation IDs and are exportable to SIEM systems via OpenTelemetry or log aggregators.
Global Configurationโ
Auto-generated. Do not edit manually. Run
pnpm --filter @eudiplo/docs run prebuild(scripts/generate-config-docs.ts).
| Key | Type | Notes |
|---|---|---|
SESSION_TIDY_UP_INTERVAL | number | Interval in seconds to run session tidy up (default: 3600) |
SESSION_TTL | number | Default time to live for sessions in seconds. Can be overridden per tenant. (default: 86400) |
SESSION_CLEANUP_MODE | string | Default cleanup mode when sessions expire. 'full' deletes the entire session, 'anonymize' keeps metadata but removes personal data. Can be overridden per tenant. (default: full) |