Abstract
HHTTPS (Human-verified HTTPS) is an open protocol that adds a cryptographic proof-of-personhood layer on top of HTTPS. It allows web servers to verify that an HTTP request was initiated by a real human — without storing personally identifiable information.
The protocol combines three established standards: WebAuthn (W3C) for human presence verification, ES256-signed JWTs (RFC 7519) for portable claims, and JWKS (RFC 7517) for distributed verification. Adoption requires no central authority — any operator can run an HHTTPS issuer compatible with this spec.
Design Principles
- Zero PII storage. The issuer never stores name, address, or contact data. Only public keys, hashed identifiers, and ephemeral session state.
- No central authority. Anyone can run an HHTTPS issuer. Tokens are verified against the issuer's public JWKS — no API key exchange, no rate-limited validation calls.
- Standards over invention. WebAuthn, JWT, JWKS — all W3C/IETF standards. No proprietary cryptography. No new threat model.
- European by default. GDPR-compliant by design. eIDAS-aware. Servers in the EU. No US cloud lock-in.
- Roles, not identities. A token claims a role (e.g.
medical_professional) and trust score (0–100), not a person. - Revocable. Tokens can be revoked via the issuer; revocation status is published in real-time at
/hhttps/revoke/status.
API Endpoints
All endpoints listed are part of the v0.4.1 reference implementation at
hhttps.org. Custom prefixes are permitted; .well-known/hhttps-configuration
is the source of truth for endpoint paths.
Discovery
WebAuthn Flow
PublicKeyCredentialCreationOptions.Token Operations
Token Format
An HHTTPS access token is a standard JWT (RFC 7519) signed with ES256. The payload contains claims about the verified human's role and trust level.
{
"jti": "550e8400-e29b-41d4-a716-446655440000",
// unique token identifier
"iss": "hhttps://hhttps.org",
"sub": "human-verified",
"human": true,
"actorType": "human",
"role": "medical_professional",
"roleLevel": "approbation-id",
"trustScore": 93,
"method": "webauthn-passkey",
"deviceType": "singleDevice",
"ia": 1715242800,
"exp": 1715246400
}
Tokens are short-lived (1 hour by default). Refresh tokens (7 days) allow
extension without repeated WebAuthn challenges. Both can be revoked via
/hhttps/revoke.
HTTP Headers
HHTTPS responses set the following headers, exposing verification status to client-side code and intermediaries:
HHTTPS-Protocol-Version: 0.4.1 HHTTPS-Status: verified HHTTPS-Human: true HHTTPS-Actor-Type: human HHTTPS-Role: medical_professional HHTTPS-Role-Level: approbation-id HHTTPS-Trust-Score: 93 HHTTPS-Method: webauthn-passkey HHTTPS-Issuer: hhttps://hhttps.org
Trust Scoring
Each verification method maps to a numeric trust score (0–100). Verifiers choose a minimum threshold based on their use case — a comment section may accept 30+, a medical-advice forum may require 90+.
See the full mapping in roles.js. Higher methods strictly imply lower ones (a score of 93 also satisfies any threshold ≤ 93).
Integration
Verifying tokens requires no API call to the issuer — only the public JWKS, which can be cached for hours. Below: minimal Express middleware example.
import jwt from 'jsonwebtoken'; import jwksClient from 'jwks-rsa'; const jwks = jwksClient({ jwksUri: 'https://hhttps.org/.well-known/jwks.json', cache: true, cacheMaxAge: 3600000 }); function requireHuman({ minTrust = 60, allowedRoles = null } = {}) { return async (req, res, next) => { const token = req.headers['hhttps-token']; if (!token) return res.status(401).json({ error: 'token required' }); try { const decoded = await new Promise((resolve, reject) => { jwt.verify(token, getKey, { algorithms: ['ES256'] }, (e, d) => e ? reject(e) : resolve(d)); }); if (decoded.trustScore < minTrust) throw new Error('trust too low'); if (allowedRoles && !allowedRoles.includes(decoded.role)) throw new Error('role denied'); req.hhttps = decoded; next(); } catch (e) { res.status(401).json({ error: e.message }); } }; } // Use it on any route: app.post('/medical-advice', requireHuman({ minTrust: 90, allowedRoles: ['medical_professional'] }), postAdvice );
Reference SDKs are available for JavaScript and Python, with examples for Express, Flask, Django, and FastAPI.
"Sign in with HHTTPS" button
Beyond JWT verification, HHTTPS provides a full OpenID Connect 1.0 flow. Your platform can offer a "Sign in with HHTTPS" button that lets users authenticate with their Passkey and bring along a verified role plus trust score — without sharing any PII with your platform.
Subjects are pairwise: each client sees a different stable identifier for the same user, so users cannot be tracked across platforms. PKCE is mandatory for public clients (no client secret required).
const verifier = crypto.randomBytes(32).toString('base64url'); const challenge = crypto.createHash('sha256').update(verifier).digest('base64url'); const state = crypto.randomBytes(16).toString('base64url'); req.session.pkceVerifier = verifier; req.session.oauthState = state; const params = new URLSearchParams({ response_type: 'code', client_id: 'your-client-id', redirect_uri: 'https://your-site.com/auth/callback', scope: 'openid role verification_method', state, code_challenge: challenge, code_challenge_method: 'S256' }); res.redirect(`https://hhttps.org/hhttps/oauth/authorize?${params}`);
const tokenRes = await fetch('https://hhttps.org/hhttps/oauth/token', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ grant_type: 'authorization_code', code: req.query.code, redirect_uri: 'https://your-site.com/auth/callback', client_id: 'your-client-id', code_verifier: req.session.pkceVerifier }) }); const { access_token, id_token } = await tokenRes.json(); // id_token is a JWT with: sub, role, role_label, trust_score, // verification_method, nonce, exp, iat, iss, aud
Register your platform as an OAuth client by inserting a row into
oauth_clients on the HHTTPS server (currently manual — public
registration UI is on the roadmap). Discovery document at
/.well-known/openid-configuration.
Real-world example: ask.iamhmn.org is a Q&A platform that uses this exact flow. Source code on GitHub.
Machine tokens — for bots and automated agents
HHTTPS recognizes that not all useful traffic comes from humans. Bots,
AI agents, and automated services can register as machine operators
and obtain tokens that carry a transparent actorType: 'bot' claim.
Platforms can then treat machines and humans uniformly while keeping the
difference visible to users.
In pilot mode, bots self-declare their role (no verification — no industry standard for AI agent identity yet exists). Role-based logic on the platform still applies, just as it does for human OAuth tokens.
curl -X POST https://hhttps.org/hhttps/machine/register \ -H "Content-Type: application/json" \ -d '{ "operatorName": "MyBot", "purpose": "Answers technical questions on ask.iamhmn.org", "role": "developer", "contactEmail": "ops@example.com", "operatorUrl": "https://example.com/bot" }' # Response (save apiKey — shown only once): # { "operatorId": "op-...", "apiKey": "mk-...", "role": "developer", ... }
curl -X POST https://hhttps.org/hhttps/machine/token \ -H "Content-Type: application/json" \ -d '{ "operatorId": "op-...", "apiKey": "mk-..." }' # Returns: { "token": "eyJ...", "expiresAt": "..." } # Token claims include: sub=machine, human=false, actorType=bot, # operatorId, operatorName, purpose, role
Verify machine tokens the same way as human tokens — same JWKS, same ES256
signature. Distinguish them by the actorType claim.
Token TTL is short (5 minutes by default) so bots refresh frequently —
this gives the issuer the ability to revoke abusive operators quickly.
Discovery
Any HHTTPS issuer publishes its configuration at
/.well-known/hhttps-configuration. Clients use this to discover
endpoints without hard-coding URLs:
{
"issuer": "hhttps://hhttps.org",
"protocol_version": "0.4.1",
"jwks_uri": "https://hhttps.org/.well-known/jwks.json",
"check_endpoint": "https://hhttps.org/hhttps/check",
"registration_endpoint": "https://hhttps.org/hhttps/webauthn/register/start",
"authentication_endpoint": "https://hhttps.org/hhttps/webauthn/auth/start",
"revocation_endpoint": "https://hhttps.org/hhttps/revoke",
"supported_algorithms": ["ES256"],
"supported_roles": ["citizen", "journalist", ..., "craftsman"],
"token_ttl": 3600,
"refresh_ttl": 604800
}
Security Considerations
- Private keys never leave the user's device. WebAuthn enforces this in hardware (TPM, Secure Enclave, YubiKey).
- Issuer signing keys must be rotated periodically. JWKS supports multi-key publishing for seamless rotation.
- The token's
jtiis logged at issuance and removed at expiration. Revocation persists permanently. - Replay protection: each WebAuthn ceremony uses a fresh server-generated challenge.
- The
RP_IDbinds passkeys to a specific origin. A token issued athhttps.orgcannot be authenticated against a different origin. - Rate-limiting is applied per IP at all sensitive endpoints (registration, authentication, email, revocation).
- For maximum trust, issuers SHOULD publish a transparency log of issued/revoked token hashes (planned for v0.5).
Governance & License
The HHTTPS specification and reference implementation are released under the European Union Public Licence (EUPL-1.2) — an OSI-approved license compatible with GPLv3, AGPLv3, MPLv2, and most permissive licenses, with explicit GDPR alignment.
The protocol is maintained by the HumanProof Initiative (github.com/dhannus/HumanProof), an unfunded civic-tech project. Anyone may propose changes via pull request. Major specification revisions require public discussion period (≥ 30 days).
An IETF Internet-Draft is in preparation. Once stable, the protocol will be submitted for standardization through the IETF process — independent of the reference implementation.
Initiative contact: daniel.hannuschka@tweakz.de · Press & institutional inquiries welcome.