Common user management and authentication package.

Name Last Update
email Loading commit data...
httperr Loading commit data...
templates Loading commit data...
vendor Loading commit data...
.gitlab-ci.yml Loading commit data...
README.md Loading commit data...
actions.go Loading commit data...
client.go Loading commit data...
handlers.go Loading commit data...
ratelimit.go Loading commit data...
ratelimit_test.go Loading commit data...
session_auth.go Loading commit data...
token_auth.go Loading commit data...
userlib.go Loading commit data...
userlib_test.go Loading commit data...


This package implements user management and authentication for standalone web applications. There are a number of subtleties in the UX interactions required to do user authentication properly (email-based activation and password recovery, brute-force protections, etc.), and userlib aims to free you from this burden by offering a correct implementation. The package also supports management of credentials for API-using noninteractive applications (using signed bearer tokens).

The interface is partially prescriptive: rather than adapting to an arbitrary user data model, it expects you to store its own User objects. Similarly, there isn't much flexibility in the generated URL structure.


  • Interactive authentication based on username/password
  • Email-based account activation
  • Email-based password recovery
  • Rate-limiting of login and password recovery requests
  • Application registration requires once-off interactive login for confirmation
  • Customizable templates

In scope:

  • Emails to users are signed and encrypted with PGP


  • Can't change the name of a user because it is used as primary key


The HTTP handler methods in userlib use a slightly different interface than the one from net/http in the Go standard library: the httperr package offers a Handler whose ServeHTTP method returns an error. Errors are then caught by the WithError wrapper.

import (


func main() {
        // Setup your application, create myDatabase somehow...
        // Also, you probably don't want to generate the RSA key every time.
        pkey, _ := rsa.GenerateKey(rand.reader, 1024)
        mgr, err := userlib.NewManager(&userlib.Config{
                UserProvider: myDatabase,
                PrivateKey:   pkey,
                Mailer:       email.DefaultSMTPMailer(),
                EmailSender:  &mail.Address{
                        Address: "app@example.com",
                        Name:    "My App",

        // Create the app HTTP handler and hook up our handler, with
        // authentication and a redirect to the login page.
        mux, _ := mgr.SetupHandlers(mux, nil)

        // Serve the app (a sample handler).
        mux.Handle("/myapp", mgr.Private(httperr.HandlerFunc(
                func(w http.ResponseWriter, r *http.Request) error {
                        fmt.Fprintf(w, "OK\n")
                        return nil
                }), []userlib.ACL{userlib.IsValidUserACL}))

        // Add global handlers.
        h := userlib.WithSession(userlib.WithError(mux)))
        http.ListenAndServe(":8080", h)