Authsome

Plugin Architecture

How Authsome's plugin system extends the engine with authentication strategies, hooks, routes, and migrations.

Authsome is built around a composable plugin architecture. Every authentication method, lifecycle behavior, and integration point is implemented as a plugin that registers itself with the engine. The core engine provides session management, user storage, and the hook bus -- plugins add everything else.

The Plugin interface

Every plugin must implement the base Plugin interface:

type Plugin interface {
    Name() string
}

The Name() method returns a unique identifier used for logging, debugging, and registry deduplication. Beyond this single required method, plugins opt into capabilities by implementing additional interfaces.

Capability interfaces

Plugins declare what they can do by implementing zero or more of the following interfaces:

InterfacePurpose
OnInitCalled during engine.Start() to capture engine references
OnShutdownCalled during graceful shutdown
RouteProviderRegisters additional HTTP routes on the Forge router
MigrationProviderContributes database migration groups for plugin tables
StrategyProviderContributes an authentication strategy to the strategy registry
AuthMethodContributorReports which auth methods are linked to a user
AuthMethodUnlinkerSupports unlinking an auth method from a user account
DataExportContributorContributes data to GDPR user exports
ExtensibleAccepts sub-plugins for compositional plugin design

Hook interfaces

Plugins can subscribe to lifecycle events by implementing hook interfaces. Before-hooks can abort the operation by returning an error. After-hooks are fire-and-forget -- errors are logged but never block the pipeline.

Auth event hooks

InterfaceTrigger
BeforeSignUp / AfterSignUpUser account creation
BeforeSignIn / AfterSignInAuthentication attempt
BeforeSignOut / AfterSignOutSession termination

User lifecycle hooks

InterfaceTrigger
BeforeUserCreate / AfterUserCreateUser record creation
BeforeUserUpdate / AfterUserUpdateUser record update
BeforeUserDelete / AfterUserDeleteUser record deletion

Session lifecycle hooks

InterfaceTrigger
BeforeSessionCreate / AfterSessionCreateSession creation
AfterSessionRefreshToken refresh
AfterSessionRevokeSession revocation

Organization lifecycle hooks

InterfaceTrigger
AfterOrgCreate / AfterOrgUpdate / AfterOrgDeleteOrganization CRUD
AfterMemberAdd / AfterMemberRemove / AfterMemberRoleChangeMembership changes

Plugin registry

The plugin.Registry is the core dispatch mechanism. It type-caches plugins at registration time so that emit calls iterate only over plugins implementing the relevant hook -- there is no runtime type assertion on the hot path.

registry := plugin.NewRegistry(logger)
registry.Register(passwordPlugin)
registry.Register(mfaPlugin)
registry.Register(socialPlugin)

// During sign-up, only plugins implementing BeforeSignUp are called:
err := registry.EmitBeforeSignUp(ctx, req)

Lifecycle

When you call engine.Start(), the following sequence executes:

  1. Registration -- Plugins passed via WithPlugin() are registered with the plugin registry. Each plugin is type-asserted into all applicable hook caches.
  2. Migration -- The engine collects migration groups from all MigrationProvider plugins and runs them alongside core schema migrations.
  3. Initialization -- The registry calls OnInit(ctx, engine) on every plugin that implements OnInit. Plugins use this to capture store references, bridge handles, and other engine capabilities.
  4. Strategy registration -- Plugins implementing StrategyProvider have their strategies auto-registered with the strategy registry.
  5. Route registration -- Plugins implementing RouteProvider have their HTTP routes registered on the Forge router.

Built-in plugins

Authsome ships with 14 built-in plugins:

PluginPackageDescription
passwordplugins/passwordEmail/password sign-up and sign-in with bcrypt or argon2id hashing
emailplugins/emailEmail notifications for welcome, verification, and password reset
magiclinkplugins/magiclinkPasswordless authentication via emailed magic links
mfaplugins/mfaMulti-factor authentication with TOTP, SMS OTP, and recovery codes
passkeyplugins/passkeyFIDO2/WebAuthn passkey registration and authentication
socialplugins/socialOAuth2 social login (Google, GitHub, Microsoft, Apple, custom)
ssoplugins/ssoEnterprise SSO via OIDC and SAML
oauth2providerplugins/oauth2providerOAuth2 authorization server (Authorization Code + PKCE, Client Credentials)
organizationplugins/organizationOrganization, member, and team management with invitations
consentplugins/consentGDPR consent tracking with grant, revoke, and audit trail
phoneplugins/phonePhone number verification and OTP-based authentication
notificationplugins/notificationMulti-channel notifications via Herald bridge
apikeyplugins/apikeyAPI key generation, scoping, rotation, and authentication strategy
devicedeviceDevice fingerprinting, trust management, and session binding

Example: registering plugins

import (
    "github.com/xraph/authsome"
    "github.com/xraph/authsome/plugins/password"
    "github.com/xraph/authsome/plugins/mfa"
    "github.com/xraph/authsome/plugins/social"
)

eng, err := authsome.NewEngine(
    authsome.WithStore(store),
    authsome.WithPlugin(password.New()),
    authsome.WithPlugin(mfa.New(mfa.Config{Issuer: "MyApp"})),
    authsome.WithPlugin(social.New(social.Config{
        Providers: []social.Provider{
            social.NewGoogle(googleCfg),
            social.NewGitHub(githubCfg),
        },
    })),
)

Plugins are initialized in registration order. If plugin B depends on state set by plugin A during OnInit, register A first.

On this page