Version: v0.0.0-...-3eca13d Latest Latest

This package is not in the latest version of its module.

Go to latest
Published: Apr 1, 2014 License: MIT Imports: 12 Imported by: 262


auth/htpasswd GoDoc

Authenticate using Apache-style htpasswd files and HTTP Basic Authentication.

htpasswd has supported a number of different password hashing schemes over the decades. Most common and sane ones are supported directly. For some you will need to add another package.

Style Status
plain yes+
md5 yes
sha yes
crypt no (conflicts with plain)
bcrypt no (can add with another package)

The standard set of systems will use Plain, Sha, and MD5 systems while filtering out bcrypt. Because of its complexity, bcrypt will be in another package which you can import and add if you need it. Plain accepts both Apache style plain text and nginx style where the password is preceded by {PLAIN}.


import (

func main() {
  m := martini.Classic()

  pw,err := basic.New("My Realm", "./my-htpasswd-file", htpasswd.DefaultSystems, nil)
  if ( err != nil) {
    log.Fatalf("Unable to read my htpassword file: %s", err.Error())

  // authenticate every request
  m.Use( pw.ServeHTTP)

  // You will also want to call pw.Reload(nil) to reprocess the password file when it changes.

  // You can use pw.ReloadOn( syscall.SIGHUP, nil ) to make it automatically
  // reload on a HUP signal.

  // And those 'nil' arguments are where you pass a function to be notified about illegally 
  // formatted entries, or unsupported hash systems. See the API documents.

  // If you only want to authenticate some requests, then it goes like this...
  //    m.Get("/secure/thing", pw.ServeHTTP, myRealHandler)
  // ... if pw.ServeHTTP does the 401 then your handler will not be called


API Documentation

The API is documented using godoc and also available at



Package htpasswd provides HTTP Basic Authentication using Apache-style htpasswd files for the user and password data.

It supports most common hashing systems used over the decades and can be easily extended by the programmer to support others. (See the sha.go source file as a guide.)

You will want to use something like...

myauth := htpasswd.New("My Realm", "./my-htpasswd-file", htpasswd.DefaultSystems, nil)
m.Use(myauth.Handler) configure your authentication and then use the myauth.Handler as a middleware handler in your Martini stack. You should read about that nil, as well as Reread() too.



This section is empty.


An array of PasswdParser including all builtin parsers. Notice that Plain is last, since it accepts anything


This section is empty.


type BadLineHandler

type BadLineHandler func(err error)

A BadLineHandler is used to notice bad lines in a password file. If not nil, it will be called for each bad line with a descriptive error. Think about what you do with these, they will sometimes contain hashed passwords.

type EncodedPasswd

type EncodedPasswd interface {
	// Return true if the string matches the password.
	// This may cache the result in the case of expensive comparison functions.
	MatchesPassword(pw string) bool

An EncodedPasswd is created from the encoded password in a password file by a PasswdParser.

The password files consist of lines like "user:passwd-encoding". The user part is stripped off and the passwd-encoding part is captured in an EncodedPasswd.

func AcceptMd5

func AcceptMd5(src string) (EncodedPasswd, error)

Accept valid MD5 encoded passwords

func AcceptPlain

func AcceptPlain(pw string) (EncodedPasswd, error)

Accept any password in the plain text encoding. Be careful: This matches any line, so it *must* be the last parser in you list.

func AcceptSha

func AcceptSha(src string) (EncodedPasswd, error)

Accept valid SHA encoded passwords.

func RejectBcrypt

func RejectBcrypt(src string) (EncodedPasswd, error)

Reject any password encoded using bcrypt.

func RejectMd5

func RejectMd5(src string) (EncodedPasswd, error)

Reject any MD5 encoded password

func RejectPlain

func RejectPlain(pw string) (EncodedPasswd, error)

Reject any plain text encoded passoword. Be careful: This matches any line, so it *must* be the last parser in you list.

func RejectSha

func RejectSha(src string) (EncodedPasswd, error)

Reject any password encoded as SHA.

type HtpasswdFile

type HtpasswdFile struct {
	// contains filtered or unexported fields

An HtpasswdFile encompasses an Apache-style htpasswd file for HTTP Basic authentication

func New

func New(realm string, filename string, parsers []PasswdParser, bad BadLineHandler) (*HtpasswdFile, error)

New creates an HtpasswdFile from an Apache-style htpasswd file for HTTP Basic Authentication.

The realm is presented to the user in the login dialog.

The filename must exist and be accessible to the process, as well as being a valid htpasswd file.

parsers is a list of functions to handle various hashing systems. In practice you will probably just pass htpasswd.DefaultSystems, but you could make your own to explicitly reject some formats or implement your own.

bad is a function, which if not nil will be called for each malformed or rejected entry in the password file.

func (*HtpasswdFile) Reload

func (bf *HtpasswdFile) Reload(bad BadLineHandler) error

Reread the password file for this HtpasswdFile. You will need to call this to notice any changes to the password file. This function is thread safe. Someone versed in fsnotify might make it happen automatically. Likewise you might also connect a SIGHUP handler to this function.

func (*HtpasswdFile) ReloadOn

func (bf *HtpasswdFile) ReloadOn(when os.Signal, onbad BadLineHandler)

Reload the htpasswd file on a signal. If there is an error, the old data will be kept instead. Typically you would use syscall.SIGHUP for the value of "when"

func (*HtpasswdFile) ServeHTTP

func (bf *HtpasswdFile) ServeHTTP(res http.ResponseWriter, req *http.Request)

A Martini middleware handler to enforce HTTP Basic Auth using the policy read from the htpasswd file.

type PasswdParser

type PasswdParser func(pw string) (EncodedPasswd, error)

Examine an encoded password, and if it is formatted correctly and sane, return an EncodedPasswd which will recognize it.

If the format is not understood, then return nil so that another parser may have a chance. If the format is understood but not sane, return an error to prevent other formats from possibly claiming it

You may write and supply one of these functions to support a format (e.g. bcrypt) not already included in this package. Use sha.c as a template, it is simple but not too simple.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL