Forge Extension
Mount Authsome into a Forge application as a first-class extension with automatic dependency discovery and route registration.
Authsome ships a ready-made Forge extension in the extension package. It wires the engine, HTTP API, middleware, and lifecycle management into Forge's extension system with automatic discovery of optional forgery bridges.
Installation
import "github.com/xraph/authsome/extension"Registering the extension
package main
import (
"github.com/xraph/forge"
"github.com/xraph/authsome/extension"
)
func main() {
app := forge.New()
authExt := extension.New(
extension.WithGroveDatabase(""), // resolve default grove.DB from DI
)
app.RegisterExtension(authExt)
app.Run()
}Or with an explicit store:
import pgstore "github.com/xraph/authsome/store/postgres"
authExt := extension.New(
extension.WithEngineOption(authsome.WithStore(pgstore.New(db))),
)What the extension does
| Lifecycle event | Behaviour |
|---|---|
Register | Loads configuration, auto-discovers bridges from DI, builds the engine, registers it in the container |
Start | Runs store.Migrate (unless disabled), initializes plugins, auto-registers strategies |
RegisterRoutes | Mounts all Authsome HTTP endpoints on the Forge router |
Middlewares | Returns the auth middleware for global application to all routes |
Stop | Calls engine.Stop -- emits OnShutdown to all plugins |
Extension options
| Option | Type | Default | Description |
|---|---|---|---|
WithConfig(cfg) | Config | defaults | Full config struct |
WithPlugin(p) | plugin.Plugin | -- | Register a plugin (repeatable) |
WithPlugins(ps...) | ...plugin.Plugin | -- | Register multiple plugins |
WithEngineOption(opt) | authsome.Option | -- | Pass engine option directly |
WithEngineOptions(opts...) | ...authsome.Option | -- | Pass multiple engine options |
WithDisableRoutes() | -- | false | Skip HTTP route registration |
WithDisableMigrate() | -- | false | Skip migrations on Start |
WithBasePath(path) | string | "/v1/auth" | URL prefix for all auth routes |
WithGroveDatabase(name) | string | "" | Name of the grove.DB to resolve from DI |
WithRequireConfig(b) | bool | false | Require config in YAML files |
WithLogger(l) | log.Logger | Forge logger | Custom logger |
Auto-discovered bridges
When running inside a Forge app, the extension automatically discovers optional bridges from the DI container. You do not need to configure these manually -- they are resolved if the corresponding extension is registered.
| Bridge | Discovered from | Purpose |
|---|---|---|
| Chronicle | chronicle.Emitter | Audit trail logging |
| Warden | *warden.Engine | RBAC/ReBAC/ABAC authorization |
| Keysmith | *keysmith.Engine | API key management |
| Relay | *relay.Relay | Webhook event delivery |
| Herald | *herald.Herald | Multi-channel notifications |
| Dispatch | *dispatch.Engine | Background job queue |
| Ledger | *ledger.Ledger | Billing and metering |
| Vault | *vault.Vault | Secrets and feature flags |
| Grove DB | *grove.DB | Database (PostgreSQL, SQLite, MongoDB) |
If a bridge is not found in the container, a no-op implementation is used automatically.
File-based configuration (YAML)
The extension loads configuration from YAML config files. It looks for config under these keys (in order):
extensions.authsome-- standard Forge extension config namespaceauthsome-- top-level shorthand
Example YAML config
# forge.yaml
extensions:
authsome:
base_path: "/v1/auth"
disable_routes: false
disable_migrate: false
grove_database: ""
debug: false
session:
token_ttl: "1h"
refresh_token_ttl: "720h"
max_active_sessions: 0
rotate_refresh_token: true
password:
min_length: 8
require_uppercase: true
require_lowercase: true
require_digit: true
bcrypt_cost: 12
algorithm: "bcrypt"
rate_limit:
enabled: true
signin_limit: 5
signup_limit: 3
window_seconds: 60
lockout:
enabled: true
max_attempts: 5
lockout_duration_seconds: 900
reset_after_seconds: 3600
mailer:
provider: "resend"
resend:
api_key: "${RESEND_API_KEY}"
from: "noreply@example.com"Merge behaviour
File-based configuration is merged with programmatic options. Programmatic boolean flags (DisableRoutes, DisableMigrate, Debug) always win when set to true. For other fields, YAML values take precedence, then programmatic values, then defaults.
Accessing the engine from other extensions
After Register is called by Forge, authExt.Engine() returns the fully initialized engine:
eng := authExt.Engine()
// Use eng.Store(), eng.Plugins(), etc. from another extension.Or resolve the engine from the DI container:
import (
"github.com/xraph/vessel"
authsome "github.com/xraph/authsome"
)
eng, err := vessel.Inject[*authsome.Engine](app.Container())Adding plugins
Register plugins that provide additional authentication methods:
import (
"github.com/xraph/authsome/extension"
"github.com/xraph/authsome/plugins/social"
"github.com/xraph/authsome/plugins/mfa"
"github.com/xraph/authsome/plugins/passkey"
"github.com/xraph/authsome/plugins/magiclink"
"github.com/xraph/authsome/plugins/phone"
)
authExt := extension.New(
extension.WithGroveDatabase(""),
extension.WithPlugins(
social.New(
social.WithGoogle(googleID, googleSecret),
social.WithGitHub(ghID, ghSecret),
),
mfa.New(),
passkey.New(passkey.Config{
RPName: "My App",
RPID: "example.com",
Origin: "https://example.com",
}),
magiclink.New(),
phone.New(),
),
)Auth middleware
The extension automatically registers global authentication middleware via Middlewares(). This middleware:
- Reads the
Authorization: Bearer <token>header - Validates the token (opaque lookup or JWT validation)
- Falls back to the strategy registry (API keys, etc.) when session resolution fails
- Sets the authenticated user and session on the request context
Other extensions can access the authenticated user via the Forge scope:
import "github.com/xraph/forge"
func handler(w http.ResponseWriter, r *http.Request) {
scope := forge.ScopeFromContext(r.Context())
userID := scope.UserID()
orgID := scope.OrgID()
}Grove database integration
Using the default grove database
ext := extension.New(
extension.WithGroveDatabase(""),
)Using a named grove database
ext := extension.New(
extension.WithGroveDatabase("authsome"),
)Store resolution order
- Explicit store -- if
WithEngineOption(authsome.WithStore(s))was called, it is used directly. - Grove database -- if
WithGroveDatabase(name)was called, the named or defaultgrove.DBis resolved from DI. - Auto-discovery -- if neither is configured, the extension attempts to resolve a default
grove.DBfrom the container.
Dashboard integration
When the Forge Dashboard extension is present, Authsome automatically registers as the dashboard's authentication provider:
- Provides sign-in and sign-up pages for the dashboard
- Handles session checking and user resolution
- Contributes "Profile" and "Security" items to the user dropdown menu
- Renders user management pages in the dashboard