package runtime
import (
"encoding/base64"
"fmt"
"net/http"
)
// Authenticator attaches credentials to an outgoing request.
//
// Return a non-nil error to abort the request before it leaves the client.
type Authenticator interface {
AuthenticateRequest(req *http.Request) error
}
// BearerAuth sends `Authorization: Bearer <Token>`.
type BearerAuth struct {
Token string
}
func (b BearerAuth) AuthenticateRequest(req *http.Request) error {
if b.Token == "" {
return fmt.Errorf("bearer auth: empty token")
}
req.Header.Set("Authorization", "Bearer "+b.Token)
return nil
}
// APIKeyLocation enumerates where an API key is placed on the wire.
type APIKeyLocation int
const (
APIKeyInHeader APIKeyLocation = iota
APIKeyInQuery
APIKeyInCookie
)
// APIKeyAuth attaches a named API key to a request.
type APIKeyAuth struct {
Key string
Name string
Location APIKeyLocation
}
func (a APIKeyAuth) AuthenticateRequest(req *http.Request) error {
if a.Key == "" || a.Name == "" {
return fmt.Errorf("api key auth: empty key or name")
}
switch a.Location {
case APIKeyInHeader:
req.Header.Set(a.Name, a.Key)
case APIKeyInQuery:
q := req.URL.Query()
q.Set(a.Name, a.Key)
req.URL.RawQuery = q.Encode()
case APIKeyInCookie:
req.AddCookie(&http.Cookie{Name: a.Name, Value: a.Key})
default:
return fmt.Errorf("api key auth: unknown location %d", a.Location)
}
return nil
}
// BasicAuth sends `Authorization: Basic <base64(user:pass)>`.
type BasicAuth struct {
Username string
Password string
}
func (b BasicAuth) AuthenticateRequest(req *http.Request) error {
creds := b.Username + ":" + b.Password
encoded := base64.StdEncoding.EncodeToString([]byte(creds))
req.Header.Set("Authorization", "Basic "+encoded)
return nil
}