CRITICAL SECURITY FIX: The authorization endpoint was bypassing domain verification entirely, allowing anyone to authenticate as any domain. Changes: - Add domain verification check in GET /authorize before showing consent - Add POST /authorize/verify-code endpoint for code validation - Add verify_code.html and verification_error.html templates - Add check_domain_verified() and store_verified_domain() functions - Preserve OAuth parameters through verification flow Flow for unverified domains: 1. GET /authorize -> Check DB for verified domain 2. If not verified: start 2FA (DNS + email) -> show code entry form 3. POST /authorize/verify-code -> validate code -> store verified 4. Show consent page 5. POST /authorize/consent -> issue authorization code Verified domains skip directly to consent page. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
52 lines
1.9 KiB
HTML
52 lines
1.9 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Verify Your Identity - Gondulf{% endblock %}
|
|
|
|
{% block content %}
|
|
<h1>Verify Your Identity</h1>
|
|
|
|
<p>To sign in as <strong>{{ domain }}</strong>, please enter the verification code sent to <strong>{{ masked_email }}</strong>.</p>
|
|
|
|
{% if error %}
|
|
<div class="error">
|
|
<p>{{ error }}</p>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<form method="POST" action="/authorize/verify-code">
|
|
<!-- Pass through authorization parameters -->
|
|
<input type="hidden" name="domain" value="{{ domain }}">
|
|
<input type="hidden" name="client_id" value="{{ client_id }}">
|
|
<input type="hidden" name="redirect_uri" value="{{ redirect_uri }}">
|
|
<input type="hidden" name="response_type" value="{{ response_type }}">
|
|
<input type="hidden" name="state" value="{{ state }}">
|
|
<input type="hidden" name="code_challenge" value="{{ code_challenge }}">
|
|
<input type="hidden" name="code_challenge_method" value="{{ code_challenge_method }}">
|
|
<input type="hidden" name="scope" value="{{ scope }}">
|
|
<input type="hidden" name="me" value="{{ me }}">
|
|
|
|
<div class="form-group">
|
|
<label for="code">Verification Code:</label>
|
|
<input type="text"
|
|
id="code"
|
|
name="code"
|
|
placeholder="000000"
|
|
maxlength="6"
|
|
pattern="[0-9]{6}"
|
|
inputmode="numeric"
|
|
autocomplete="one-time-code"
|
|
required
|
|
autofocus>
|
|
</div>
|
|
|
|
<button type="submit">Verify</button>
|
|
</form>
|
|
|
|
<p class="help-text">
|
|
Did not receive a code? Check your spam folder.
|
|
<a href="/authorize?client_id={{ client_id }}&redirect_uri={{ redirect_uri }}&response_type={{ response_type }}&state={{ state }}&code_challenge={{ code_challenge }}&code_challenge_method={{ code_challenge_method }}&scope={{ scope }}&me={{ me }}">
|
|
Request a new code
|
|
</a>
|
|
</p>
|
|
{% endblock %}
|