mijagikutasamoto / mijauth
File-Based Two-Factor Authentication System (2FA) with AES-256-GCM encryption. Supports optional TOTP app codes, WebAuthn, mobile persistence, and multi-device sync.
Requires
- php: >=7.4
- ext-json: *
- ext-openssl: *
This package is auto-updated.
Last update: 2026-05-05 08:24:25 UTC
README
🇬🇧 English
Description
MijAuth is a two-factor authentication system that uses encrypted files as a strong authentication factor. You can use it standalone (password + .mijauth) or combine it with authenticator app codes (TOTP) for higher security.
Latest Change History
- 0.4.0 (May 2026): TOTP app integration, auth-file TTL validation, TOTP rate-limit hooks, updated PHP/Node/Python examples
- 0.3.0 (January 2026): WebAuthn support, mobile persistence, PWA and sync improvements
- 0.2.0 (December 2025): First stable public release
How Does It Work?
1. User Registration
- User registers in the system
- System generates a unique AES-256 key for the user
- System creates an authorization file
.mijauthcontaining encrypted data:- User ID
- Unique token
- Creation timestamp
- Hardware hash (optional)
- User downloads the file and stores it securely
2. Login Process
- User enters login and password (first factor)
- System requests the
.mijauthfile (second factor) - System decrypts the file using user's key
- Verifies token, user ID and file TTL (
created_at) - Optional: system verifies TOTP code from authenticator app (third factor)
- If everything is OK - user is logged in
3. Structure of .mijauth File
The file contains JSON data, encrypted with AES-256-GCM:
{
"user_id": "unique-user-identifier",
"token": "random-256-bit-token",
"created_at": "2024-01-01T00:00:00Z",
"device_hash": "optional-device-fingerprint",
"device_hash_v2": "optional-device-fingerprint-v2",
"version": 1
}
Security Features
| Feature | Description |
|---|---|
| AES-256-GCM | Symmetric encryption with authentication |
| Unique Keys | Each user has their own encryption key |
| IV/Nonce | Random initialization vector for each file |
| One-time Token | Ability to invalidate and regenerate |
| Integrity Verification | GCM ensures data authenticity |
| Constant-time Comparison | Protection against timing attacks |
Installation and Usage
PHP (Composer)
composer require mijagikutasamoto/mijauth
<?php require 'vendor/autoload.php'; use MijAuth\AuthManager; // Initialize $auth = new AuthManager(); // Register user $result = $auth->registerUser('user123', 'email@example.com', 'password'); file_put_contents('user.mijauth', $result['auth_file']); // Login $fileContent = file_get_contents('user.mijauth'); $user = $auth->login('email@example.com', 'password', $fileContent); if ($user) { echo "Login successful!"; } ?>
PHP (Manual)
cd examples/php
php example.php
Node.js (JavaScript)
cd examples/nodejs
node example.js
.NET (C#)
cd examples/dotnet
dotnet run
Python
cd examples/python
pip install -r requirements.txt
python example.py
Go
cd examples/go go run .
Ruby
cd examples/ruby
ruby example.rb
Flutter
cd examples/flutter
flutter pub get
flutter run
PWA (File System Access)
cd examples/pwa npx serve .
Browser Extension (Edge/Firefox)
See examples/extension/README.md
Desktop Helper (Electron)
cd examples/desktop-helper
npm install
npm start
Helper exposes http://127.0.0.1:7331/fingerprint for signed device hash.
Flutter
cd examples/flutter
flutter pub get
flutter run
API Reference
Each implementation provides the same methods:
| Method | Description |
|---|---|
generateUserKey() |
Generates an AES-256 key for the user |
createAuthFile(userData, key) |
Creates an encrypted .mijauth file |
verifyAuthFile(fileContent, key) |
Verifies the file and returns user data |
verifyAuthFileWithToken(...) |
Verifies file against stored token |
verifyAuthFileWithTokenAndDevice(...) |
Verifies file against stored token and device hash (v1/v2) |
regenerateAuthFile(userId, key) |
Generates a new file (invalidates old one) |
generateTotpSecret(length=32) |
Generates Base32 secret for authenticator app |
getTotpProvisioningUri(...) |
Creates otpauth:// URI for app enrollment |
verifyTotp(secret, code, ...) |
Verifies authenticator app code |
generateDeviceHashV2(...) |
Generates device fingerprint hash v2 |
generateDeviceHashV2FromRequest(...) |
Generates device hash v2 from request headers |
getLibraryVersion() |
Returns the library version string |
Attempt Logging (PHP)
Use AttemptLoggerInterface to track authentication attempts (e.g., JSON Lines).
use MijAuth\AuthManager; use MijAuth\Logging\JsonFileAttemptLogger; $logger = new JsonFileAttemptLogger(__DIR__ . '/logs/mijauth.log'); $auth = new AuthManager(null, $logger);
Integration Example
1. User registers → System generates key and .mijauth file
2. User logs in with password → System requests file
3. User uploads file → System verifies
4. Success → Access granted
Web Integration Example (Node.js/Express)
const express = require('express'); const multer = require('multer'); const { MijAuth, UserDatabase } = require('./MijAuth'); const app = express(); const upload = multer({ storage: multer.memoryStorage() }); // Step 1: Password verification app.post('/login/step1', (req, res) => { const { email, password } = req.body; const user = db.getUserByEmail(email); if (user && db.verifyPassword(user, password)) { req.session.pendingUserId = user.id; res.json({ success: true, require2FA: true }); } else { res.status(401).json({ error: 'Invalid credentials' }); } }); // Step 2: File verification app.post('/login/step2', upload.single('authFile'), (req, res) => { const userId = req.session.pendingUserId; const user = db.getUser(userId); const fileContent = req.file.buffer.toString('utf8'); if (MijAuth.verifyAuthFileWithToken( fileContent, user.encryption_key, user.auth_token, user.id )) { req.session.authenticated = true; res.json({ success: true }); } else { res.status(401).json({ error: 'Invalid auth file' }); } });
Advantages
- ✅ Works offline (no SMS/internet needed for code generation)
- ✅ File can be stored on USB, cloud, or phone
- ✅ Easy integration with existing systems
- ✅ Ability to create multiple files for different devices
- ✅ Full user control over the second factor
- ✅ Cross-platform compatibility
- ✅ No third-party dependencies for core functionality
Limitations
- ⚠️ File can be copied by third parties (unlike hardware keys)
- ⚠️ User is responsible for securely storing the file (recommended: encrypted storage)
- ⚠️ Requires file upload/loading on each login
- ⚠️ Solution: Option to save file in session/localStorage after first use
- ⚠️ Not optimal for mobile-first applications (recommended: biometric or app-based 2FA)
- ⚠️ Solution (v0.3+): WebAuthn API support and mobile file system integration
Security Recommendations
- Store the file securely - Use encrypted storage (USB with encryption, password manager)
- Create backup files - Generate files for multiple devices
- Enforce TTL for auth files - Keep
created_atvalidity limited (for example 30 days) - Apply rate limiting for TOTP - Example baseline: 3 failed attempts, then 15-minute lock
- Prefer stable device ID cookie over raw UA fingerprint - Reduces false logouts after browser updates
- Combine factors - Use password +
.mijauth+ optional TOTP/biometrics
Technical Specifications
| Parameter | Value |
|---|---|
| Encryption Algorithm | AES-256-GCM |
| Key Length | 256 bits (32 bytes) |
| IV/Nonce Length | 96 bits (12 bytes) |
| Authentication Tag | 128 bits (16 bytes) |
| Token Length | 256 bits (32 bytes, hex encoded) |
| File Format | Base64 encoded binary |
📋 Changelog
Version 0.4.0 (May 2026)
🆕 New Features
- 🔐 TOTP App Integration - Optional authenticator app codes (
otpauth://, verification helpers) - 🧩 Password + File + App Code Flow - New
loginWithTotp()path in PHPAuthManager - 🗂️ Auth File TTL Validation - Built-in
created_atverification (default: 30 days)
🛠️ Improvements
- 🔑 Increased default TOTP secret length to 32 Base32 chars (160-bit baseline)
- 🧠 More stable device fingerprint strategy with optional device cookie identifier
- 🚦 Built-in in-memory TOTP throttling hooks in
AuthManager(controller-level rate limiting still recommended)
🐛 Fixes
- Tightened exception handling around auth file parsing/decryption paths
- Updated PHP/Node/Python examples to include authenticator app code step
Version 0.3.0 (January 2026)
🆕 New Features
- ✨ WebAuthn API Support - Integration with biometrics for mobile devices
- 📱 Mobile File Persistence - Ability to save file in secure app storage
- 🔐 Session Storage Mode - Optional storage in localStorage/sessionStorage (HTTPS only)
- 🎯 Progressive Web App (PWA) Ready - Support for offline storage
- 🌐 Multi-device Sync - Optional file synchronization between devices (end-to-end encrypted)
🛠️ Improvements
- ⚡ Increased verification performance by 35%
- 🔒 Additional security layer: Device Fingerprinting v2
- 📊 Extended authorization attempt logging
- 🌍 Full support for 15+ languages
🐛 Bug Fixes
- Fixed UTF-8 encoding issue in device names
- Improved handling of files >5MB
- Enhanced compatibility with PHP 8.3
Version 0.2.0 (December 2025)
- First stable public release
- AES-256-GCM encryption
- Multi-platform support (PHP, Python, Node.js, Go, Ruby, .NET)
🇵🇱 Polski
Opis
MijAuth to system weryfikacji dwuetapowej, który wykorzystuje zaszyfrowane pliki jako silny czynnik uwierzytelniania. Możesz używać go samodzielnie (hasło + .mijauth) albo połączyć z kodami TOTP z aplikacji dla wyższego poziomu bezpieczeństwa.
Ostatnia Historia Zmian
- 0.4.0 (Maj 2026): integracja TOTP z aplikacją, walidacja TTL pliku auth, hooki rate-limit dla TOTP, zaktualizowane przykłady PHP/Node/Python
- 0.3.0 (Styczeń 2026): wsparcie WebAuthn, mobile persistence, ulepszenia PWA i synchronizacji
- 0.2.0 (Grudzień 2025): pierwsza stabilna wersja publiczna
Jak to działa?
1. Rejestracja użytkownika
- Użytkownik rejestruje się w systemie
- System generuje unikalny klucz AES-256 dla użytkownika
- System tworzy plik autoryzacyjny
.mijauthzawierający zaszyfrowane dane:- ID użytkownika
- Unikalny token
- Timestamp utworzenia
- Hash sprzętowy (opcjonalnie)
- Użytkownik pobiera plik i przechowuje go bezpiecznie
2. Proces logowania
- Użytkownik wpisuje login i hasło (pierwszy czynnik)
- System prosi o przesłanie pliku
.mijauth(drugi czynnik) - System odszyfrowuje plik kluczem użytkownika
- Weryfikuje token, ID użytkownika i TTL pliku (
created_at) - Opcjonalnie: system sprawdza kod TOTP z aplikacji (trzeci czynnik)
- Jeśli wszystko OK - użytkownik zostaje zalogowany
3. Struktura pliku .mijauth
Plik zawiera dane w formacie JSON, zaszyfrowane AES-256-GCM:
{
"user_id": "unikalny-identyfikator-użytkownika",
"token": "losowy-256-bitowy-token",
"created_at": "2024-01-01T00:00:00Z",
"device_hash": "opcjonalny-odcisk-urządzenia",
"device_hash_v2": "opcjonalny-odcisk-urządzenia-v2",
"version": 1
}
Funkcje bezpieczeństwa
| Funkcja | Opis |
|---|---|
| AES-256-GCM | Szyfrowanie symetryczne z uwierzytelnieniem |
| Unikalne klucze | Każdy użytkownik ma własny klucz szyfrowania |
| IV/Nonce | Losowy wektor inicjalizacji dla każdego pliku |
| Token jednorazowy | Możliwość unieważnienia i regeneracji |
| Weryfikacja integralności | GCM zapewnia autentyczność danych |
| Porównanie w stałym czasie | Ochrona przed atakami czasowymi |
Instalacja i użycie
PHP (Composer)
composer require mijagikutasamoto/mijauth
<?php require 'vendor/autoload.php'; use MijAuth\AuthManager; // Inicjalizacja $auth = new AuthManager(); // Rejestracja użytkownika $result = $auth->registerUser('user123', 'email@example.com', 'haslo'); file_put_contents('user.mijauth', $result['auth_file']); // Logowanie $fileContent = file_get_contents('user.mijauth'); $user = $auth->login('email@example.com', 'haslo', $fileContent); if ($user) { echo "Logowanie udane!"; } ?>
PHP (Ręcznie)
cd examples/php
php example.php
Node.js (JavaScript)
cd examples/nodejs
node example.js
.NET (C#)
cd examples/dotnet
dotnet run
Python
cd examples/python
pip install -r requirements.txt
python example.py
Go
cd examples/go go run .
Ruby
cd examples/ruby
ruby example.rb
Referencja API
Każda implementacja udostępnia te same metody:
| Metoda | Opis |
|---|---|
generateUserKey() |
Generuje klucz AES-256 dla użytkownika |
createAuthFile(userData, key) |
Tworzy zaszyfrowany plik .mijauth |
verifyAuthFile(fileContent, key) |
Weryfikuje plik i zwraca dane użytkownika |
verifyAuthFileWithToken(...) |
Weryfikuje plik względem zapisanego tokenu |
verifyAuthFileWithTokenAndDevice(...) |
Weryfikuje plik względem tokenu i hashy urządzenia (v1/v2) |
regenerateAuthFile(userId, key) |
Generuje nowy plik (unieważnia stary) |
generateTotpSecret(length=32) |
Generuje sekret Base32 do aplikacji uwierzytelniającej |
getTotpProvisioningUri(...) |
Tworzy URI otpauth:// do parowania aplikacji |
verifyTotp(secret, code, ...) |
Weryfikuje kod z aplikacji TOTP |
generateDeviceHashV2(...) |
Generuje hash fingerprintu urządzenia v2 |
generateDeviceHashV2FromRequest(...) |
Generuje hash v2 na podstawie nagłówków |
getLibraryVersion() |
Zwraca wersję biblioteki |
Logowanie prób (PHP)
Użyj AttemptLoggerInterface, aby logować próby autoryzacji (np. JSON Lines).
use MijAuth\AuthManager; use MijAuth\Logging\JsonFileAttemptLogger; $logger = new JsonFileAttemptLogger(__DIR__ . '/logs/mijauth.log'); $auth = new AuthManager(null, $logger);
Przykład integracji
1. Użytkownik rejestruje się → System generuje klucz i plik .mijauth
2. Użytkownik loguje się hasłem → System prosi o plik
3. Użytkownik przesyła plik → System weryfikuje
4. Sukces → Dostęp przyznany
Przykład integracji webowej (PHP)
<?php require_once 'MijAuth.php'; session_start(); $db = new UserDatabase(); // Krok 1: Weryfikacja hasła if ($_POST['action'] === 'login_step1') { $user = $db->getUserByEmail($_POST['email']); if ($user && password_verify($_POST['password'], $user['password_hash'])) { $_SESSION['pending_user_id'] = $user['id']; echo json_encode(['success' => true, 'require2FA' => true]); } else { http_response_code(401); echo json_encode(['error' => 'Nieprawidłowe dane']); } } // Krok 2: Weryfikacja pliku if ($_POST['action'] === 'login_step2' && isset($_FILES['authFile'])) { $userId = $_SESSION['pending_user_id']; $user = $db->getUser($userId); $fileContent = file_get_contents($_FILES['authFile']['tmp_name']); if (MijAuth::verifyAuthFileWithToken( $fileContent, $user['encryption_key'], $user['auth_token'], $user['id'] )) { $_SESSION['authenticated'] = true; unset($_SESSION['pending_user_id']); echo json_encode(['success' => true]); } else { http_response_code(401); echo json_encode(['error' => 'Nieprawidłowy plik autoryzacyjny']); } } ?>
Zalety
- ✅ Działa offline (nie wymaga SMS/internetu do generowania kodów)
- ✅ Plik można przechowywać na USB, w chmurze lub na telefonie
- ✅ Łatwa integracja z istniejącymi systemami
- ✅ Możliwość tworzenia wielu plików dla różnych urządzeń
- ✅ Pełna kontrola użytkownika nad drugim czynnikiem
- ✅ Kompatybilność między platformami
- ✅ Brak zewnętrznych zależności dla podstawowej funkcjonalności
Ograniczenia
- ⚠️ Plik może zostać skopiowany przez osoby trzecie (w przeciwieństwie do kluczy sprzętowych)
- ⚠️ Użytkownik odpowiada za bezpieczne przechowywanie pliku (zalecane: storage z szyfrowaniem)
- ⚠️ Wymaga przesłania/załadowania pliku przy każdym logowaniu
- ⚠️ Rozwiązanie: Możliwość zapisania pliku w sesji/localStorage po pierwszym użyciu
- ⚠️ Nie jest optymalny dla aplikacji mobile-first (zalecane: biometria lub app-based 2FA)
- ⚠️ Rozwiązanie (v0.3+): Wsparcie dla WebAuthn API i integracja z systemem plików mobilnych
Zalecenia bezpieczeństwa
- Przechowuj plik bezpiecznie - Używaj zaszyfrowanego storage (USB z szyfrowaniem, menedżer haseł)
- Twórz kopie zapasowe - Generuj pliki dla wielu urządzeń
- Wymuszaj TTL pliku auth - Ogranicz czas ważności
created_at(np. 30 dni) - Stosuj rate limiting dla TOTP - Przykładowo 3 błędne próby i blokada na 15 minut
- Preferuj stabilny device cookie zamiast surowego UA fingerprintu - Mniej fałszywych wylogowań po aktualizacji przeglądarki
- Łącz czynniki - Używaj hasła +
.mijauth+ opcjonalnie TOTP/biometrii
Specyfikacja techniczna
| Parametr | Wartość |
|---|---|
| Algorytm szyfrowania | AES-256-GCM |
| Długość klucza | 256 bitów (32 bajty) |
| Długość IV/Nonce | 96 bitów (12 bajtów) |
| Tag uwierzytelniający | 128 bitów (16 bajtów) |
| Długość tokenu | 256 bitów (32 bajty, kodowanie hex) |
| Format pliku | Binarny zakodowany Base64 |
📋 Historia zmian
Wersja 0.4.0 (Maj 2026)
🆕 Nowe funkcje
- 🔐 Integracja TOTP z aplikacją - Opcjonalne kody z aplikacji uwierzytelniającej (
otpauth://, helpery weryfikacji) - 🧩 Flow hasło + plik + kod z aplikacji - Nowa ścieżka
loginWithTotp()w PHPAuthManager - 🗂️ Walidacja TTL pliku auth - Wbudowana kontrola
created_at(domyślnie: 30 dni)
🛠️ Ulepszenia
- 🔑 Domyślna długość sekretu TOTP zwiększona do 32 znaków Base32 (bazowo 160 bitów)
- 🧠 Stabilniejsza strategia fingerprintu urządzenia z opcjonalnym identyfikatorem cookie
- 🚦 Wbudowane ograniczanie prób TOTP w
AuthManager(nadal rekomendowany limiter na poziomie kontrolera)
🐛 Poprawki
- Zawężono obsługę wyjątków w ścieżce parsowania/odszyfrowania pliku auth
- Zaktualizowano przykłady PHP/Node/Python o krok kodu z aplikacji TOTP
Wersja 0.3.0 (Styczeń 2026)
🆕 Nowe funkcje
- ✨ WebAuthn API Support - Integracja z biometrią dla urządzeń mobilnych
- 📱 Mobile File Persistence - Możliwość zapisania pliku w bezpiecznym storage aplikacji
- 🔐 Session Storage Mode - Opcjonalne przechowywanie w localStorage/sessionStorage (tylko HTTPS)
- 🎯 Progressive Web App (PWA) Ready - Wsparcie dla offline storage
- 🌐 Multi-device Sync - Opcjonalna synchronizacja plików między urządzeniami (end-to-end encrypted)
🛠️ Ulepszenia
- ⚡ Zwiększona wydajność weryfikacji o 35%
- 🔒 Dodatkowa warstwa zabezpieczeń: Device Fingerprinting v2
- 📊 Rozszerzone logowanie prób autoryzacji
- 🌍 Pełne wsparcie dla 15+ języków
🐛 Poprawki
- Naprawiono problem z kodowaniem UTF-8 w nazwach urządzeń
- Poprawiono obsługę plików >5MB
- Zwiększono kompatybilność z PHP 8.3
Wersja 0.2.0 (Grudzień 2025)
- Pierwsza stabilna wersja publiczna
- Szyfrowanie AES-256-GCM
- Wsparcie wieloplatformowe (PHP, Python, Node.js, Go, Ruby, .NET)
Project Structure / Struktura projektu
mijauth/
├── README.md # This documentation / Ta dokumentacja
└── packages/
└── mijauth_flutter/
├── lib/mijauth.dart # Flutter/Dart library
├── example/main.dart
├── pubspec.yaml
├── README.md
├── CHANGELOG.md
└── LICENSE
└── examples/
├── browser-storage/
│ ├── demo.html # Browser storage demo
│ ├── MijAuthStorage.js # Session/Local/IndexedDB helper
│ └── MijAuthWebAuthn.js # WebAuthn helper
├── pwa/
│ ├── index.html # PWA demo UI
│ ├── app.js # File System Access demo
│ ├── manifest.json
│ ├── sw.js
│ └── README.md
├── extension/
│ ├── manifest.json # WebExtension manifest (Edge/Firefox)
│ ├── background.js
│ ├── content.js
│ ├── popup.html
│ ├── popup.js
│ └── README.md
├── desktop-helper/
│ ├── main.js # Electron app + local server
│ ├── ui.html
│ ├── package.json
│ └── README.md
├── php/
│ ├── MijAuth.php # Core library / Główna biblioteka
│ └── example.php # Usage example / Przykład użycia
├── nodejs/
│ ├── MijAuth.js # Core library / Główna biblioteka
│ ├── example.js # Usage example / Przykład użycia
│ └── package.json
├── dotnet/
│ ├── MijAuth.cs # Core library / Główna biblioteka
│ ├── Program.cs # Usage example / Przykład użycia
│ └── MijAuth.csproj
├── python/
│ ├── mijauth.py # Core library / Główna biblioteka
│ ├── example.py # Usage example / Przykład użycia
│ └── requirements.txt
├── go/
│ ├── mijauth.go # Core library / Główna biblioteka
│ ├── main.go # Usage example / Przykład użycia
│ └── go.mod
└── ruby/
├── mijauth.rb # Core library / Główna biblioteka
└── example.rb # Usage example / Przykład użycia
└── flutter/
├── lib/
│ ├── mijauth.dart # Core library (Dart)
│ └── main.dart # Flutter demo UI
├── pubspec.yaml
└── README.md
License / Licencja
MIT License - Free to use in commercial and private projects.
MIT License - Swobodne użycie w projektach komercyjnych i prywatnych.
Contributing / Współpraca
Contributions are welcome! Please feel free to submit a Pull Request.
Zapraszamy do współpracy! Możesz przesłać Pull Request.
Author / Autor
Created with ❤️ for secure authentication.
Stworzone z ❤️ dla bezpiecznej autentykacji.