docs: add Phase 2 domain verification design and clarifications

Add comprehensive Phase 2 documentation:
- Complete design document for two-factor domain verification
- Implementation guide with code examples
- ADR for implementation decisions (ADR-0004)
- ADR for rel="me" email discovery (ADR-008)
- Phase 1 impact assessment
- All 23 clarification questions answered
- Updated architecture docs (indieauth-protocol, security)
- Updated ADR-005 with rel="me" approach
- Updated backlog with technical debt items

Design ready for Phase 2 implementation.

Generated with Claude Code https://claude.com/claude-code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-20 13:05:09 -07:00
parent bebd47955f
commit 6f06aebf40
10 changed files with 5605 additions and 410 deletions

View File

@@ -162,26 +162,34 @@ Accept: text/html
- Reject non-200 responses
- Log client_id fetch failures
#### Authentication Flow (v1.0.0: Email-based)
#### Authentication Flow (v1.0.0: Two-Factor Domain Verification)
1. **Domain Ownership Check**
- Check if `me` domain has verified TXT record: `_gondulf.example.com` = `verified`
- If found and cached, skip email verification
- If not found, proceed to email verification
1. **DNS TXT Record Verification (Required)**
- Check if `me` domain has TXT record: `_gondulf.{domain}` = `verified`
- Query multiple DNS resolvers (Google 8.8.8.8, Cloudflare 1.1.1.1)
- Require consensus from at least 2 resolvers
- If not found: Display error with instructions to add TXT record
- If found: Proceed to email discovery
- Proves: User controls DNS for the domain
2. **Email Verification**
- Display form requesting email address
- Validate email is at `me` domain (e.g., `admin@example.com` for `https://example.com`)
2. **Email Discovery via rel="me" (Required)**
- Fetch user's domain homepage (e.g., https://example.com)
- Parse HTML for `<link rel="me" href="mailto:user@example.com">` or `<a rel="me" href="mailto:user@example.com">`
- Extract email address from first matching mailto: link
- If not found: Display error with instructions to add rel="me" link
- If found: Proceed to email verification
- Proves: User has published email relationship on their site
- Reference: https://indieweb.org/rel-me
3. **Email Verification Code (Required)**
- Generate 6-digit verification code (cryptographically random)
- Store code in memory with 15-minute TTL
- Send code via SMTP
- Display code entry form
3. **Code Verification**
- Send code to discovered email address via SMTP
- Display code entry form showing discovered email (partially masked)
- User enters 6-digit code
- Validate code matches and hasn't expired
- Validate code matches and hasn't expired (max 3 attempts)
- Proves: User controls the email account
- Mark domain as verified (store in database)
- Proceed to authorization
4. **User Consent**
- Display authorization prompt:
@@ -208,6 +216,8 @@ Accept: text/html
Location: {redirect_uri}?code={code}&state={state}
```
**Security Model**: Two-factor verification requires BOTH DNS control AND email control. An attacker would need to compromise both to authenticate fraudulently.
#### Error Responses
Return error via redirect when possible:
@@ -404,18 +414,19 @@ Future implementation per RFC 7009.
```python
{
"email": "admin@example.com",
"email": "admin@example.com", # Discovered from rel="me", not user-provided
"code": "123456", # 6-digit string
"domain": "example.com",
"created_at": datetime,
"expires_at": datetime, # created_at + 15 minutes
"attempts": 0 # Rate limiting
"attempts": 0 # Rate limiting (max 3 attempts)
}
```
**Storage**: Python dict with TTL management
**Email Source**: Discovered from site's rel="me" link (not user input)
**Expiration**: 15 minutes
**Rate Limiting**: Max 3 attempts per email
**Rate Limiting**: Max 3 attempts per email, max 3 codes per domain per hour
**Cleanup**: Automatic expiration via TTL
### Access Token (SQLite)
@@ -448,18 +459,21 @@ CREATE TABLE tokens (
CREATE TABLE domains (
id INTEGER PRIMARY KEY AUTOINCREMENT,
domain TEXT NOT NULL UNIQUE,
verification_method TEXT NOT NULL, -- 'txt_record' or 'email'
verification_method TEXT NOT NULL, -- 'two_factor' (DNS + Email)
verified_at TIMESTAMP NOT NULL,
last_checked TIMESTAMP,
txt_record_valid BOOLEAN DEFAULT 0,
last_dns_check TIMESTAMP,
dns_txt_valid BOOLEAN DEFAULT 0,
last_email_check TIMESTAMP,
INDEX idx_domain (domain)
);
```
**Purpose**: Cache domain ownership verification
**TXT Record**: Re-verified periodically (daily)
**Email Verification**: Permanent unless admin deletes
**Verification Method**: Always 'two_factor' in v1.0.0 (DNS TXT + Email via rel="me")
**DNS TXT**: Re-verified periodically (daily check)
**Email**: NOT stored (only verification timestamp recorded)
**Re-verification**: DNS checked periodically, email re-verified on each login
**Cleanup**: Optional (admin decision)
## Security Considerations