Release APK / build (push) Successful in 1m59s
- 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)
74 lines
3.5 KiB
Markdown
74 lines
3.5 KiB
Markdown
# 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 gate** — `BIOMETRIC_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
|
|
|
|
<p align="center">
|
|
<img src="docs/screenshots/setup.png" width="240" alt="Setup / ready screen">
|
|
|
|
<img src="docs/screenshots/approve-context.png" width="240" alt="Approval prompt with login context">
|
|
|
|
<img src="docs/screenshots/approved.png" width="240" alt="Login approved">
|
|
</p>
|
|
|
|
## Install
|
|
|
|
1. Download `homelab-mfa.apk` from the [latest release](../../releases/latest)
|
|
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
|