// Package auth is an implementation of HTTP Basic and HTTP Digest authentication. package auth import ( "context" "net/http" ) // AuthenticatedRequest is passed to AuthenticatedHandlerFunc instead // of *http.Request. type AuthenticatedRequest struct { http.Request // Username is the authenticated user name. Current API implies that // Username is never empty, which means that authentication is // always done before calling the request handler. Username string } // AuthenticatedHandlerFunc is like http.HandlerFunc, but takes // AuthenticatedRequest instead of http.Request type AuthenticatedHandlerFunc func(http.ResponseWriter, *AuthenticatedRequest) // Authenticator wraps an AuthenticatedHandlerFunc with // authentication-checking code. // // Typical Authenticator usage is something like: // // authenticator := SomeAuthenticator(...) // http.HandleFunc("/", authenticator(my_handler)) // // Authenticator wrapper checks the user authentication and calls the // wrapped function only after authentication has succeeded. Otherwise, // it returns a handler which initiates the authentication procedure. type Authenticator func(AuthenticatedHandlerFunc) http.HandlerFunc // Info contains authentication information for the request. type Info struct { // Authenticated is set to true when request was authenticated // successfully, i.e. username and password passed in request did // pass the check. Authenticated bool // Username contains a user name passed in the request when // Authenticated is true. It's value is undefined if Authenticated // is false. Username string // ResponseHeaders contains extra headers that must be set by server // when sending back HTTP response. ResponseHeaders http.Header } // UpdateHeaders updates headers with this Info's ResponseHeaders. It is // safe to call this function on nil Info. func (i *Info) UpdateHeaders(headers http.Header) { if i == nil { return } for k, values := range i.ResponseHeaders { for _, v := range values { headers.Add(k, v) } } } type key int // used for context keys var infoKey key // AuthenticatorInterface is the interface implemented by BasicAuth // and DigestAuth authenticators. // // Deprecated: this interface is not coherent. New code should define // and use your own interfaces with a required subset of authenticator // methods. type AuthenticatorInterface interface { // NewContext returns a new context carrying authentication // information extracted from the request. NewContext(ctx context.Context, r *http.Request) context.Context // Wrap returns an http.HandlerFunc which wraps // AuthenticatedHandlerFunc with this authenticator's // authentication checks. Wrap(AuthenticatedHandlerFunc) http.HandlerFunc } // FromContext returns authentication information from the context or // nil if no such information present. func FromContext(ctx context.Context) *Info { info, ok := ctx.Value(infoKey).(*Info) if !ok { return nil } return info } // AuthUsernameHeader is the header set by JustCheck functions. It // contains an authenticated username (if authentication was // successful). const AuthUsernameHeader = "X-Authenticated-Username" // JustCheck returns a new http.HandlerFunc, which requires // authenticator to successfully authenticate a user before calling // wrapped http.HandlerFunc. func JustCheck(auth AuthenticatorInterface, wrapped http.HandlerFunc) http.HandlerFunc { return auth.Wrap(func(w http.ResponseWriter, ar *AuthenticatedRequest) { ar.Header.Set(AuthUsernameHeader, ar.Username) wrapped(w, &ar.Request) }) }