Authsome ships 26 plugins. The core engine handles users, sessions, devices and RBAC; every authentication method and every policy control is a plugin you register explicitly. Nothing here is on by default, so you only carry what you use.
engine, err := authsome.NewEngine(
authsome.WithStore(store),
authsome.WithPlugin(password.New()),
authsome.WithPlugin(mfa.New(mfa.Config{Issuer: "My App"})),
)Each plugin has its own README with config, settings, endpoints and the hooks it runs on.
| You want | Use |
|---|---|
| Classic email and password sign-in | password |
| Sign in with Google, GitHub, Apple | social |
| Passwordless over email | magiclink |
| Face ID, Touch ID, YubiKey | passkey |
| Phone number and an SMS code | phone |
| A second factor on top of a password | mfa |
| Credentials for scripts and CI | apikey |
| Enterprise SSO against Okta or Entra | sso |
| To be the OAuth2 provider others sign in with | oauth2provider |
| Companies as customers, not just people | organization |
| Automated user provisioning and offboarding | scim |
| To charge for the product | subscription |
| Proof of GDPR consent | consent |
| A pre-launch signup queue | waitlist |
| Auth emails, quickly | email |
| Localised, multi-channel messages | notification |
| To block whole countries | geofence |
| To block Tor and anonymising proxies | vpndetect |
| To block known-bad IPs | ipreputation |
| To catch account takeover across continents | impossibletravel |
| Behavioural detection on login patterns | anomaly |
| A challenge when a new device appears | deviceverify |
| One risk score instead of five separate blocks | riskengine |
| Compromise signals pushed from Google or Okta | sharedsignals |
| To let an AI agent act for a user, on a leash | agentauth |
| Country and city on every session | geoip |
| Category | Plugins |
|---|---|
| Authentication | password, social, magiclink, passkey, mfa, apikey, sso, phone |
| Identity | organization, consent, subscription, waitlist |
| Communication | email, notification |
| Risk and security | anomaly, geofence, geoip, impossibletravel, ipreputation, riskengine, vpndetect, sharedsignals |
| Provisioning | scim, deviceverify, oauth2provider, agentauth |
Most plugins stand alone. These do not, and registration order matters where it says so.
geofence,vpndetectandimpossibletravelread the location thatgeoipresolves. Registergeoipfirst or they have nothing to work with.anomalyusesgeoipfor its new-country signal, and degrades quietly without it.sharedsignalsimplementsriskengine.RiskContributor. Its signals are stored either way, but nothing acts on them unlessriskengineis registered.riskenginefinds contributors automatically at init, so you rarely pass them by hand.ssoandscimscope their connections to an organisation, which meansorganization.subscriptionin organisation mode needsorganizationfor its tenants.phoneandmfashare the engine's SMS bridge. Configure it once.waitlistcontributes notification mappings thatnotificationrenders.agentauthplugs its consent gate intooauth2provider, automatically when both are registered on the same engine. Its org policy surface needsorganization.
Pick one of email or notification, not both. They hook the same events and you will send
every message twice.
Two mechanisms, and the difference matters when you are debugging.
Config is passed at construction and fixed for the life of the process. settings are
dynamic: they are declared with settings.Define, scoped global or per-app, and changeable at
runtime from the admin dashboard or the settings API. Where a plugin has both, the setting is
what actually applies. Every plugin README lists both tables.
Plugins also declare their lifecycle hooks as compile-time assertions:
var (
_ plugin.Plugin = (*Plugin)(nil)
_ plugin.BeforeSignUp = (*Plugin)(nil)
_ plugin.RouteProvider = (*Plugin)(nil)
)That block at the top of any plugin.go is the fastest answer to "when does this thing run".
See docs/content/docs/plugins/creating-plugins.mdx.
The interfaces you can implement are in plugin/plugin.go.