This commit introduces a generic authentication plugin mechanism
to the LuCI dispatcher, enabling multi-factor authentication
(MFA/2FA) and other custom verification methods without
modifying core files.
This implementation integrates with the new plugin UI architecture
introduced in commit 617f364 (luci-mod-system: implement plugin UI
architecture), allowing authentication plugins to be managed
through the unified System > Plugins interface.
Signed-off-by: Han Yiming <moebest@outlook.jp>
4.9 KiB
LuCI Authentication Plugin Example
This package demonstrates how to create authentication plugins for LuCI that integrate with the plugin UI architecture (System > Plugins).
Architecture
Authentication plugins consist of two components:
1. Backend Plugin (ucode)
Location: /usr/share/ucode/luci/plugins/auth/login/<uuid>.uc
The backend plugin implements the authentication logic. It must:
- Return a plugin object
- Provide a
check(http, user)method to determine if auth is required - Provide a
verify(http, user)method to validate the auth response - Use a 32-character hexadecimal UUID as the filename
Example structure:
return {
priority: 10, // Optional: execution order (lower = first)
check: function(http, user) {
// Return { required: true/false, fields: [...], message: '...', html: '...', assets: [...] }
},
verify: function(http, user) {
// Return { success: true/false, message: '...' }
}
};
2. UI Plugin (JavaScript)
Location: /www/luci-static/resources/view/plugins/<uuid>.js
The UI plugin provides configuration interface in System > Plugins. It must:
- Extend
baseclass - Define
class: 'auth'andtype: 'login' - Use the same UUID as the backend plugin (without .uc extension)
- Implement
addFormOptions(s)to add configuration fields - Optionally implement
configSummary(section)to show current config
Example structure:
return baseclass.extend({
class: 'auth',
class_i18n: _('Authentication'),
type: 'login',
type_i18n: _('Login'),
id: 'd0ecde1b009d44ff82faa8b0ff219cef',
name: 'My Auth Plugin',
title: _('My Auth Plugin'),
description: _('Description of what this plugin does'),
addFormOptions(s) {
// Add configuration options using form.*
},
configSummary(section) {
// Return summary string to display in plugin list
}
});
Configuration
Plugins are configured through the luci_plugins UCI config:
config global 'global'
option enabled '1' # Global plugin system
option auth_login_enabled '1' # Auth plugin class
config auth_login 'd0ecde1b009d44ff82faa8b0ff219cef'
option name 'Example Auth Plugin'
option enabled '1'
option priority '10'
option challenge_field 'verification_code'
option help_text 'Enter your code'
option test_code '123456'
Integration with Login Flow
- User enters username/password
- If password is correct,
check()is called on each enabled auth plugin - If any plugin returns
required: true, the login form shows additional fields and optional raw HTML/JS assets - User submits the additional fields
verify()is called to validate the response- If verification succeeds, session is granted
- If verification fails, user must try again
The dispatcher stores the required plugin UUID list in session state before
verification, then clears it by setting pending_auth_plugins to null after
successful verification.
Priority is configurable via luci_plugins.<uuid>.priority (lower values run first).
If changed at runtime, reload plugin cache or restart services to apply.
Raw HTML + JS Assets
Plugins may return:
html: raw HTML snippet inserted into the login formassets: script URLs for challenge UI behavior
Asset security rules:
- URLs must be under
/luci-static/plugins/<plugin-uuid>/ - Invalid asset URLs are ignored by the framework
- Keep
htmlstatic or generated from trusted values only
Generating a UUID
Use one of these methods:
# Linux
cat /proc/sys/kernel/random/uuid | tr -d '-'
# macOS
uuidgen | tr -d '-' | tr '[:upper:]' '[:lower:]'
# Online
# Visit https://www.uuidgenerator.net/ and remove dashes
Plugin Types
Common authentication plugin types:
- TOTP/OTP: Time-based one-time passwords (Google Authenticator, etc.)
- SMS: SMS verification codes
- Email: Email verification codes
- WebAuthn: FIDO2/WebAuthn hardware keys
- Biometric: Fingerprint, face recognition (mobile apps)
- Push Notification: Approve/deny on mobile device
- Security Questions: Additional security questions
Testing
- Install the plugin package
- Navigate to System > Plugins
- Enable "Global plugin system"
- Enable "Authentication > Login"
- Enable the specific auth plugin and configure it
- Log out and try logging in
- After entering correct password, you should see the auth challenge
Real Implementation Examples
For production use, integrate with actual authentication systems:
- TOTP: Use
oathtoolcommand or liboath library - SMS: Integrate with SMS gateway API
- WebAuthn: Use WebAuthn JavaScript API and verify on server
- LDAP 2FA: Query LDAP server for 2FA attributes
See Also
- LuCI Plugin Architecture: commit
617f364 - HTTP Header Plugins:
plugins/plugins-example/ - LuCI Dispatcher:
modules/luci-base/ucode/dispatcher.uc