A secure, containerized command-line authentication system written in Go. Supports user registration, bcrypt password hashing, optional TOTP-based 2FA (Google Authenticator compatible), account lockouts, and session management — all backed by an embedded SQLite database.
- Registration & Login — username/password with input validation
- Bcrypt password hashing — passwords never stored in plaintext
- TOTP 2FA — Google Authenticator compatible QR code enrollment
- Account lockout — locks after 3 consecutive failed attempts (password or 2FA)
- Session management — configurable TTL with automatic expiry on every command
- Session token hashing — tokens stored as SHA-256 hashes, not plaintext
- Tab completion — context-aware autocomplete (
register,login, etc.) - Command history — persisted across sessions via readline history file
- Zero external dependencies — pure Go SQLite, no system packages required
Requires Docker. No Go installation needed.
# Build and launch the interactive CLI
make run
# Clean up container and volumes
make cleanTo run locally without Docker:
go run cmd/app/main.go| State | Command | Description |
|---|---|---|
| Guest | register |
Create a new account |
| Guest | login |
Sign in (+ 2FA if enabled) |
| Guest | help |
List available commands |
| Guest | exit |
Quit |
| Authenticated | whoami |
Show session info |
| Authenticated | enable-2fa |
Set up TOTP authenticator |
| Authenticated | disable-2fa |
Remove TOTP |
| Authenticated | logout |
End session |
| Authenticated | help |
List available commands |
| Concern | Implementation |
|---|---|
| Password storage | bcrypt with default cost factor |
| Session tokens | UUID v4, stored as SHA-256 hash in DB |
| Brute force | Account lockout after 3 failed attempts (password + 2FA) |
| Username enumeration | Generic "invalid username or password" for all login failures |
| Duplicate registration | Pre-checks username availability before bcrypt computation |
| Expired session cleanup | Purged from DB on every login attempt |
Set via environment variables (defaults shown):
| Variable | Default | Description |
|---|---|---|
DATABASE_URL |
auth.db |
Path to the SQLite database file |
SESSION_DURATION |
5m |
How long a session stays valid |
LOCKOUT_DURATION |
1m |
How long an account stays locked |
cmd/app/main.go # Entrypoint — config, wiring, startup
internal/
auth/
service.go # DB init, auth logic, session management
service_test.go # Unit tests for the core auth service
cli/
handler.go # readline loop, command dispatch, tab completion
commands.go # register, login, 2FA, logout, whoami handlers
migration/
0001_create_users_table.up.sql
0002_create_sessions_table.up.sql
Dockerfile
docker-compose.yml
go test -v ./internal/authTests cover registration validation, password verification, failed attempt tracking, account lockout and recovery, and session lifecycle.
| Library | Purpose |
|---|---|
| chzyer/readline | Interactive prompt with history, masked passwords, tab completion |
| pquerna/otp | TOTP generation and validation (Google Authenticator compatible) |
| mdp/qrterminal | QR code rendering in the terminal |
| modernc.org/sqlite | Pure Go SQLite — no CGO, no system dependencies |
| golang.org/x/crypto | bcrypt password hashing |
| google/uuid | Cryptographically secure session token generation |