diff options
Diffstat (limited to 'util/httphdr/auth.go')
| -rw-r--r-- | util/httphdr/auth.go | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/util/httphdr/auth.go b/util/httphdr/auth.go new file mode 100644 index 000000000..af81c9b3d --- /dev/null +++ b/util/httphdr/auth.go @@ -0,0 +1,81 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +package httphdr + +import ( + "bytes" + "encoding/base64" + "fmt" + "strings" +) + +// TODO: Must authorization parameters be valid UTF-8? + +// AuthScheme is an authorization scheme per RFC 7235. +// Per section 2.1, the "Authorization" header is formatted as: +// +// Authorization: <auth-scheme> <auth-parameter> +// +// A scheme implementation must self-report the <auth-scheme> name and +// provide the ability to marshal and unmarshal the <auth-parameter>. +// +// For concrete implementations, see [Basic] and [Bearer]. +type AuthScheme interface { + // AuthScheme is the authorization scheme name. + // It must be valid according to RFC 7230, section 3.2.6. + AuthScheme() string + + // MarshalAuth marshals the authorization parameter for the scheme. + MarshalAuth() (string, error) + + // UnmarshalAuth unmarshals the authorization parameter for the scheme. + UnmarshalAuth(string) error +} + +// BasicAuth is the Basic authorization scheme as defined in RFC 2617. +type BasicAuth struct { + Username string // must not contain ':' per section 2 + Password string +} + +func (BasicAuth) AuthScheme() string { return "Basic" } + +func (a BasicAuth) MarshalAuth() (string, error) { + if strings.IndexByte(a.Username, ':') >= 0 { + return "", fmt.Errorf("invalid username: contains a colon") + } + return base64.StdEncoding.EncodeToString([]byte(a.Username + ":" + a.Password)), nil +} + +func (a *BasicAuth) UnmarshalAuth(s string) error { + b, err := base64.StdEncoding.DecodeString(s) + if err != nil { + return fmt.Errorf("invalid basic authorization: %w", err) + } + i := bytes.IndexByte(b, ':') + if i < 0 { + return fmt.Errorf("invalid basic authorization: missing a colon") + } + a.Username = string(b[:i]) + a.Password = string(b[i+len(":"):]) + return nil +} + +// BearerAuth is the Bearer Token authorization scheme as defined in RFC 6750. +type BearerAuth struct { + Token string // usually a base64-encoded string per section 2.1 +} + +func (BearerAuth) AuthScheme() string { return "Bearer" } + +func (a BearerAuth) MarshalAuth() (string, error) { + // TODO: Verify that token is valid base64? + return a.Token, nil +} + +func (a *BearerAuth) UnmarshalAuth(s string) error { + // TODO: Verify that token is valid base64? + a.Token = s + return nil +} |
