Skip to main content

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):

FieldPurpose
walletNonceWallet-facing nonce, included in presentation requests
sessionIdInternal correlation ID, never exposed to the wallet
nonceServer-side replay prevention nonce (deprecated in favor of walletNonce for clarity)
stateSame-device state parameter (optional, for redirect-based flows)
responseCodeOne-time code for same-device redirect flow (appended to redirect_uri to prevent session fixation)

Security Rationale:

  • walletNonce is the ONLY nonce value sent to the wallet and included in VP tokens
  • sessionId remains internal and is used only for backend correlation (e.g., mapping to response_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_grant or invalid_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
}
}
FieldTypeDefaultDescription
cleanupMode"delete" | "anonymize""delete"Whether to fully delete or anonymize sessions
retentionDaysnumber30Days 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).

KeyTypeNotes
SESSION_TIDY_UP_INTERVALnumberInterval in seconds to run session tidy up (default: 3600)
SESSION_TTLnumberDefault time to live for sessions in seconds. Can be overridden per tenant. (default: 86400)
SESSION_CLEANUP_MODEstringDefault cleanup mode when sessions expire. 'full' deletes the entire session, 'anonymize' keeps metadata but removes personal data. Can be overridden per tenant. (default: full)