TLDR: eIDAS 2.0 introduces the European Digital Identity Wallet with new consent requirements for identity attributes.
Read full summary
Guide to consent management under the updated eIDAS regulation. Covers selective disclosure of identity attributes, wallet-based consent flows, integration requirements for relying parties accepting EU digital identities, and the future of privacy-preserving identity verification.
*Summary by Claude AI*
## What is eIDAS 2.0?
eIDAS 2.0 is the updated European electronic identification and trust services regulation that mandates every EU Member State provide citizens with a European Digital Identity Wallet (EUDI Wallet) by 2026. This wallet enables privacy-preserving identity verification through selective disclosure—users can prove specific attributes like "over 18" without revealing their full birthdate, fundamentally changing how consent works for identity data.
## Introduction: The Digital Identity Revolution
The way we prove who we are online is about to fundamentally change. For decades, digital identity has meant sharing more information than necessary—providing your full birthdate just to prove you're an adult, or your complete address to verify your country of residence.
eIDAS 2.0 changes everything. By 2026, every EU citizen will have access to a digital wallet that puts them in complete control of their identity data. They'll choose exactly what to share, with whom, and for how long. And they'll have a cryptographic audit trail of every disclosure.
For organizations accepting identity verification—from online retailers to financial services—this represents the biggest shift in identity management since the internet began. The traditional model of collecting and storing identity data is giving way to a verification model where you confirm attributes without ever holding sensitive data.
This guide explores how eIDAS 2.0 transforms consent management and what organizations need to do to prepare for this identity revolution.
## Understanding the EUDI Wallet Architecture
The European Digital Identity Wallet isn't just a digital ID card—it's a comprehensive identity management system built on privacy-preserving cryptography.
### Core Components
```typescript
// EUDI Wallet architecture overview
interface EUDIWalletArchitecture {
// User-controlled identity wallet
wallet: {
holder: 'EU citizen or resident';
storage: 'Device-based (smartphone/tablet)';
control: 'User has full control over disclosures';
interoperability: 'Cross-border by design';
};
// Verifiable credentials issued by trusted authorities
credentials: {
pid: 'Person Identification Data (core identity)';
attestations: 'Additional verified attributes';
qualifiedCertificates: 'QES, QSeals for signatures';
pseudonyms: 'Privacy-preserving identifiers';
};
// Trust framework
trust: {
issuers: 'Government-approved credential issuers';
verifiers: 'Relying parties accepting wallet credentials';
trustLists: 'EU-maintained lists of trusted services';
governance: 'eIDAS 2.0 regulation and technical specs';
};
}
// Credential types in the EUDI Wallet
interface EUDICredentialTypes {
// Person Identification Data - mandatory core identity
pid: {
familyName: string;
firstName: string;
dateOfBirth: string; // ISO 8601
nationality: string; // ISO 3166-1 alpha-2
uniqueIdentifier: string; // Pseudonymous
issuingCountry: string;
issuingAuthority: string;
issuanceDate: string;
expiryDate: string;
};
// Optional attestations
attestations: {
address?: AddressAttestation;
drivingLicense?: DrivingLicenseAttestation;
educationalCredentials?: EducationalAttestation;
professionalQualifications?: ProfessionalAttestation;
healthInsurance?: HealthInsuranceAttestation;
ageVerification?: AgeVerificationAttestation;
};
// Derived credentials for privacy
derivedCredentials: {
ageProof: 'Boolean proof of age threshold';
nationalityProof: 'Proof of EU/EEA citizenship';
residencyProof: 'Proof of residence in specific country';
};
}
```
### The Selective Disclosure Revolution
The most transformative aspect of eIDAS 2.0 is selective disclosure—the ability to prove specific attributes without revealing underlying data:
```typescript
// Selective disclosure implementation
class SelectiveDisclosureManager {
private cryptoEngine: ZKProofEngine;
private credentialStore: SecureCredentialStore;
async createSelectiveDisclosure(
request: DisclosureRequest,
credentials: VerifiableCredential[]
): Promise {
// Parse what the verifier is requesting
const requestedAttributes = this.parseRequest(request);
// Determine minimum disclosure needed
const minimalDisclosure = this.calculateMinimalDisclosure(
requestedAttributes,
credentials
);
// Generate cryptographic proofs
const proofs: AttributeProof[] = [];
for (const attribute of minimalDisclosure) {
if (attribute.type === 'exact_value') {
// Reveal the actual value
proofs.push({
attribute: attribute.name,
type: 'disclosed',
value: attribute.value,
proof: await this.cryptoEngine.createDisclosureProof(
attribute,
credentials
)
});
} else if (attribute.type === 'range_proof') {
// Prove value is within range without revealing it
proofs.push({
attribute: attribute.name,
type: 'range_proof',
statement: attribute.statement, // e.g., "age >= 18"
proof: await this.cryptoEngine.createRangeProof(
attribute,
credentials
)
});
} else if (attribute.type === 'membership_proof') {
// Prove value is in a set without revealing which
proofs.push({
attribute: attribute.name,
type: 'membership_proof',
set: attribute.allowedValues, // e.g., EU countries
proof: await this.cryptoEngine.createMembershipProof(
attribute,
credentials
)
});
} else if (attribute.type === 'predicate_proof') {
// Prove arbitrary predicate
proofs.push({
attribute: attribute.name,
type: 'predicate_proof',
predicate: attribute.predicate,
proof: await this.cryptoEngine.createPredicateProof(
attribute,
credentials
)
});
}
}
// Create presentation
return {
context: ['https://www.w3.org/2018/credentials/v1', 'https://eudi.ec.europa.eu/2024/wallet/v1'],
type: ['VerifiablePresentation', 'EUDIWalletPresentation'],
holder: this.generateHolderIdentifier(request.verifier),
proofs,
metadata: {
created: new Date().toISOString(),
verifierIdentity: request.verifier,
purpose: request.purpose,
expiresAt: this.calculateExpiry(request),
consentReference: this.generateConsentReference()
}
};
}
private calculateMinimalDisclosure(
requested: AttributeRequest[],
credentials: VerifiableCredential[]
): MinimalDisclosure[] {
const minimal: MinimalDisclosure[] = [];
for (const req of requested) {
// Always try to use privacy-preserving proofs first
if (req.acceptsRangeProof && this.canCreateRangeProof(req, credentials)) {
minimal.push({
name: req.attribute,
type: 'range_proof',
statement: req.rangeStatement
});
} else if (req.acceptsMembershipProof && this.canCreateMembershipProof(req, credentials)) {
minimal.push({
name: req.attribute,
type: 'membership_proof',
allowedValues: req.membershipSet
});
} else if (req.acceptsPredicateProof && this.canCreatePredicateProof(req, credentials)) {
minimal.push({
name: req.attribute,
type: 'predicate_proof',
predicate: req.predicate
});
} else {
// Fall back to exact disclosure only if necessary
minimal.push({
name: req.attribute,
type: 'exact_value',
value: this.getAttributeValue(req.attribute, credentials)
});
}
}
return minimal;
}
}
```
## Consent in the eIDAS 2.0 Era
eIDAS 2.0 fundamentally changes how consent works for identity data. Instead of blanket consent to data collection, users give granular, revocable consent for specific disclosures.
### The New Consent Paradigm
```typescript
// eIDAS 2.0 consent management
interface EIDASConsentModel {
// Traditional cookie consent
traditionalConsent: {
model: 'Opt-in/opt-out';
granularity: 'Category-based';
storage: 'Website controls consent records';
revocation: 'User requests, site processes';
evidence: 'Consent management platform logs';
};
// eIDAS 2.0 identity consent
eidasConsent: {
model: 'Transaction-based disclosure';
granularity: 'Attribute-level';
storage: 'Wallet maintains consent records';
revocation: 'User controls directly via wallet';
evidence: 'Cryptographic proof in wallet';
};
}
// Consent flow for identity verification
class EIDASConsentManager {
private walletConnector: WalletConnectionService;
private consentStore: ConsentRecordStore;
private auditLogger: AuditLogService;
async requestIdentityConsent(
verificationRequest: VerificationRequest
): Promise {
// Step 1: Generate consent request
const consentRequest = this.createConsentRequest(verificationRequest);
// Step 2: Present to user via wallet interface
const userDecision = await this.presentConsentRequest(consentRequest);
if (!userDecision.approved) {
await this.auditLogger.log({
event: 'consent_denied',
request: consentRequest,
reason: userDecision.reason,
timestamp: new Date().toISOString()
});
return {
success: false,
reason: userDecision.reason,
alternatives: this.suggestAlternatives(verificationRequest)
};
}
// Step 3: Receive selective disclosure from wallet
const disclosure = await this.walletConnector.receiveDisclosure(
consentRequest.id,
userDecision.approvedAttributes
);
// Step 4: Verify cryptographic proofs
const verification = await this.verifyDisclosure(disclosure);
if (!verification.valid) {
throw new Error('Disclosure verification failed');
}
// Step 5: Store consent record (without storing the actual data)
await this.consentStore.record({
consentId: consentRequest.id,
timestamp: new Date().toISOString(),
verifier: verificationRequest.verifier,
purpose: verificationRequest.purpose,
attributesVerified: userDecision.approvedAttributes.map(a => a.name),
// Note: We don't store the actual values, just proof we verified them
proofReference: disclosure.proofReference,
expiresAt: disclosure.metadata.expiresAt
});
// Step 6: Log for audit trail
await this.auditLogger.log({
event: 'consent_granted',
consentId: consentRequest.id,
attributes: userDecision.approvedAttributes.map(a => a.name),
purpose: verificationRequest.purpose,
timestamp: new Date().toISOString()
});
return {
success: true,
verification: verification.results,
consentReference: consentRequest.id
};
}
private createConsentRequest(
verification: VerificationRequest
): ConsentRequest {
return {
id: this.generateRequestId(),
verifier: {
name: verification.verifier.name,
identifier: verification.verifier.euTrustServiceId,
trustMark: verification.verifier.trustMark,
privacyPolicy: verification.verifier.privacyPolicyUrl
},
purpose: {
description: verification.purpose.description,
legalBasis: verification.purpose.legalBasis,
retentionPeriod: verification.purpose.dataRetention
},
requestedAttributes: verification.attributes.map(attr => ({
attribute: attr.name,
required: attr.required,
purpose: attr.specificPurpose,
acceptsMinimalDisclosure: attr.acceptsZKProof
})),
created: new Date().toISOString(),
expiresAt: new Date(Date.now() + 15 * 60 * 1000).toISOString() // 15 min
};
}
async revokeConsent(consentId: string, userId: string): Promise {
// Verify user owns this consent
const consent = await this.consentStore.get(consentId);
if (!consent) {
throw new Error('Consent record not found');
}
// Mark consent as revoked
await this.consentStore.revoke(consentId, {
revokedAt: new Date().toISOString(),
revokedBy: userId,
reason: 'user_request'
});
// Notify verifier of revocation (if still within validity period)
if (new Date(consent.expiresAt) > new Date()) {
await this.notifyVerifierOfRevocation(consent);
}
// Log revocation
await this.auditLogger.log({
event: 'consent_revoked',
consentId,
timestamp: new Date().toISOString()
});
return {
success: true,
consentId,
revokedAt: new Date().toISOString()
};
}
}
```
### User-Controlled Consent Records
With eIDAS 2.0, users maintain their own consent records in their wallet:
```typescript
// User's wallet consent management
class WalletConsentDashboard {
private wallet: EUDIWallet;
private consentHistory: ConsentHistoryStore;
async getConsentHistory(filters?: ConsentFilters): Promise {
const records = await this.consentHistory.query({
userId: this.wallet.holderId,
...filters
});
return records.map(record => ({
id: record.id,
verifier: {
name: record.verifierName,
trustLevel: record.verifierTrustLevel,
logo: record.verifierLogo
},
timestamp: record.timestamp,
purpose: record.purpose,
attributesShared: record.disclosedAttributes,
expiresAt: record.expiryDate,
status: this.calculateStatus(record),
actions: this.getAvailableActions(record)
}));
}
async viewDisclosureDetails(consentId: string): Promise {
const record = await this.consentHistory.get(consentId);
return {
overview: {
verifier: record.verifierName,
date: record.timestamp,
purpose: record.purpose
},
attributesShared: record.disclosedAttributes.map(attr => ({
name: attr.name,
disclosureType: attr.type, // 'exact', 'range_proof', etc.
valueShared: attr.type === 'exact' ? attr.value : null,
proofStatement: attr.type !== 'exact' ? attr.statement : null
})),
consent: {
legalBasis: record.legalBasis,
retention: record.retentionPeriod,
canRevoke: this.canRevoke(record)
},
audit: {
proofReference: record.proofReference,
blockchainAnchor: record.anchorReference,
verificationTimestamp: record.verificationTimestamp
}
};
}
async exportConsentHistory(format: 'json' | 'pdf'): Promise {
const records = await this.getConsentHistory();
if (format === 'json') {
return {
format: 'json',
data: JSON.stringify(records, null, 2),
filename: `consent-history-${Date.now()}.json`
};
}
// Generate PDF report
return {
format: 'pdf',
data: await this.generatePDFReport(records),
filename: `consent-history-${Date.now()}.pdf`
};
}
}
```
## Integrating with EUDI Wallets
For organizations that need to verify identity, integration with EUDI Wallets requires becoming a "Relying Party" in the eIDAS trust framework.
### Relying Party Integration
```typescript
// EUDI Wallet relying party integration
class EUDIRelyingParty {
private config: RelyingPartyConfig;
private trustFramework: TrustFrameworkClient;
private verifier: PresentationVerifier;
private sessionManager: SessionManager;
constructor(config: RelyingPartyConfig) {
this.config = config;
this.trustFramework = new TrustFrameworkClient(config.trustListUrl);
this.verifier = new PresentationVerifier(config.verifierKeyPair);
this.sessionManager = new SessionManager();
}
async initiateVerification(
requirements: VerificationRequirements
): Promise {
// Step 1: Create verification request according to ARF specs
const request = await this.createVerificationRequest(requirements);
// Step 2: Create session
const session = await this.sessionManager.create({
requestId: request.id,
requirements,
status: 'pending',
createdAt: new Date().toISOString(),
expiresAt: new Date(Date.now() + 15 * 60 * 1000).toISOString()
});
// Step 3: Generate QR code or deep link for wallet connection
const connectionMethod = await this.generateConnectionMethod(request);
return {
sessionId: session.id,
request,
connectionMethod,
expiresAt: session.expiresAt
};
}
private async createVerificationRequest(
requirements: VerificationRequirements
): Promise {
// Follow OpenID4VP specification
return {
response_type: 'vp_token',
client_id: this.config.clientId,
redirect_uri: this.config.redirectUri,
presentation_definition: {
id: this.generateDefinitionId(),
input_descriptors: requirements.attributes.map(attr => ({
id: `${attr.name}_descriptor`,
name: attr.displayName,
purpose: attr.purpose,
constraints: {
fields: [{
path: [`$.credentialSubject.${attr.name}`, `$.vc.credentialSubject.${attr.name}`],
filter: attr.filter,
predicate: attr.acceptsZKProof ? attr.predicate : undefined
}]
}
})),
format: {
'jwt_vc': { alg: ['ES256'] },
'ldp_vc': { proof_type: ['Ed25519Signature2018'] }
}
},
nonce: this.generateNonce(),
state: this.generateState()
};
}
async processWalletResponse(
response: WalletResponse
): Promise {
// Step 1: Validate response structure
this.validateResponseStructure(response);
// Step 2: Verify presentation signature
const signatureValid = await this.verifier.verifyPresentation(
response.vp_token
);
if (!signatureValid) {
throw new VerificationError('Invalid presentation signature');
}
// Step 3: Verify credential issuer is trusted
const issuerTrusted = await this.trustFramework.verifyIssuer(
response.credential.issuer
);
if (!issuerTrusted) {
throw new VerificationError('Credential issuer not in trust list');
}
// Step 4: Verify credential is not revoked
const revocationStatus = await this.checkRevocation(response.credential);
if (revocationStatus.revoked) {
throw new VerificationError('Credential has been revoked');
}
// Step 5: Verify cryptographic proofs (for selective disclosure)
const proofsValid = await this.verifySelectiveDisclosureProofs(
response.presentation
);
if (!proofsValid.allValid) {
throw new VerificationError('Selective disclosure proof verification failed');
}
// Step 6: Extract verified attributes
const verifiedAttributes = this.extractVerifiedAttributes(
response.presentation,
proofsValid.proofResults
);
return {
success: true,
sessionId: response.state,
verifiedAttributes,
issuer: response.credential.issuer,
issuanceDate: response.credential.issuanceDate,
proofType: this.determineProofType(response.presentation),
timestamp: new Date().toISOString()
};
}
private async verifySelectiveDisclosureProofs(
presentation: VerifiablePresentation
): Promise {
const results: ProofResult[] = [];
for (const proof of presentation.proofs) {
let valid: boolean;
let details: any;
switch (proof.type) {
case 'disclosed':
// Verify the disclosed value matches the credential
valid = await this.verifier.verifyDisclosedValue(proof);
details = { value: proof.value };
break;
case 'range_proof':
// Verify zero-knowledge range proof
valid = await this.verifier.verifyRangeProof(
proof.proof,
proof.statement
);
details = { statement: proof.statement };
break;
case 'membership_proof':
// Verify set membership proof
valid = await this.verifier.verifyMembershipProof(
proof.proof,
proof.set
);
details = { set: proof.set };
break;
case 'predicate_proof':
// Verify arbitrary predicate proof
valid = await this.verifier.verifyPredicateProof(
proof.proof,
proof.predicate
);
details = { predicate: proof.predicate };
break;
default:
valid = false;
details = { error: 'Unknown proof type' };
}
results.push({
attribute: proof.attribute,
type: proof.type,
valid,
details
});
}
return {
allValid: results.every(r => r.valid),
proofResults: results
};
}
}
```
### Trust Framework Verification
```typescript
// eIDAS trust framework client
class TrustFrameworkClient {
private trustListUrl: string;
private cachedTrustList: TrustList | null = null;
private cacheExpiry: Date | null = null;
constructor(trustListUrl: string) {
this.trustListUrl = trustListUrl;
}
async verifyIssuer(issuerId: string): Promise {
const trustList = await this.getTrustList();
const issuer = trustList.issuers.find(i => i.id === issuerId);
if (!issuer) {
return {
trusted: false,
reason: 'Issuer not found in trust list'
};
}
// Verify issuer's qualification
const qualificationValid = this.verifyQualification(issuer);
if (!qualificationValid) {
return {
trusted: false,
reason: 'Issuer qualification expired or invalid'
};
}
return {
trusted: true,
issuer: {
name: issuer.name,
country: issuer.country,
qualifications: issuer.qualifications,
supervisoryBody: issuer.supervisoryBody
}
};
}
async verifyCredentialType(
credentialType: string,
issuerId: string
): Promise {
const trustList = await this.getTrustList();
const issuer = trustList.issuers.find(i => i.id === issuerId);
if (!issuer) {
return {
authorized: false,
reason: 'Issuer not found'
};
}
const authorization = issuer.authorizedCredentialTypes.find(
ct => ct.type === credentialType
);
if (!authorization) {
return {
authorized: false,
reason: `Issuer not authorized to issue ${credentialType}`
};
}
return {
authorized: true,
scope: authorization.scope,
restrictions: authorization.restrictions
};
}
private async getTrustList(): Promise {
if (this.cachedTrustList && this.cacheExpiry && this.cacheExpiry > new Date()) {
return this.cachedTrustList;
}
// Fetch and verify trust list
const response = await fetch(this.trustListUrl);
const trustList = await response.json();
// Verify trust list signature
const signatureValid = await this.verifyTrustListSignature(trustList);
if (!signatureValid) {
throw new Error('Trust list signature verification failed');
}
// Cache for 1 hour
this.cachedTrustList = trustList;
this.cacheExpiry = new Date(Date.now() + 60 * 60 * 1000);
return trustList;
}
}
```
## Impact on Consent Management Platforms
eIDAS 2.0 will significantly impact traditional CMPs. Here's how to prepare:
### Hybrid Consent Architecture
```typescript
// Hybrid CMP supporting both cookie consent and EUDI Wallet
class HybridConsentManager {
private cookieConsent: CookieConsentManager;
private walletConsent: EUDIConsentManager;
private unifiedPreferences: UnifiedPreferenceStore;
async initializeConsent(context: ConsentContext): Promise {
// Determine which consent mechanisms apply
const mechanisms = this.determineApplicableMechanisms(context);
const interfaces: ConsentInterface[] = [];
// Traditional cookie consent (still needed for cookies!)
if (mechanisms.includes('cookie_consent')) {
interfaces.push(await this.cookieConsent.initialize(context));
}
// EUDI Wallet consent (for identity verification)
if (mechanisms.includes('wallet_consent') && context.requiresIdentityVerification) {
interfaces.push(await this.walletConsent.initialize(context));
}
// Return unified interface
return this.createUnifiedInterface(interfaces);
}
async handleConsentChoice(choice: UserConsentChoice): Promise {
const results: ConsentResult[] = [];
// Process cookie consent
if (choice.cookiePreferences) {
const cookieResult = await this.cookieConsent.processChoice(
choice.cookiePreferences
);
results.push(cookieResult);
}
// Process wallet consent (triggered by verification requests)
if (choice.walletDisclosure) {
const walletResult = await this.walletConsent.processDisclosure(
choice.walletDisclosure
);
results.push(walletResult);
}
// Sync to unified preferences
await this.unifiedPreferences.update({
userId: choice.userId,
cookieConsent: choice.cookiePreferences,
walletConsent: choice.walletDisclosure,
lastUpdated: new Date().toISOString()
});
return this.aggregateResults(results);
}
async getUserConsentStatus(userId: string): Promise {
const [cookieStatus, walletStatus] = await Promise.all([
this.cookieConsent.getStatus(userId),
this.walletConsent.getStatus(userId)
]);
return {
cookies: {
necessary: true,
analytics: cookieStatus.analytics,
marketing: cookieStatus.marketing,
functional: cookieStatus.functional
},
wallet: {
disclosureHistory: walletStatus.disclosureHistory,
activeConsents: walletStatus.activeConsents,
revokedConsents: walletStatus.revokedConsents
},
lastModified: Math.max(
new Date(cookieStatus.lastModified).getTime(),
new Date(walletStatus.lastModified).getTime()
)
};
}
}
```
### Preference Center Updates
```typescript
// Updated preference center supporting EUDI Wallet
class ModernPreferenceCenter {
async render(userId: string): Promise {
const status = await this.getUnifiedStatus(userId);
return {
sections: [
// Traditional cookie preferences
{
id: 'cookies',
title: 'Cookie Preferences',
description: 'Control how we use cookies and similar technologies',
categories: [
{
id: 'necessary',
name: 'Strictly Necessary',
description: 'Required for the website to function',
enabled: true,
locked: true
},
{
id: 'analytics',
name: 'Analytics',
description: 'Help us understand how you use our site',
enabled: status.cookies.analytics,
locked: false
},
{
id: 'marketing',
name: 'Marketing',
description: 'Used to deliver relevant advertisements',
enabled: status.cookies.marketing,
locked: false
}
]
},
// NEW: Identity verification history
{
id: 'identity',
title: 'Identity Verification History',
description: 'Your EUDI Wallet disclosure history with us',
enabled: status.wallet.disclosureHistory.length > 0,
items: status.wallet.disclosureHistory.map(d => ({
id: d.id,
date: d.timestamp,
purpose: d.purpose,
attributesShared: d.attributes,
status: d.status,
actions: d.status === 'active' ? ['view', 'revoke'] : ['view']
}))
},
// NEW: Connected wallet status
{
id: 'wallet_connection',
title: 'EUDI Wallet',
description: 'Manage your digital identity wallet connection',
connected: status.wallet.connected,
walletInfo: status.wallet.connected ? {
provider: status.wallet.providerName,
lastUsed: status.wallet.lastUsed
} : null,
actions: status.wallet.connected
? ['disconnect', 'view_history']
: ['connect']
}
]
};
}
}
```
## Implementation Timeline and Preparation
### eIDAS 2.0 Rollout Timeline
| Milestone | Date | Impact |
|-----------|------|--------|
| Regulation adopted | December 2024 | Legal framework in place |
| Technical specifications finalized | June 2025 | Integration specs available |
| Pilot wallets launched | December 2025 | Early adopter testing |
| Mandatory wallet availability | September 2026 | All EU citizens can get wallet |
| Large platforms must accept | September 2027 | Mandatory relying party status |
| Full cross-border interoperability | December 2027 | Seamless EU-wide usage |
### Preparation Checklist for Organizations
```typescript
// eIDAS 2.0 preparation checklist
const eidasPreparationChecklist = {
phase1_assessment: {
timeline: '2024-2025',
tasks: [
{
task: 'Audit current identity verification needs',
details: 'Identify all processes requiring identity verification',
priority: 'high'
},
{
task: 'Map data currently collected vs. needed',
details: 'Identify opportunities for data minimization',
priority: 'high'
},
{
task: 'Assess CMP upgrade requirements',
details: 'Evaluate if current CMP can support wallet integration',
priority: 'medium'
},
{
task: 'Legal review of consent processes',
details: 'Ensure processes align with eIDAS requirements',
priority: 'high'
}
]
},
phase2_planning: {
timeline: '2025',
tasks: [
{
task: 'Architecture design for wallet integration',
details: 'Design technical integration with EUDI Wallets',
priority: 'high'
},
{
task: 'Update privacy policies',
details: 'Add wallet consent and selective disclosure explanations',
priority: 'medium'
},
{
task: 'Train staff on new consent model',
details: 'Ensure teams understand wallet-based verification',
priority: 'medium'
},
{
task: 'Select wallet integration partners',
details: 'Choose SDK/service providers for integration',
priority: 'high'
}
]
},
phase3_implementation: {
timeline: '2025-2026',
tasks: [
{
task: 'Implement relying party infrastructure',
details: 'Set up verification endpoints and trust framework connection',
priority: 'high'
},
{
task: 'Develop hybrid consent interface',
details: 'Build UI supporting both cookie and wallet consent',
priority: 'high'
},
{
task: 'Integrate with pilot wallets',
details: 'Test with early wallet implementations',
priority: 'medium'
},
{
task: 'Update audit and compliance processes',
details: 'Ensure compliance monitoring covers wallet interactions',
priority: 'medium'
}
]
},
phase4_launch: {
timeline: '2026-2027',
tasks: [
{
task: 'Launch wallet verification option',
details: 'Offer users wallet-based verification',
priority: 'high'
},
{
task: 'Monitor user adoption',
details: 'Track wallet usage vs. traditional methods',
priority: 'medium'
},
{
task: 'Optimize user experience',
details: 'Refine flows based on user feedback',
priority: 'medium'
},
{
task: 'Achieve mandatory compliance',
details: 'Ensure full compliance by deadline',
priority: 'critical'
}
]
}
};
```
## Frequently Asked Questions
### Will eIDAS 2.0 replace cookie consent?
No. eIDAS 2.0 addresses identity verification, not website tracking. Cookie consent under GDPR/ePrivacy remains separate. However, the two may interact when identity verification is needed alongside website functionality that uses cookies.
### Do all businesses need to support EUDI Wallets?
Large online platforms and certain regulated sectors (banking, government services) will have mandatory support requirements. Other businesses can choose whether to accept wallet-based verification. However, supporting wallets offers significant advantages for user trust and data minimization.
### How does selective disclosure work technically?
Selective disclosure uses zero-knowledge proofs (ZKPs) and other cryptographic techniques. For example, to prove you're over 18, the wallet creates a mathematical proof that your birthdate makes you at least 18 years old, without revealing the actual date. The verifier can confirm the proof is valid without learning your birthdate.
### What happens if a user loses their wallet device?
EUDI Wallets include recovery mechanisms. Users can backup their wallet to secure cloud storage or recovery devices. The wallet ecosystem includes standardized recovery procedures that allow credential re-issuance while maintaining security.
## The Future: Privacy-Preserving Identity
eIDAS 2.0 and the EUDI Wallet represent a fundamental shift in digital identity and privacy. Instead of the current model where organizations collect and store identity data (with all associated risks), we're moving to a model where users prove attributes without sharing underlying data.
For consent management, this means:
1. **Less data to protect**: You verify attributes without storing them
2. **User-controlled records**: Users maintain their own consent history
3. **Cryptographic proof**: Audit trails are mathematically verifiable
4. **True data minimization**: Request only what you need, receive only proofs
Organizations that embrace this shift will benefit from reduced data liability, increased user trust, and alignment with the direction privacy regulation is heading globally.
The future of privacy isn't about managing ever-larger consent databases—it's about not needing that data in the first place. eIDAS 2.0 shows us how to get there.
## Additional Resources
- [European Commission eIDAS 2.0 Page](https://ec.europa.eu/digital-building-blocks/wikis/display/EUDIGITALIDENTITYWALLET)
- [Architecture Reference Framework (ARF)](https://eu-digital-identity-wallet.github.io/architecture-and-reference-framework/)
- [OpenID4VP Specification](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html)
- [W3C Verifiable Credentials](https://www.w3.org/TR/vc-data-model/)