-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #209 from xmidt-org/feature/redesign
initial checkin ideas
- Loading branch information
Showing
16 changed files
with
861 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// SPDX-FileCopyrightText: 2020 Comcast Cable Communications Management, LLC | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package bascule | ||
|
||
import "go.uber.org/multierr" | ||
|
||
// Authenticator provides a strategy for verifying that a Token | ||
// is valid beyond just simple parsing. For example, an Authenticator may | ||
// verify certain roles or capabilities. | ||
type Authenticator interface { | ||
// Authenticate verifies the given Token. | ||
Authenticate(Token) error | ||
} | ||
|
||
// Authenticators is an aggregate Authenticator. | ||
type Authenticators []Authenticator | ||
|
||
// Authenticate applies each contained Authenticator in order. All Authenticators | ||
// are executed. The returned error, if not nil, will be an aggregate of all errors | ||
// that occurred. | ||
func (as Authenticators) Authenticate(t Token) (err error) { | ||
for _, auth := range as { | ||
err = multierr.Append(err, auth.Authenticate(t)) | ||
} | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// SPDX-FileCopyrightText: 2020 Comcast Cable Communications Management, LLC | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package bascule | ||
|
||
// Authorizer is a strategy for verifying that a given Token has | ||
// access to resources. | ||
type Authorizer interface { | ||
// Authorize verifies that the given Token can access a resource. | ||
Authorize(resource any, t Token) error | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// SPDX-FileCopyrightText: 2020 Comcast Cable Communications Management, LLC | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package basculehttp | ||
|
||
import ( | ||
"net/http" | ||
"strings" | ||
|
||
"github.com/xmidt-org/bascule/v2" | ||
) | ||
|
||
const DefaultAuthorizationHeader = "Authorization" | ||
|
||
// Accessor is the strategy for extracting the raw, serialized credentials | ||
// from an HTTP request. | ||
type Accessor interface { | ||
// GetCredentials obtains the raw, serialized credentials from the request. | ||
GetCredentials(*http.Request) (string, error) | ||
} | ||
|
||
var defaultAccessor Accessor = AuthorizationAccessor{} | ||
|
||
func DefaultAccessor() Accessor { return defaultAccessor } | ||
|
||
// AuthorizationAccessor is an Accessor that pulls the serialized credentials | ||
// from an HTTP header of the format defined by https://www.rfc-editor.org/rfc/rfc7235#section-4.2. | ||
// Only the single header is considered. | ||
type AuthorizationAccessor struct { | ||
// Header is the name of the Authorization header. If unset, then | ||
// DefaultAuthorizationHeader is used. | ||
Header string | ||
} | ||
|
||
func (aa AuthorizationAccessor) header() string { | ||
if len(aa.Header) == 0 { | ||
return DefaultAuthorizationHeader | ||
} | ||
|
||
return aa.Header | ||
} | ||
|
||
func (aa AuthorizationAccessor) GetCredentials(r *http.Request) (serialized string, err error) { | ||
header := aa.header() | ||
serialized = r.Header.Get(header) | ||
|
||
if len(serialized) == 0 { | ||
var reason strings.Builder | ||
reason.WriteString("missing header ") | ||
reason.WriteString(header) | ||
err = &bascule.MissingCredentialsError{ | ||
Reason: reason.String(), | ||
} | ||
} | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// SPDX-FileCopyrightText: 2020 Comcast Cable Communications Management, LLC | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package basculehttp | ||
|
||
import ( | ||
"encoding/base64" | ||
"strings" | ||
|
||
"github.com/xmidt-org/bascule/v2" | ||
) | ||
|
||
type basicToken struct { | ||
credentials bascule.Credentials | ||
userName string | ||
} | ||
|
||
func (bt *basicToken) Credentials() bascule.Credentials { return bt.credentials } | ||
|
||
func (bt *basicToken) Principal() string { return bt.userName } | ||
|
||
type basicTokenParser struct{} | ||
|
||
func (basicTokenParser) Parse(c bascule.Credentials) (t bascule.Token, err error) { | ||
var decoded []byte | ||
decoded, err = base64.StdEncoding.DecodeString(c.Value) | ||
if err == nil { | ||
if userName, _, ok := strings.Cut(string(decoded), ":"); ok { | ||
t = &basicToken{ | ||
credentials: c, | ||
userName: userName, | ||
} | ||
} else { | ||
err = &bascule.InvalidCredentialsError{ | ||
Raw: c.Value, | ||
} | ||
} | ||
} | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
// SPDX-FileCopyrightText: 2020 Comcast Cable Communications Management, LLC | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package basculehttp | ||
|
||
import ( | ||
"net/http" | ||
"strings" | ||
|
||
"github.com/xmidt-org/bascule/v2" | ||
) | ||
|
||
const ( | ||
BasicScheme bascule.Scheme = "Basic" | ||
BearerScheme bascule.Scheme = "Bearer" | ||
|
||
// WwwAuthenticateHeaderName is the HTTP header used for StatusUnauthorized challenges. | ||
WwwAuthenticateHeaderName = "WWW-Authenticate" | ||
|
||
// DefaultBasicRealm is the realm used for a basic challenge | ||
// when no realm is supplied. | ||
DefaultBasicRealm string = "bascule" | ||
|
||
// DefaultBearerRealm is the realm used for a bearer challenge | ||
// when no realm is supplied. | ||
DefaultBearerRealm string = "bascule" | ||
) | ||
|
||
// Challenge represents a WWW-Authenticate challenge. | ||
type Challenge interface { | ||
// FormatAuthenticate formats the authenticate string. | ||
FormatAuthenticate(strings.Builder) | ||
} | ||
|
||
// Challenges represents a sequence of challenges to associated with | ||
// a StatusUnauthorized response. | ||
type Challenges []Challenge | ||
|
||
// WriteHeader inserts one WWW-Authenticate header per challenge in this set. | ||
// If this set is empty, the given http.Header is not modified. | ||
// | ||
// This method returns the count of headers added, which will be zero (0) for | ||
// an empty Challenges. | ||
func (chs Challenges) WriteHeader(h http.Header) int { | ||
var o strings.Builder | ||
for _, ch := range chs { | ||
ch.FormatAuthenticate(o) | ||
h.Add(WwwAuthenticateHeaderName, o.String()) | ||
o.Reset() | ||
} | ||
|
||
return len(chs) | ||
} | ||
|
||
// BasicChallenge represents a WWW-Authenticate basic auth challenge. | ||
type BasicChallenge struct { | ||
// Scheme is the name of scheme supplied in the challenge. If this | ||
// field is unset, BasicScheme is used. | ||
Scheme bascule.Scheme | ||
|
||
// Realm is the name of the realm for the challenge. If this field | ||
// is unset, DefaultBasicRealm is used. | ||
// | ||
// Note that this field should always be set. The default isn't very | ||
// useful outside of development. | ||
Realm string | ||
|
||
// UTF8 indicates whether "charset=UTF-8" is appended to the challenge. | ||
// This is the only charset allowed for a Basic challenge. | ||
UTF8 bool | ||
} | ||
|
||
func (bc BasicChallenge) FormatAuthenticate(o strings.Builder) { | ||
if len(bc.Scheme) > 0 { | ||
o.WriteString(string(bc.Scheme)) | ||
} else { | ||
o.WriteString(string(BasicScheme)) | ||
} | ||
|
||
o.WriteString(` realm="`) | ||
if len(bc.Realm) > 0 { | ||
o.WriteString(bc.Realm) | ||
} else { | ||
o.WriteString(DefaultBasicRealm) | ||
} | ||
|
||
o.WriteRune('"') | ||
if bc.UTF8 { | ||
o.WriteString(`, charset="UTF-8"`) | ||
} | ||
} | ||
|
||
type BearerChallenge struct { | ||
// Scheme is the name of scheme supplied in the challenge. If this | ||
// field is unset, BearerScheme is used. | ||
Scheme bascule.Scheme | ||
|
||
// Realm is the name of the realm for the challenge. If this field | ||
// is unset, DefaultBearerRealm is used. | ||
// | ||
// Note that this field should always be set. The default isn't very | ||
// useful outside of development. | ||
Realm string | ||
} | ||
|
||
func (bc BearerChallenge) FormatAuthenticate(o strings.Builder) { | ||
if len(bc.Scheme) > 0 { | ||
o.WriteString(string(bc.Scheme)) | ||
} else { | ||
o.WriteString(string(BasicScheme)) | ||
} | ||
|
||
o.WriteString(` realm="`) | ||
if len(bc.Realm) > 0 { | ||
o.WriteString(bc.Realm) | ||
} else { | ||
o.WriteString(DefaultBasicRealm) | ||
} | ||
} |
Oops, something went wrong.