A Next.js application demonstrating passwordless authentication using BSV (Bitcoin SV) certificates with privacy-preserving age verification through selective disclosure. This project showcases how users can authenticate and prove their age without revealing unnecessary personal information.
- Passwordless Authentication: Login using BSV certificates instead of passwords
- Privacy-Preserving Age Verification: Uses selective disclosure to reveal ONLY age, keeping all other personal data private
- Age-Gated Content: Demo whiskey & cigars store requiring 18+ verification
- Cross-Platform Compatibility: Certificates work across multiple applications in the same trust circle
- DID Certificate Support: W3C-compliant Decentralized Identifiers for identity management
- Age Verification Certificate Integration: Seamless onboarding flow for certificate issuance
- Docker Deployment: Containerized application with GitHub Actions CI/CD
- Wallet Connection: User connects BSV wallet via
WalletClient - Certificate Retrieval: App requests certificates using certifier public key
- Selective Disclosure: Only the age field is made accessible through verifier keyring
- Privacy-Preserving Decryption: Uses master keyring with selective fields to decrypt ONLY age
- Age Verification: Validates user meets minimum age requirement (18+)
- Access Granted: User can access age-gated content while maintaining privacy
-
AgeVerificationGuard (
src/components/AgeVerificationGuard.js)- Implements privacy-preserving age verification
- Uses selective disclosure to access only age field
- Redirects to Age Verification Onboarding if no valid certificate
-
WhiskeyCigarsStore (
src/components/WhiskeyCigarsStore.js)- Demo age-gated content requiring 18+ verification
- Shows practical application of age verification
-
Wallet Context (
src/context/walletContext.js)- Manages BSV wallet connection and authentication
- Handles identity key retrieval
-
DID Context (
src/context/DidContext.js)- Manages DID certificate checking and validation
- Handles W3C DID resolution
-
Auth Context (
src/context/authContext.js)- Stores authentication state and certificate data
- Manages user session
- Node.js 18+ installed
- BSV wallet with valid certificates (MetaNet Desktop recommended)
- Access to Age Verification Onboarding for certificate issuance
-
Clone the repository:
git clone https://github.com/your-org/cert-landing-page.git cd cert-landing-page -
Install dependencies:
npm install
-
Configure environment variables: Create a
.env.localfile with the following:# Required - Certificate verification public key NEXT_PUBLIC_SERVER_PUBLIC_KEY=024c144093f5a2a5f71ce61dce874d3f1ada840446cebdd283b6a8ccfe9e83d9e4 # Required - CS Onboarding URL for certificate issuance NEXT_PUBLIC_COMMON_SOURCE_URL=https://common-source-onboarding.vercel.app # Optional - Server private key for certificate operations SERVER_PRIVATE_KEY=your_private_key_here # Optional - BSV wallet storage service WALLET_STORAGE_URL=https://store-us-1.bsvb.tech/ # Optional - BSV network (main or test) CHAIN=main
For complete environment variable documentation, see Environment Variables section below.
-
Run the development server:
npm run dev
-
Open http://localhost:3000 in your browser
npm run dev # Start development server
npm run build # Build for production
npm start # Start production server
npm run lint # Run ESLint for code qualityThis application implements BRC-29 compliant selective disclosure for privacy protection:
-
Traditional Approach (Privacy Risk):
// β Decrypts ALL certificate fields const decryptedFields = await MasterCertificate.decryptFields( wallet, certificate.keyring, certificate.fields, certificate.certifier ); // Exposes: username, email, residence, gender, work, age, etc.
-
Our Privacy-Preserving Approach:
// β Creates verifier keyring for ONLY age field const verifierKeyring = await MasterCertificate.createKeyringForVerifier( wallet, certificate.certifier, verifierPublicKey, certificate.fields, ['age'], // Only age field! certificate.keyring, certificate.serialNumber ); // β Decrypts using master keyring + selective fields const decryptedFields = await MasterCertificate.decryptFields( wallet, certificate.keyring, // Master keyring verifiableCertificate.fields, // Only age field from selective disclosure certificate.certifier ); // Result: ONLY age is accessible, all other data remains private
- Certificate Verification: All certificates are cryptographically verified
- Selective Field Access: Users control which data fields are revealed
- Encrypted Storage: Personal data encrypted until authorized decryption
- No Password Storage: Eliminates password-related vulnerabilities
| Variable | Description | Example |
|---|---|---|
NEXT_PUBLIC_SERVER_PUBLIC_KEY |
Public key for certificate verification | 024c144093f5a2a5f71ce61dce874d3f1ada840446cebdd283b6a8ccfe9e83d9e4 |
NEXT_PUBLIC_COMMON_SOURCE_URL |
CommonSource Onboarding URL | https://common-source-onboarding.vercel.app |
| Variable | Description | Default |
|---|---|---|
SERVER_PRIVATE_KEY |
Server's BSV private key | - |
WALLET_STORAGE_URL |
BSV wallet storage service | https://store-us-1.bsvb.tech/ |
CHAIN |
BSV network (main/test) | main |
| Variable | Description |
|---|---|
NEXT_PUBLIC_SERVER_DID |
Server's DID identifier |
DID_TOPIC |
DID topic for resolution |
VC_TOPIC |
Verifiable Credential topic |
OVERLAY_SERVICE_URL |
Overlay service for DID resolution |
CMSRC_PROTOCOL_ID |
Protocol identifier |
Verifies BSV certificates and validates claims.
Request:
{
"certificate": {...},
"userIdentityKey": "public_key",
"verificationLevel": "comprehensive",
"requireCryptographicProof": false
}Response:
{
"verificationResult": {
"valid": true,
"claims": {...},
"verificationDetails": [...]
}
}Resolves DID to retrieve user data from overlay network.
Request:
{
"did": "did:bsv:example",
"fields": ["age", "username"]
}Retrieves user certificates with selective disclosure.
Request:
{
"fieldsToReveal": ["age"]
}# Build the Docker image
docker build -t cert-landing-page .
# Run the container
docker run -p 8080:8080 \
-e NEXT_PUBLIC_SERVER_PUBLIC_KEY=your_key \
-e NEXT_PUBLIC_COMMON_SOURCE_URL=https://common-source-onboarding.vercel.app \
cert-landing-pageThe project includes automated Docker builds via GitHub Actions:
- Triggers on: Tags (
v*), main branch pushes, and pull requests - Publishes to GitHub Container Registry (ghcr.io)
- Workflow file:
.github/workflows/docker-publish.yml
src/
βββ app/
β βββ api/
β β βββ verify-certificate/ # Certificate verification
β β βββ resolve-did/ # DID resolution
β β βββ get-certificates/ # Certificate retrieval
β βββ page.js # Main application
β βββ layout.js # App layout
β βββ globals.css # Global styles
βββ components/
β βββ AgeVerificationGuard.js # Age verification logic
β βββ WhiskeyCigarsStore.js # Demo age-gated content
β βββ toasts.js # Notifications
β βββ ui/ # UI components
βββ context/
β βββ walletContext.js # Wallet management
β βββ DidContext.js # DID management
β βββ authContext.js # Auth state
βββ lib/
βββ ageVerification.js # Age verification utilities
βββ vcDataResolver.js # VC data resolution
βββ bsv/
βββ BsvDidService.js # DID operations
βββ BsvVcService.js # VC operations
- Initial Visit: Access the application at http://localhost:3000
- Age Gate: You'll see the age verification screen
- No Certificate: Click "Get Verified" to redirect to Age Verification Onboarding
- Complete Onboarding: Fill in your details (ensure age is 18+)
- Return: After certificate issuance, return to the application
- Automatic Verification: The app will verify your age using selective disclosure
- Access Granted: Browse the demo whiskey & cigars store
Applications can integrate this authentication system by:
- Using the same certifier public key for verification
- Implementing selective disclosure for privacy
- Following BRC-29 standards for certificate handling
- Maintaining compatible encryption/decryption protocols
- BRC-42: BSV Key Derivation Scheme
- BRC-29: Selective Disclosure Protocol
- BRC-103: Identity Certificates
- W3C DID: Decentralized Identifiers v1.0
- Always use plan mode to create implementation plans
- Write plans to
.claude/tasks/TASK_NAME.md - Research latest package versions and best practices
- Get plan approval before implementation
- Follow existing code conventions
- Use established libraries (check package.json first)
- Maintain privacy-first approach
- Run lint checks before committing
This project is part of the CS BSV ecosystem. Please refer to the project license for usage terms.
For questions or issues:
- Create an issue in the repository
- Contact the BSV development team
- Check CS documentation
Note: This is a demonstration application showcasing privacy-preserving age verification. For production use, ensure proper security audits, key management, and compliance with relevant regulations.