Plugin Ecosystem
UAAA's plugin system allows extending authentication capabilities with custom credential providers and functionality.
Overview
Plugins are npm packages that implement the UAAA plugin interface. They can:
- Register custom credential types
- Add user claims
- Extend HTTP endpoints
- Hook into authentication flows
- Integrate external identity providers
Built-in Plugins
UAAA includes several built-in credential plugins:
password
Username/password authentication with bcrypt hashing.
Security Level: MEDIUM Configuration: Password complexity rules, bcrypt rounds
email
Email-based OTP (One-Time Password) verification.
Security Level: MEDIUM (2) Configuration: SMTP settings, OTP length, TTL
sms
SMS-based OTP verification.
Security Level: HIGH (3) Configuration: SMS gateway (Twilio, etc.), OTP settings
totp
Time-based One-Time Password (Google Authenticator).
Security Level: HIGH Configuration: Issuer name, time window
webauthn
WebAuthn/FIDO2 hardware key authentication.
Security Level: HIGH (3) Configuration: Relying Party ID, origin, timeout
External Plugins
@pku-uaaa/plugin-iaaa
Integrates PKU's IAAA (Identity Authentication and Authorization) system.
Features:
- OAuth token validation
- Direct credential authentication
- PKU identity claims mapping
- Email auto-inference
Installation:
npm install @pku-uaaa/plugin-iaaaConfiguration:
{
"plugins": ["password", "totp", "@pku-uaaa/plugin-iaaa"],
"iaaaConfig": {
"id": "app-id",
"name": "My App",
"key": "app-secret",
"redirect": "https://auth.example.com/callback"
}
}Plugin Architecture
Plugin Interface
interface IPlugin {
name: string
version: string
description?: string
license?: string
author?: string
configType?: ArkType // Config schema validation
setup(ctx: PluginContext): void | Cleanup | Promise<void | Cleanup>
}Plugin Context
class PluginContext {
app: App // Access to application instance
manager: PluginManager // Plugin manager
metadata: IPluginMetadata // Plugin metadata
}Credential Interface
Credential plugins implement CredentialImpl:
abstract class CredentialImpl {
abstract type: CredentialType
// Availability checks
showLogin(ctx: CredentialContext): Promise<ICredentialLoginInfo | null>
showVerify(ctx: CredentialContext, userId: string, targetLevel: SecurityLevel, matchedCredentials: ICredentialDoc[]): Promise<ICredentialVerifyInfo | null>
showBind(ctx: CredentialContext, userId: string): Promise<ICredentialBindInfo | null>
// Authentication operations
login?(ctx: CredentialContext, payload: unknown): Promise<ICredentialLoginResult>
verify(ctx: CredentialContext, userId: string, targetLevel: SecurityLevel, payload: unknown): Promise<ICredentialVerifyResult>
bind(ctx: CredentialContext, userId: string, credentialId: string | undefined, payload: unknown): Promise<ICredentialBindResult>
unbind(ctx: CredentialContext, userId: string, credentialId: string, payload: unknown): Promise<ICredentialUnbindResult>
// Optional: auto-provisioning
ensure?(ctx: CredentialContext, payload: unknown): Promise<ICredentialEnsureResult>
}Plugin Lifecycle
- Loading: Plugin module imported
- Validation: Config schema validated
- Setup:
setup()function called - Registration: Credentials/claims registered
- Ready: Plugin active
- Cleanup: Optional cleanup on shutdown
Installing Plugins
From npm
npm install @org/uaaa-plugin-name
# Add to config
{
"plugins": ["password", "@org/uaaa-plugin-name"]
}From Local Path
{
"plugins": ["password", "/path/to/local/plugin"]
}Shorthand Resolution
Plugin names are resolved in order:
- Exact name:
@org/plugin-name - Local path:
/path/to/plugin - Shorthand:
name→@uaaa/plugin-name - Built-in:
builtin/name
Plugin Configuration
Plugin-specific configuration is merged into main config:
{
"plugins": ["@org/plugin-custom"],
"customPluginOption": "value",
"customPluginConfig": {
"nested": "option"
}
}Plugins validate their configuration using ArkType schemas.
Developing Plugins
See Plugin Development Guide for:
- Creating credential plugins
- Registering custom claims
- Adding HTTP endpoints
- Publishing plugins
- Best practices
Plugin Examples
Simple Credential Plugin
// index.ts
import { definePlugin, CredentialImpl, SECURITY_LEVEL } from '@uaaa/server'
class MyCredImpl extends CredentialImpl {
readonly type = 'mycred'
async showLogin(ctx) {
return { recommended: false }
}
async showVerify(ctx, userId, targetLevel, matchedCredentials) {
return { recommended: true }
}
async showBind(ctx, userId) {
return { securityLevel: SECURITY_LEVEL.MEDIUM }
}
async verify(ctx, userId, targetLevel, payload) {
// Verify user with external API
const valid = await this.validateExternal(payload.token)
if (!valid) throw new Error('Invalid token')
return {
userId,
securityLevel: SECURITY_LEVEL.MEDIUM
}
}
async bind(ctx, userId, credentialId, payload) {
const newCredentialId = await ctx.manager.bindCredential(
ctx,
this.type,
userId,
credentialId,
{
userIdentifier: '',
globalIdentifier: payload.externalId,
data: '',
secret: payload.token,
remark: '',
expiration: 0
}
)
return { credentialId: newCredentialId }
}
async unbind(ctx, userId, credentialId, payload) {
await ctx.manager.unbindCredential(ctx, this.type, userId, credentialId)
return {}
}
}
export default definePlugin({
name: 'mycred',
version: '1.0.0',
setup: (ctx) => {
ctx.app.credential.provide(new MyCredImpl(ctx.app))
}
})Plugin with Custom Endpoint
export default definePlugin({
name: 'myplugin',
version: '1.0.0',
setup: (ctx) => {
// Register credential
ctx.app.credential.provide(new MyCredImpl(ctx.app))
// Add custom endpoint
ctx.app.hook('extendApp', (router) => {
router.get('/api/plugin/myplugin/data', async (c) => {
return c.json({ data: 'custom data' })
})
})
// Register custom claim
ctx.app.claim.addClaimDescriptor({
name: 'myplugin:custom_field',
description: 'Custom field from plugin',
securityLevel: SECURITY_LEVEL.LOW,
editable: false
})
}
})Plugin Discovery
Browse plugins:
Plugin Security
Best Practices:
- Validate all inputs with ArkType
- Use secure credential storage
- Avoid storing secrets in plain text
- Log security-relevant events
- Rate limit external API calls
- Handle errors gracefully
- Document security considerations
Plugin Review:
Before installing third-party plugins:
- Review source code
- Check npm downloads and stars
- Verify maintainer identity
- Test in development first
- Monitor logs after installation
Next Steps
- Developing Plugins: Create your own plugins
- Configuration: Configure plugins