// 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)
|
})
|
}
|