AllowID developers

Work in progress. The API and SDKs work today, but AllowID is still being built: details may change before a first stable release.

Website sign-in

Your login page shows a QR code. The person scans it with the AllowID app, sees your company's name and what you are asking for, and approves. Your server learns who signed in.

Sign-in sequence: your server creates a session, the browser shows the QR, the app approves, the browser is told, your server collects the result. Your server Browser AllowID AllowID app 1 · create_session (with your key) session_id, qr_payload, browser_token 2 · page with the widget 3 · status? (browser token) 4 · scan, approve (signed) authenticated 5 · go to /login/done 6 · get_session (with your key) subject, claims (email, …)
The browser never holds your key or the person's details: it only learns that the sign-in happened.

1. Your server starts a session§

On the request for your login page, create a session and keep its id in your own session for this browser (a cookie, your framework's session). Then put three values on the page.

# Flask
@app.get("/login")
def login():
    s = allowid_client.create_session("Sign in to Example Co", ["profession"])
    session["allowid"] = s.session_id
    return render_template("login.html", s=s)

purpose is shown to the person in the app. Keep it short and specific. The optional attributes are things the person may choose to share besides their email: profession, company, address, age_band, nationality. Ask only for what you use; each one is off until the person turns it on.

2. The page shows the QR§

Download allowid-login.js (17 KB, no dependencies) and serve it from your own site. Then one element and one script tag do the rest:

<div data-allowid-session="{{ s.session_id }}"
     data-allowid-token="{{ s.browser_token }}"
     data-allowid-qr="{{ s.qr_payload }}"
     data-allowid-redirect="/login/done"></div>
<script src="/js/allowid-login.js" defer></script>

Escape the values as you would any attribute (your template engine does). The QR payload contains quotes. When the person approves, the browser goes to /login/done. Options, events and styling are in The sign-in widget.

3. Your server collects the result§

@app.get("/login/done")
def login_done():
    r = allowid_client.get_session(session.pop("allowid", ""))
    if not r.authenticated:
        return redirect("/login")
    user = users.find_or_create(subject=r.subject, email=r.claims["email"])
    login_user(user)
    return redirect("/")

state is pending, authenticated, denied (the person declined in the app) or expired. The first get_session that returns authenticated is billed; asking again is free.

Who signed in§

Timing§

Without the widget§

If you'd rather draw the QR yourself, render qr_payload with any QR library (error correction M is fine) and poll GET /v1/sessions/{id}/status with the header X-AllowID-Browser-Token, or poll get_session from your server. Native apps and kiosks can use wait_for_session, which polls until the person has decided.

A complete example§

The JavaScript SDK has a whole working sign-in site in one file: examples/website/server.mjs in the JavaScript download. Run it with your key and sign in with your phone.