▲ JUST RELEASED · v0.1.0

Auth for Go
that doesn't dictate your stack.

Limen handles sessions, cookies, and security primitives. Auth methods — credentials, OAuth providers, 2FA — drop in as plugins. Idiomatic Go, plugin-first DX, no framework lock-in.

go get github.com/thecodearcher/limen copy
idiomatic http.Handler plugin-first DX no DB tied in MIT licensed
main.go credential plugin oauth plugin
package main

import (
    "net/http"

    "github.com/thecodearcher/limen"
    "github.com/thecodearcher/limen/plugins/credential"
    "github.com/thecodearcher/limen/plugins/oauth"
)

func main() {
    // 1. configure once: sessions + cookies + security primitives
    auth := limen.New(limen.Config{
        SessionStore: limen.MemoryStore(),  // or your own
        CookieName:   "limen_session",
        SignKey:      []byte(os.Getenv("SIGN_KEY")),
    })

    // 2. compose plugins — bring only what you need
    auth.Use(credential.New(credential.Config{
        Verify: verifyUserPassword,           // you own the DB
    }))
    auth.Use(oauth.Google(oauth.GoogleConfig{
        ClientID:     os.Getenv("GOOGLE_ID"),
        ClientSecret: os.Getenv("GOOGLE_SECRET"),
    }))

    // 3. mount as a standard http.Handler — no framework imposed
    http.Handle("/auth/", auth)
    http.ListenAndServe(":8080", nil)
}
why limen

Auth that composes, not auth that configures.

Most Go auth libraries are either too thin (you write the session layer yourself) or too thick (you adopt their entire stack). Limen does the dangerous parts once and lets you bring everything else.

01 / CORE

Session, cookie, signing — handled.

The parts that are easy to get subtly wrong (cookie flags, signing rotation, CSRF binding) live in the core and stay there.

02 / PLUGINS

Auth methods are just limen.Plugin.

Credentials, OAuth, 2FA today. Magic links, passkeys, SAML when you need them. Same interface, no special cases.

03 / NO LOCK-IN

You own the database.

Limen never talks to your DB directly. You hand it a Verify func; it stays out of your model layer.

plugins shipping in v0.1

Three plugins covering the 80% case.

Each plugin is its own Go module — import what you use, nothing more.

credential 42 LoC
oauth/google 88 LoC
oauth/github 71 LoC
2fa/totp 54 LoC
passkeys soon
magic-link soon

plugins/credential

Username + password auth. Limen handles hashing, timing-safe comparison, lockout, and the session handoff. You hand it one function: "given a username + password, return a user ID."

credential.New(credential.Config{
    Verify: func(ctx context.Context, u, p string) (string, error) {
        user, err := db.FindByEmail(ctx, u)
        if err != nil { return "", err }
        if !user.CheckPassword(p) { return "", limen.ErrInvalidCreds }
        return user.ID, nil
    },
    LockoutAfter: 5,
})
honest comparison

vs. better-auth (the inspiration).

Limen owes its plugin DX to better-auth. It also makes different trade-offs because Go has different idioms.

aspect
better-auth (TS)
limen (Go)
extension surface
framework adapters + plugins
just limen.Plugin — one interface
database coupling
opinionated; expects schema
none — you hand in a Verify func
handler integration
framework-specific
stdlib http.Handler
ecosystem maturity
large, battle-tested
v0.1.0 — small, focused, growing
try it

Drop it into your next Go service.

Read the launch post for the design rationale, or jump straight to the source.

go get github.com/thecodearcher/limen copy
Open on GitHub