Introduction
In response to the European Commission's findings that Meta is in breach of the Digital Services Act for failing to keep children off Facebook and Instagram, this tutorial will teach you how to implement age verification systems using modern web technologies. This is a crucial skill for developers building platforms that must comply with regulations like the GDPR and DSA. We'll create a practical age verification system that can be integrated into social media platforms to prevent underage access.
Prerequisites
- Basic understanding of JavaScript and Node.js
- Knowledge of REST APIs and HTTP requests
- Familiarity with MongoDB or similar database systems
- Basic understanding of JWT (JSON Web Tokens)
- Node.js installed on your system
- Basic knowledge of frontend development (HTML/CSS/JavaScript)
Step-by-step Instructions
Step 1: Set up the Project Structure
First, we'll create our project directory and initialize the Node.js application with necessary dependencies.
1.1 Create Project Directory
mkdir age-verification-system
cd age-verification-system
npm init -y
1.2 Install Required Dependencies
npm install express mongoose bcryptjs jsonwebtoken dotenv cors helmet
Why: Express.js provides the web framework, Mongoose handles MongoDB interactions, bcryptjs for password hashing, JWT for authentication tokens, and other packages for security and API handling.
Step 2: Configure Environment Variables
Create a .env file to store sensitive configuration data.
2.1 Create .env File
PORT=3000
MONGODB_URI=mongodb://localhost:27017/ageverification
JWT_SECRET=your-super-secret-jwt-key-here
NODE_ENV=development
2.2 Create Configuration File
const dotenv = require('dotenv');
dotenv.config();
module.exports = {
port: process.env.PORT || 3000,
mongodbUri: process.env.MONGODB_URI || 'mongodb://localhost:27017/ageverification',
jwtSecret: process.env.JWT_SECRET || 'your-super-secret-jwt-key-here',
nodeEnv: process.env.NODE_ENV || 'development'
};
Why: This separation of configuration from code ensures security and makes deployment easier across different environments.
Step 3: Create Database Models
Define the user and verification models to store user information and age verification data.
3.1 Create User Model
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
dateOfBirth: { type: Date, required: true },
ageVerified: { type: Boolean, default: false },
verifiedAt: { type: Date }
}, { timestamps: true });
module.exports = mongoose.model('User', userSchema);
3.2 Create Verification Request Model
const mongoose = require('mongoose');
const verificationRequestSchema = new mongoose.Schema({
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
verificationType: { type: String, enum: ['document', 'parental_consent'], required: true },
status: { type: String, enum: ['pending', 'approved', 'rejected'], default: 'pending' },
submittedAt: { type: Date, default: Date.now },
verifiedAt: { type: Date }
}, { timestamps: true });
module.exports = mongoose.model('VerificationRequest', verificationRequestSchema);
Why: These models ensure we can track user age verification and maintain compliance with EU regulations by storing verification data.
Step 4: Implement Authentication Middleware
Create middleware to verify user authentication and age verification status.
4.1 Create Auth Middleware
const jwt = require('jsonwebtoken');
const User = require('../models/User');
const config = require('../config');
const authenticate = async (req, res, next) => {
try {
const token = req.header('Authorization')?.replace('Bearer ', '');
if (!token) {
return res.status(401).json({ message: 'Access denied. No token provided.' });
}
const decoded = jwt.verify(token, config.jwtSecret);
const user = await User.findById(decoded._id).select('-password');
if (!user) {
return res.status(401).json({ message: 'Invalid token.' });
}
req.user = user;
next();
} catch (error) {
res.status(401).json({ message: 'Invalid token.' });
}
};
const requireAgeVerification = (req, res, next) => {
if (!req.user.ageVerified) {
return res.status(403).json({
message: 'Age verification required to access this resource.'
});
}
next();
};
module.exports = { authenticate, requireAgeVerification };
Why: This middleware ensures that only verified users can access certain parts of the application, which is essential for compliance with age restrictions.
Step 5: Create Age Verification API Endpoints
Build the core API endpoints for handling age verification requests.
5.1 Create Verification Routes
const express = require('express');
const router = express.Router();
const { authenticate, requireAgeVerification } = require('../middleware/auth');
const User = require('../models/User');
const VerificationRequest = require('../models/VerificationRequest');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const config = require('../config');
// Register user with date of birth
router.post('/register', async (req, res) => {
try {
const { username, email, password, dateOfBirth } = req.body;
// Check if user already exists
const existingUser = await User.findOne({ email });
if (existingUser) {
return res.status(400).json({ message: 'User already exists' });
}
// Hash password
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);
// Create user
const user = new User({
username,
email,
password: hashedPassword,
dateOfBirth
});
await user.save();
res.status(201).json({ message: 'User created successfully' });
} catch (error) {
res.status(500).json({ message: error.message });
}
});
// Submit verification request
router.post('/verify', authenticate, async (req, res) => {
try {
const { verificationType } = req.body;
const verificationRequest = new VerificationRequest({
userId: req.user._id,
verificationType
});
await verificationRequest.save();
res.status(201).json({
message: 'Verification request submitted',
requestId: verificationRequest._id
});
} catch (error) {
res.status(500).json({ message: error.message });
}
});
// Verify user age (admin endpoint)
router.put('/verify/:id', authenticate, async (req, res) => {
try {
const { id } = req.params;
const { status } = req.body;
const verificationRequest = await VerificationRequest.findById(id);
if (!verificationRequest) {
return res.status(404).json({ message: 'Verification request not found' });
}
// Update verification status
verificationRequest.status = status;
verificationRequest.verifiedAt = new Date();
await verificationRequest.save();
// Update user age verification status
if (status === 'approved') {
await User.findByIdAndUpdate(verificationRequest.userId, {
ageVerified: true,
verifiedAt: new Date()
});
}
res.json({ message: 'Verification status updated' });
} catch (error) {
res.status(500).json({ message: error.message });
}
});
module.exports = router;
Why: These endpoints handle the complete verification flow, from user registration to verification approval, ensuring compliance with EU regulations.
Step 6: Create Frontend Interface
Build a simple frontend to demonstrate how users would interact with the age verification system.
6.1 Create HTML Interface
<!DOCTYPE html>
<html>
<head>
<title>Age Verification System</title>
</head>
<body>
<div id="app">
<h1>Age Verification System</h1>
<div id="register-section">
<h2>Register</h2>
<input type="text" id="username" placeholder="Username"><br>
<input type="email" id="email" placeholder="Email"><br>
<input type="password" id="password" placeholder="Password"><br>
<input type="date" id="dob" placeholder="Date of Birth"><br>
<button onclick="registerUser()">Register</button>
</div>
<div id="verification-section" style="display:none;">
<h2>Age Verification</h2>
<button onclick="submitVerification()">Submit Verification</button>
<button onclick="logout()">Logout</button>
</div>
</div>
<script>
let authToken = null;
async function registerUser() {
const username = document.getElementById('username').value;
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;
const dob = document.getElementById('dob').value;
const response = await fetch('/api/auth/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, email, password, dateOfBirth: dob })
});
const data = await response.json();
alert(data.message);
}
async function submitVerification() {
const response = await fetch('/api/verification/verify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${authToken}`
}
});
const data = await response.json();
alert(data.message);
}
function logout() {
authToken = null;
document.getElementById('verification-section').style.display = 'none';
document.getElementById('register-section').style.display = 'block';
}
</script>
</body>
</html>
Why: This frontend interface demonstrates how users would interact with the system, showing the complete age verification workflow that platforms like Facebook and Instagram must implement.
Step 7: Test the System
Run the application and test the age verification functionality.
7.1 Start the Server
node server.js
7.2 Test Endpoints
Use tools like Postman or curl to test the API endpoints:
# Register a user
POST http://localhost:3000/api/auth/register
{
"username": "testuser",
"email": "[email protected]",
"password": "password123",
"dateOfBirth": "2000-01-01"
}
# Verify user age
PUT http://localhost:3000/api/verification/verify/REQUEST_ID
{
"status": "approved"
}
Why: Testing ensures that our implementation works correctly and can be used to comply with EU regulations regarding underage access to social media platforms.
Summary
In this tutorial, we've built a comprehensive age verification system that can be used by social media platforms to comply with EU regulations like the Digital Services Act. The system includes user registration, verification request submission, and verification status management. This implementation helps platforms like Facebook and Instagram meet their legal obligations to prevent underage access to their services.
Key components of our system include:
- Database models for users and verification requests
- Authentication middleware to protect resources
- Age verification API endpoints
- Frontend interface demonstrating user interaction
This system provides a foundation for implementing age verification compliance that can be expanded with additional features like document verification, parental consent flows, and integration with external verification services.



