Something went wrong. Try again.
Caddy module to require at-proto authentication and restrict routes to DIDs
Something went wrong. Try again.
caddy-atproto-auth global.go
3.9 kB · 157 lines
Go
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158package caddyatprotoauth
import ( "fmt" "net" "path/filepath" "strconv" "time"
"github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" "github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
"tangled.org/vvill.dev/caddy-atproto-auth/internal/db")
func init() { caddy.RegisterModule(&App{}) httpcaddyfile.RegisterGlobalOption("atproto", parseGlobalAtproto)}
// App configures the global atproto integration.type App struct { StoragePath string `json:"storage_path,omitempty"` CookieSecret string `json:"cookie_secret,omitempty"` SessionDurationStr string `json:"session_duration,omitempty"` OAuthManagerCacheSize int `json:"oauth_manager_cache_size,omitempty"` AllowPrivateCIDRs []net.IPNet `json:"allow_private_cidrs,omitempty"`
// Internal state Store *db.Store `json:"-"` SessionDuration time.Duration `json:"-"`}
// CaddyModule returns the Caddy module information.func (*App) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "atproto", New: func() caddy.Module { return new(App) }, }}
// Provision sets up the global app state.func (a *App) Provision(ctx caddy.Context) error { // Defaults if a.StoragePath == "" { a.StoragePath = filepath.Join(caddy.AppDataDir(), "atproto.db") }
// Initialize DB store, err := db.NewStore(a.StoragePath) if err != nil { return fmt.Errorf("failed to initialize atproto storage: %w", err) } a.Store = store
// Resolve Cookie Secret if a.CookieSecret == "" { // Try to load/generate from DB secret, err := a.Store.GetCookieSecret(ctx) if err != nil { return fmt.Errorf("failed to resolve cookie secret: %w", err) } a.CookieSecret = secret }
// Parse session duration a.SessionDuration = 24 * 7 * time.Hour if a.SessionDurationStr != "" { d, err := caddy.ParseDuration(a.SessionDurationStr) if err != nil { return fmt.Errorf("invalid session_duration: %w", err) } a.SessionDuration = time.Duration(d) }
if a.OAuthManagerCacheSize <= 0 { a.OAuthManagerCacheSize = 100 // Default max oauth managers }
return nil}
// Start starts the application.func (a *App) Start() error { return nil}
// Stop stops the application.func (a *App) Stop() error { if a.Store != nil { return a.Store.Close() } return nil}
// Interface guardsvar ( _ caddy.App = (*App)(nil) _ caddy.Provisioner = (*App)(nil))
// parseGlobalAtproto parses the global 'atproto' Caddyfile option.// Format://// atproto {// storage_path /path/to/db// cookie_secret <secret>// }func parseGlobalAtproto(d *caddyfile.Dispenser, _ any) (any, error) { app := &App{} for d.Next() { for d.NextBlock(0) { switch d.Val() { case "storage_path": if !d.NextArg() { return nil, d.ArgErr() } app.StoragePath = d.Val() case "cookie_secret": if !d.NextArg() { return nil, d.ArgErr() } app.CookieSecret = d.Val() case "session_duration": if !d.NextArg() { return nil, d.ArgErr() } app.SessionDurationStr = d.Val() case "oauth_manager_cache_size": if !d.NextArg() { return nil, d.ArgErr() } val, err := strconv.Atoi(d.Val()) if err != nil { return nil, d.Errf("invalid oauth_manager_cache_size: %v", err) } app.OAuthManagerCacheSize = val case "allow_private_cidrs": for _, c := range d.RemainingArgs() { _, ipnet, err := net.ParseCIDR(c) if err != nil || ipnet == nil { return nil, d.ArgErr() } app.AllowPrivateCIDRs = append(app.AllowPrivateCIDRs, *ipnet) } default: return nil, d.Errf("unrecognized subdirective '%s'", d.Val()) } } } return httpcaddyfile.App{ Name: "atproto", Value: caddyconfig.JSON(app, nil), }, nil}