Building an Age-Verification Microservice for European Sites: Technical Architecture and Sample Code
Build a privacy-first, EU-compliant age-verification microservice that issues minimal age tokens, integrates with registrar WHOIS privacy, and uses OAuth.
Hook: Why EU sites need a privacy-first age verification microservice now
Developers and IT leads are under pressure: regulators and platforms tightened age checks across Europe in late 2025 and early 2026, and your site must block underage access without leaking personal data or breaking registrar workflows. You need an age verification API that is automated, auditable, and integrates with domain registration/email flows while protecting WHOIS privacy.
Top-line architecture and goals
Deliver a small, composable microservice that:
- Verifies age with minimal data retention and privacy-preserving attestations
- Exposes an OAuth-protected API for site integration with clear scopes
- Integrates seamlessly with registrar APIs and email verification flows to keep WHOIS details private
- Implements EU compliance measures (GDPR, ePrivacy, DSA-related guidance) and audit trails
Why this is timely (2026 context)
In 2025–2026 regulators and major platforms intensified age-detection and verification. The EU Digital Services Act (DSA) expectations plus platform-led measures (e.g., TikTok’s Europe-wide upgrades announced January 2026) make robust age verification a first-class requirement for services targeting EU users. Additionally, emerging trust frameworks—W3C Verifiable Credentials and pilot EU digital identity efforts—enable privacy-preserving attestations in production.
High-level system diagram (text)
Components:
- Site frontend (JS/SPA) — triggers age-check via Authorization Code + PKCE, or calls backend with client credentials
- Age Verification Microservice (this article) — provides endpoints for start verification, attestation, status, and revocation
- Attestation Providers — eIDAS wallets, third-party age attest services, or document-check providers that can produce a minimal "age:overX" verifiable credential
- Registrar integrations — API calls to registrars to create/update domains using WHOIS privacy flags and masked contact addresses
- Email flows — ephemeral alias generation for verification; hashed tokens for single-click confirmation
- Secrets & KMS/HSM — signing JWTs, rotating keys, audit logs
Core design principles
- Data minimization: store only that a user is over/under threshold; avoid storing birthdays or document scans unless absolutely required.
- Privacy by design: use pseudonymous identifiers, short-lived tokens, and verifiable credentials instead of raw PII.
- Consent & lawful basis: record explicit consent where appropriate and document lawful basis for processing (e.g., compliance with DSA).
- Integratable: simple OAuth scopes and lightweight webhooks for registrar events.
API contract: endpoints & OAuth scopes
Design lightweight REST endpoints with OAuth2 and JWT. Example scopes and endpoints:
- Scopes: age:verify, age:status, registrar:manage, email:verify
- POST /v1/verifications/start — start an age check (returns verification_id and redirect link)
- GET /v1/verifications/:id — get verification status (minimal response)
- POST /v1/verifications/:id/callback — webhook for attestation providers to post results
- POST /v1/domains/register — registrar integration call that accepts an age token and privacy flags
- POST /v1/consents — record consent with timestamp and client_id
Privacy-first verification flow (recommended)
- User hits site; site determines an age-gated action and calls the microservice to start verification.
- Microservice returns a short-lived session_id and a redirect to a hosted verification page or an embedded flow.
- User completes verification via a selected attestation (local age input + optional third-party attestor or eIDAS wallet). The attestor returns a minimized verifiable credential: e.g., {"age_over": 18, "issuer": "eID-Provider", "exp": ...}.
- Microservice validates the attestation, issues a signed age token (JWT) that contains only: {sub: pseudonym_id, age_over: 18, iss, iat, exp, jti}.
- Site receives token from client and calls backend to authorize the action. The backend verifies the JWT signature and age claim.
- For registrar flows, backend calls /v1/domains/register attaching the age token. Registrar processes domain registration with WHOIS privacy set and uses masked contacts or service contact for WHOIS to avoid PII leakage.
Sample Node.js (Express) microservice — minimal, focused
This example is intentionally compact. It demonstrates starting verification, receiving an attestation callback and issuing a privacy-preserving JWT age token. In production, replace in-memory stores and secrets with persistent storage and KMS.
/* app.js (Node 18+) - run with: node app.js
npm: express, jsonwebtoken, uuid, body-parser
*/
const express = require('express');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');
const { v4: uuidv4 } = require('uuid');
const app = express();
app.use(bodyParser.json());
// In-memory "DB" for demo only
const sessions = new Map();
const ageTokens = new Map();
// Replace with a rotated private key from your KMS/HSM
const SIGNING_KEY = process.env.SIGNING_KEY || 'dev_secret_key_change_in_prod';
// Start verification — returns session_id and redirect (or embed) URL
app.post('/v1/verifications/start', (req, res) => {
const { client_id, threshold = 18 } = req.body;
const sessionId = uuidv4();
sessions.set(sessionId, { client_id, threshold, status: 'pending', created: Date.now() });
// In real use, return a URL to a hosted verification UI or accept client-provided attestor selection
const hosted = `https://verify.example.com/session/${sessionId}`;
res.json({ session_id: sessionId, hosted_verification_url: hosted });
});
// Attestor (or hosted UI) posts result here — minimal attestation
app.post('/v1/verifications/:id/callback', (req, res) => {
const id = req.params.id;
const session = sessions.get(id);
if (!session) return res.status(404).send('not found');
// Attestation payload should contain issuer, proof and minimal claims
const { issuer, age_over, proof } = req.body; // proof is opaque to this service in minimal design
// Validate proof with attestor's API or signature; omitted here for brevity
// Accept only minimal claim
session.status = (age_over >= session.threshold) ? 'passed' : 'failed';
session.attestor = issuer;
session.age_over = age_over;
sessions.set(id, session);
if (session.status === 'passed') {
// issue privacy-preserving JWT (age token)
const tokenId = uuidv4();
const payload = {
sub: `anon:${uuidv4()}`, // pseudonymous subject
age_over: session.threshold,
iss: 'https://age.example.com',
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000) + 3600, // 1 hour
jti: tokenId
};
const token = jwt.sign(payload, SIGNING_KEY);
ageTokens.set(tokenId, { token, session_id: id, created: Date.now() });
return res.json({ status: session.status, age_token: token });
}
res.json({ status: session.status });
});
// Sites call to check verification status
app.get('/v1/verifications/:id', (req, res) => {
const session = sessions.get(req.params.id);
if (!session) return res.status(404).send('not found');
res.json({ status: session.status, age_over: session.age_over || null });
});
// Validate an age token (for backends)
app.post('/v1/verifications/validate-token', (req, res) => {
const { token } = req.body;
try {
const payload = jwt.verify(token, SIGNING_KEY);
// Minimal response: only what the caller needs
return res.json({ valid: true, age_over: payload.age_over, sub: payload.sub, exp: payload.exp });
} catch (e) {
return res.json({ valid: false, reason: e.message });
}
});
app.listen(3000, () => console.log('Age verification microservice running on :3000'));
Notes on the example
- Use a KMS/HSM to sign tokens in production — never store signing keys in code or plain env.
- Replace the in-memory maps with a GDPR-compliant store and retention logic (DPIA required for production).
- Validate attestor proofs using their public keys or API to avoid accepting spoofed callbacks.
Registrar & WHOIS privacy integration
Domain registration often requires providing registrant contact details. To respect WHOIS privacy and minimize PII exposure, implement these patterns:
- Service contact + privacy flag: when calling registrar API, pass the privacy flag (most registrars offer privacy/proxy services). Use a service or agency contact when allowed (check contractual implications).
- Masked/alias emails: generate an ephemeral alias (e.g., confirm-1234@proxy.example.com) and forward to the real address. Use the alias in WHOIS fields so registrar communications won't expose PII.
- Deferred PII collection: only collect and store full PII when strictly required (e.g., legal requests); keep it encrypted and access-controlled.
- Automated registrar calls: include the age token in requests (server-to-server) so registrar gets a cryptographically verifiable attestation without raw DOB.
Sample registrar request (pseudocode)
// POST /v1/domains/register
{
"domain": "example.eu",
"privacy": true,
"contact_alias": "alias+1234@proxy.example.com",
"age_token": "eyJhb..."
}
// Registrar must accept an attestation token; if registrar requires raw registrant PII,
// store it encrypted and restrict access. Prefer registrars that support privacy by default.
Consent, lawful basis, and minors (EU-specific)
Key points for legal compliance in 2026:
- GDPR age thresholds: the GDPR default parental consent age is 16, but Member States can lower to 13. Verify the user's country to apply the correct rule.
- Consent vs. legal obligation: for restricting access to harmful content or complying with platform rules (DSA), document the lawful basis for processing. Include consent when you store extra data or perform profiling.
- For users under the applicable threshold: implement parental verification and obtain verifiable parental consent when required. Where possible, use eIDAS or verified parental attestations and keep only the minimal consent record.
- Maintain a consent ledger: record client_id, action, timestamp, scope, and pseudonymous user identifier.
Privacy-preserving attestations and future-proofing (2026 trends)
Two approaches are gaining traction and will be mainstream in 2026:
- Verifiable Credentials (W3C): attestor issues an "age_over" credential signed with their DID. Your service validates the signature and accepts the minimal claim.
- Anonymous credentials / zero-knowledge proofs: allow an attestor to prove a user is over X without revealing exact birthdate. Expect standardized libraries and eID provider integrations by major vendors in 2026.
Security, telemetry, and audit
- Use mutual TLS for attestor webhooks and registrar callbacks.
- Sign all age tokens, rotate keys regularly, and publish a JWKS endpoint for verification.
- Log only what's necessary — audit events should be pseudonymized and retention-limited per your DPIA.
- Rate-limit verification attempts and use fraud signaling to detect synthetic or bot-driven flows.
CI/CD, testing, and deployment notes
- Run the microservice in containers (OCI) and orchestrate on Kubernetes with an API Gateway for OAuth validation.
- Use secrets managers (HashiCorp Vault, cloud KMS) for signing keys and attestor credentials.
- Create automated tests for token issuance, attestor proof validation (mock), and registrar flows (staging accounts with registrars that support sandboxing).
- Integrate checks into your pipeline for privacy controls — unit tests that assert no PII is written to certain logs or endpoints.
Operational runbook & incident playbook
Prepare for:
- Attestor compromise — revoke attestor keys and invalidate issued tokens via a short blacklist and token revocation endpoint.
- Registrar policy changes — keep a manifest of registrar capabilities (privacy flag, proxy service, sandbox endpoints).
- Regulatory inquiries — keep DPIA, data flow diagrams, and your consent ledger easily exportable for Data Protection Authorities.
Practical rule: if you do not need a piece of PII to make a decision, do not collect it.
Advanced strategies & trade-offs
Delegated verification vs in-house
Delegating to eIDAS or third-party attestors reduces compliance burden but adds dependency and cost. Running a homegrown verification (e.g., document scan) gives control but raises DPIA work and storage responsibility.
Token lifetime and revocation
Short-lived tokens (minutes to hours) limit risk but increase UX friction. Use refresh tokens for ongoing sessions and provide a revocation API for administrators.
Cross-border complexities
Implement geo-IP plus user-declared residency checks to apply correct age thresholds. Keep the ruleset externalized for easy updates as Member States change their ages of consent.
Checklist before production rollout
- Run a DPIA and document lawful basis for all processing
- Integrate with a KMS/HSM and rotate keys
- Set up JWKS endpoint so relying parties can validate tokens
- Confirm registrar sandbox flows and WHOIS privacy flags
- Implement consent ledger and retention rules (e.g., 3–12 months for logs, longer for legal holds)
- Create parental consent flows for under-threshold users
- Test attestor webhook validation and failure cases
Actionable takeaways
- Prefer verifiable credentials or zero-knowledge attestations to avoid storing birthdates.
- Issue short-lived, signed age tokens that carry only the boolean/threshold claim.
- Use registrar privacy flags and masked email aliases to protect WHOIS data during domain registration.
- Design OAuth scopes for least privilege: age:verify, age:status, registrar:manage.
- Document DPIA and implement a consent ledger as operational evidence for audits.
Further references & standards (2026)
- W3C Verifiable Credentials — recommended for minimal attestation
- EU Digital Services Act (DSA) guidance on age gating and content moderation
- eIDAS and EU digital identity pilots — for verified attestations and parental consent flows
- GDPR guidance on children’s data — check Member State age thresholds
Conclusion & call-to-action
In 2026 the balance is clear: enforce age checks, but do so in a way that minimizes privacy risk. An architecture built around privacy-preserving attestations, short-lived age tokens, clear OAuth scopes, and registrar-level WHOIS privacy flags gives you compliance and automation without needless PII exposure.
Ready to implement? Clone the sample microservice, swap the dev keys for your KMS, connect a verifiable-attestor or eID provider, and test registrar sandbox flows. If you want a production starter kit with registrar integrations and compliance templates, contact your registrar partner or check registrer.cloud’s developer resources to get up and running.
Related Reading
- The Truth About 'Prebiotic' Sodas and Your Breakfast Microbiome
- Fantasy Garden League: Build Your Own Seasonal Plant Performance Dashboard (Akin to FPL Stats)
- Reducing the $34B Identity Gap: Cost-Benefit of AI-Driven KYC vs Legacy Verification
- How Supply Chain Transparency Became a Basel ine for Investors — and Which Companies Lead the Pack
- Teenage Mutant Ninja Turtles MTG Puzzle Pack: Deck-Building Challenges
Related Topics
Unknown
Contributor
Senior editor and content strategist. Writing about technology, design, and the future of digital media. Follow along for deep dives into the industry's moving parts.
Up Next
More stories handpicked for you
Age Verification, WHOIS, and Privacy: What European TikTok Rules Mean for Domain Owners
How to Use Satellite Internet (Starlink) to Keep DNS and Domain Management Online During Blackouts
Hosting and Domain Strategies for Censored Networks: What Activists Learned from Starlink in Iran
Multi-CDN and Registrar Locking: A Practical Playbook to Eliminate Single Points of Failure
Designing Domain and DNS Resilience When Your CDN Fails: Lessons from the X Outage
From Our Network
Trending stories across our publication group