AkurAI Build
Menu

Public repository / master

AkurAI-Framework / site/frontend/otp.html

Latest change 30ab30f1996c3474188ec3dd71ba00efc5e3eb8b - feat(auth): email-OTP login flow + user roles by Ólafur Búi Ólafsson

{% include "header" %}
    <main class="container">
      <header class="page-head">
        <span class="eyebrow">Passwordless email-OTP</span>
        <h1>Sign in with a code</h1>
        <p class="lede">Enter your email and the server mints a 6-digit code, stores only a
        <em>salted hash</em> of it in the embedded B+tree (<code>data/otp.db</code>) with a
        10-minute TTL and a 5-attempt cap, then hands the code to a pluggable delivery seam.
        The framework ships no email client, so by default the code is logged
        (see <a href="/docs/auth">the auth docs</a>); an app wires a real sender. Works with
        JavaScript disabled.</p>
      </header>

      {% if error %}<div class="alert alert-danger" style="margin-bottom:18px"><strong>{{ error }}</strong></div>{% endif %}

      {% if sent %}
      <div class="alert" style="margin-bottom:18px">We sent a code to <strong>{{ form_email }}</strong>.
      Check the server log (LogDeliver) and enter it below.</div>
      <form method="post" action="/login/otp" class="card stack" style="margin-bottom:28px;max-width:420px">
        <input type="hidden" name="email" value="{{ form_email }}" />
        <label>6-digit code<input type="text" name="code" inputmode="numeric" pattern="[0-9]*" maxlength="6" placeholder="000000" autocomplete="one-time-code" required /></label>
        <div><button class="btn btn-primary" type="submit">Verify &amp; sign in</button></div>
      </form>
      <p class="muted small">Didn't get it? <a href="/login/otp">Request a new code</a>.</p>
      {% else %}
      <form method="post" action="/login/otp" class="card stack" style="margin-bottom:28px;max-width:420px">
        <label>Email<input type="email" name="email" value="{{ form_email }}" placeholder="you@example.com" autocomplete="email" required /></label>
        <div><button class="btn btn-primary" type="submit">Send me a code</button></div>
      </form>
      <p class="muted small">Prefer a password? <a href="/login">Sign in with username + password</a>.</p>
      {% endif %}
    </main>
{% include "footer" %}