Files
homelab-mfa/README.md
T
amir 1fa7144a7b
Release APK / build (push) Successful in 1m59s
feat: login-context approval screen, one-tap Deny, stale-request expiry
- Approve now opens an in-app review screen showing app/user/IP/geo of the
  request (optional deep-link params: app, user, ip, geo, ts) before biometrics
- Add a Deny button on the approval screen (no biometric needed to reject)
- Reject requests older than 2 min via the ts param (replay safety net)
- README: context params table, new Features bullets, approve-context screenshot
- Bump to v1.2 (versionCode 3)
2026-06-21 02:44:27 +00:00

3.5 KiB

Homelab MFA

Biometric push-approval for your homelab logins. When you sign in through Authentik, your phone buzzes — approve with a fingerprint, or deny with one tap. A self-hosted alternative to Duo / Authy push, with no third-party cloud in the loop.

How it works

  1. You log in via Authentik. A flow step fires an ntfy notification to your phone with two action buttons: Approve and Deny.
  2. The buttons are homemfa://approve?token=… / homemfa://deny?token=… deep links that open this app.
  3. Approve opens an in-app review screen showing who is asking (see context params below), then triggers a biometric prompt (fingerprint / face / device PIN). On success the app POSTs approve:<token> to ntfy.khodak.me/mfa-approve; your Authentik flow is listening on that topic and completes the login. You can also Deny right from that screen.
  4. Deny POSTs deny:<token> to mfa-deny and blocks the login — no biometric needed to reject.

Optional context params

The approve link may carry extra query params so you can see what you're approving before you do:

Param Shown as Example
app 🖥 application name app=Grafana
user 👤 username user=amir
ip 📍 source IP ip=203.0.113.44
geo appended to the IP geo=Berlin, DE
ts request timestamp (epoch ms) — used to expire stale prompts after 2 min ts=1750000000000

All are optional and URL-encoded; with none present the app just shows a plain Approve / Deny prompt.

The activity is showWhenLocked + turnScreenOn, so an approval works straight from the lock screen.

Features

  • Biometric gateBIOMETRIC_STRONG or device credential required to approve (deny is instant)
  • Login context — see the app, user, source IP and geo of the request before approving
  • One-tap Deny — reject a suspicious login straight from the approval screen, no biometric needed
  • Stale-request expiry — prompts older than 2 minutes can't be approved (replay safety net)
  • Lock-screen ready — wakes the screen and shows over the keyguard
  • Self-hosted — talks only to your own ntfy instance; no Firebase, no vendor cloud
  • Zero stored secrets — stateless; each request carries a one-time token
  • Setup self-check — a "Test Biometric" button confirms enrollment before you rely on it

Screenshots

Setup / ready screen   Approval prompt with login context   Login approved

Install

  1. Download homelab-mfa.apk from the latest release
  2. On your Android phone: Settings → Apps → Install unknown apps → allow your browser/file manager
  3. Open the APK and tap Install
  4. Open Homelab MFA and tap Test Biometric to confirm your fingerprint is enrolled

Server side

You need:

  • An ntfy instance reachable at ntfy.khodak.me (or change the host in MainActivity.kt)
  • An Authentik flow that, on login, publishes a notification with the two homemfa:// action buttons, then waits on the mfa-approve / mfa-deny topics for the decision

Requirements

  • Android 9.0+ (API 28)
  • A fingerprint, face, or device PIN enrolled