By Mahmoud Consultancy
ValideerLeeftijd is a PSD2-powered age verification API that allows companies to reliably verify a user's age using their verified bank identity. Because banks perform KYC (Know Your Customer) checks including birth date, PSD2 gives us a trusted, privacy-friendly way to confirm age — no document uploads, no manual review.
┌─────────────────────────────────────────────────────────────┐
│ ValideerLeeftijd Platform │
├─────────────────┬───────────────────┬───────────────────────┤
│ Website │ Developer Portal │ REST API │
│ (marketing) │ (docs + keys) │ (age verification) │
│ website/ │ frontend/ │ backend/ │
│ (vanilla HTML) │ (Angular 20) │ (Spring Boot 3) │
└─────────────────┴───────────────────┴───────────────────────┘
| Component | Technology | Why | |-----------|-----------|-----| | API | Spring Boot 3, Java 17, Maven | Production-grade, matches mahmoud-consultancy | | Auth | API Keys (X-API-Key header) | Simple, stateless, easy to rotate | | PSD2 | OAuth2 PKCE + AISP | Standard PSD2 account info access | | Sessions | Redis (TTL 15 min) | Fast, no persistent storage of PII | | Developer Portal | Angular 20, standalone components | Matches mahmoud-consultancy frontend stack | | Rate Limiting | Bucket4j | In-memory, 100 req/min per IP |
Company (Client) ValideerLeeftijd API Bank (PSD2)
│ │ │
│ POST /api/v1/verify/initiate │ │
│ { minimumAge: 18, │ │
│ redirectUri: "..." } │ │
│────────────────────────────────────►│ │
│ │ │
│ ◄── { sessionId, bankRedirect } │ │
│ │ │
│ Redirect end-user to bankRedirect │ │
│────────────────────────────────────►│ │
│ │ OAuth2 PKCE Auth Request │
│ │─────────────────────────────►│
│ │ │
│ End-user logs in with bank (SCA — Strong Customer Auth)
│ │ │
│ │◄── Authorization Code │
│ │ │
│ │ Exchange code for token │
│ │─────────────────────────────►│
│ │◄── Access Token │
│ │ │
│ │ GET /aisp/accounts (birthdate)
│ │─────────────────────────────►│
│ │◄── Account holder birthdate │
│ │ │
│ │ Calculate age, store boolean│
│ │ Birth date NEVER stored │
│ │ │
│ Redirect to client redirectUri │ │
│◄────────────────────────────────────│ │
│ ?sessionId=xxx&status=completed │ │
│ │ │
│ GET /api/v1/verify/{sessionId} │ │
│────────────────────────────────────►│ │
│ │ │
│ ◄── { ageVerified: true/false } │ │
│ │ │
| Method | Path | Auth | Description |
|--------|------|------|-------------|
| POST | /api/v1/verify/initiate | X-API-Key | Start age verification session |
| GET | /api/v1/verify/{sessionId} | X-API-Key | Get verification result |
| GET | /api/v1/bank/authorize | public | Redirect to bank OAuth2 |
| GET/POST | /api/v1/bank/simulate | public | Demo bank login form |
| GET | /api/v1/bank/callback | public | Bank OAuth2 callback |
| GET | /actuator/health | public | Health check |
valideerleeftijd/
├── PLAN.md ← This file
├── CLAUDE.md ← Project rules for Claude Code
├── Makefile ← Dev/test/build/deploy targets
├── docker-compose.yml ← Local dev environment
├── backend/ ← Spring Boot 3 REST API
│ ├── pom.xml
│ ├── Dockerfile
│ └── src/main/java/nl/mahmoudconsultancy/valideerleeftijd/
│ ├── ValideerleeftijdApplication.java
│ ├── config/
│ │ ├── AppProperties.java ← @ConfigurationProperties
│ │ ├── CorsConfig.java
│ │ ├── RedisConfig.java
│ │ └── SecurityConfig.java
│ ├── controller/
│ │ ├── VerificationController.java
│ │ └── BankController.java
│ ├── dto/
│ │ ├── InitiateRequest.java
│ │ ├── InitiateResponse.java
│ │ └── VerificationStatusResponse.java
│ ├── filter/
│ │ └── ApiKeyFilter.java ← API key + rate limiting
│ ├── model/
│ │ └── VerificationSession.java ← Redis-serializable session
│ └── service/
│ ├── AgeCalculationService.java
│ └── SessionService.java
├── frontend/
│ └── valideerleeftijd-portal/ ← Angular 20 developer portal
│ ├── angular.json ← Port 4305
│ └── src/app/
│ ├── components/
│ │ ├── layout/ ← Shell with nav + footer
│ │ ├── nav/ ← Navigation bar
│ │ ├── dashboard/ ← Session stats overview
│ │ ├── api-keys/ ← API key management
│ │ ├── documentation/ ← Integration guide
│ │ └── flow-demo/ ← Interactive PSD2 flow demo
│ ├── models/session.model.ts
│ └── services/verification.service.ts
├── k8s/ ← Helm chart
│ ├── Chart.yaml
│ ├── values.yaml
│ ├── templates/
│ └── sealed-secrets/ ← Bitnami Sealed Secrets
└── .github/workflows/
├── ci-backend.yml
├── ci-frontend.yml
├── deploy-backend.yml
└── deploy-frontend.yml
Reacties