Skip to content

bettergovph/openverify

Repository files navigation

openverify

Developer-focused toolkit for integrating Philippine National ID (PhilSys) QR verification. Built on Next.js with a mobile-first UI and server APIs that mirror the official PhilSys flows—so you can embed scanning and verification into your own applications quickly.

CleanShot 2025-09-23 at 19 39 24@2x

What You Get

  • Unified verification pipeline – Detect Version 1 legacy PhilIDs and Version 3 ePhilIDs, perform signature checks, and normalize the data.
  • Server proxy to PhilSys/api/verify forwards requests to https://verify.philsys.gov.ph/api/verify with the required headers, user agent, and cookies. Optional automated session bootstrapping.
  • Image-to-QR endpoint/api/scan-image accepts uploads, extracts QR codes (Jimp + jsQR), and routes them through the same verifier.
  • Pragmatic logging[PhilSys] console diagnostics for every decoding and verification step.
  • Public eVerify support (auto-detect) – Automatically detects eVerify-style QR values (e.g., PCN or compact tokens), routes them to the public eVerify check, and handles eGovPH consent with polling.

Repository Layout

Path Purpose
src/app/page.tsx Mobile-first verification console UI
src/hooks/usePhilSysVerification.ts Client hook orchestrating legacy/ePhilID flows
src/lib/philsys/verification.ts Signature validation, CBOR decoding, formatting helpers
src/lib/philsys/session.ts PhilSys session bootstrapper and cookie cache
src/app/api/verify/route.ts Proxy to the official PhilSys /api/verify
src/app/api/scan-image/route.ts Image upload & QR decoding endpoint
src/app/api/cose/route.ts CBOR decoding smoke test
src/lib/everify/index.ts eVerify helpers: type detection, normalization, UI mapping
src/app/api/everify/check/route.ts Proxy to POST /api/pub/qr/check (public eVerify)
src/app/api/everify/egov-ph/route.ts Proxy to GET /api/pub/qr/egov_ph with result normalization

Running Locally

npm install
npm run dev

Open http://localhost:3000

Type checking:

npx tsc --noEmit

Environment Variables

Create .env.local (and .env.production for deployments) to override defaults:

Variable Description Notes
NEXT_PUBLIC_PHILSYS_PUBLIC_KEY Base64 Ed25519 public key for legacy PhilID verification Falls back to the original dump’s key if unset.
PHILSYS_VERIFY_COOKIE Optional PhilSys cookie string Include __verify-token, _ga, _ga_9P2BTMLQFL, etc. If omitted, the proxy will fetch the site once and cache issued cookies for 5 minutes.

REST Endpoints

POST /api/scan-image

Primary integration point. Send a multipart form with an image then the server extracts the QR code, runs the verification pipeline, and returns the result.

  • Form fieldfile (required)
  • Response{ qrString: string, result: VerificationResult }
curl -X POST http://localhost:3000/api/scan-image \
  -F 'file=@/path/to/qr-photo.jpg'

POST /api/verify

Forwards a normalized PhilID/ePhilID payload to the official PhilSys verifier.

curl -X POST http://localhost:3000/api/verify \
  -H 'Content-Type: application/json' \
  -d '{"d":"2022-05-11","i":"PSA","img":"","sb":{"BF":"[6,3]","DOB":"2003-05-27","PCN":"2795801750683042","POB":"City of Cabanatuan,Nueva Ecija","fn":"JARIEL","ln":"QUE","mn":"ATIENZA","s":"Male","sf":""}}'

POST /api/cose

Quick CBOR sanity check—useful for gating requests before going upstream. Returns boolean JSON.

POST /api/everify/check

Proxy to the public eVerify QR classifier. Accepts the raw scanned value and returns a normalized shape plus display-friendly fields.

  • Body{ "value": string }
  • Response{ normalized, personalInfo?, details[] }
curl -X POST http://localhost:3000/api/everify/check \
  -H 'Content-Type: application/json' \
  -d '{"value":"2795801750683042"}'

GET /api/everify/egov-ph?tracking=...

Fetches full eGovPH profile after the holder accepts consent in the official app. The UI polls this endpoint for a short window when needed.

  • Querytracking (required)
  • Response{ profile, personalInfo, details }

Verification Pipeline

  1. Detect version (checkVersion) – JSON payload ⇒ v1 (legacy), otherwise v3 (ePhilID).
    • Additionally, the client auto-detects public eVerify values (numeric PCNs or compact tokens) and routes them to the eVerify flow below.
  2. Legacy PhilID
    • Normalize payload (formatVersion1) and sanitize text.
    • Verify Ed25519 signature (verifyEddsa).
    • Format data for display (formatLegacyData / formatDisplayData).
    • Optional online check via /api/verify (results: ACTIVATED, REVOKED, etc.).
  3. ePhilID
    • Strip prefix, base45 decode, inflate, and CBOR decode (cborToJson).
    • Validate country code, convert embedded image to base64.
    • Submit to /api/verify for activation status.
  4. Result packaging – UI receives the structured data, statuses, and helper messages.
  5. Public eVerify (auto-detected)
    • POST /api/everify/check classifies the QR (e.g., National ID, National ID Signed, ePhilId, eGovPH).
    • For eGovPH, the UI enters a PENDING state and polls GET /api/everify/egov-ph?tracking=... until the profile is populated or a short timeout elapses.
    • Other types render immediately using normalized fields.

Notes on eGovPH consent

  • The production site uses Firebase Realtime Database to stream consent. This project uses short-lived HTTP polling instead (friendly to serverless deployments like Vercel).
  • A 200 response with { verified: false } or no identity fields is treated as “not ready yet” and the UI remains pending.

Troubleshooting

  • HTTP 400 from /api/verify – Cookie missing/expired. Supply a fresh PHILSYS_VERIFY_COOKIE or let the proxy bootstrap a new one (ensure outbound access).
  • hashes.sha512 not set – Restart after npm install; the verification module wires @noble/hashes on load.
  • /api/scan-image returns 422 – QR not detected. Provide clearer/larger images with the code centered.

About

eGovPH + PhilSys Verification API/Frontend

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published