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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user