Skip to content

Commit

Permalink
allow case-insensitive bearer, add tests
Browse files Browse the repository at this point in the history
Signed-off-by: Josh Dolitsky <[email protected]>
  • Loading branch information
jdolitsky committed Jan 31, 2020
1 parent 9bd9c66 commit 7bbf065
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 13 deletions.
13 changes: 8 additions & 5 deletions authorization.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package auth
import (
"fmt"
"github.com/pkg/errors"
"strings"
"regexp"
)

const (
Expand All @@ -32,6 +32,8 @@ var (

BasicAuthAuthorizerType AuthorizerType = "basic"
BearerAuthAuthorizerType AuthorizerType = "bearer"

bearerTokenMatch = regexp.MustCompile("(?i)bearer (.*)")
)

type (
Expand Down Expand Up @@ -166,7 +168,11 @@ func (authorizer *Authorizer) authorizeBearerAuth(authHeader string, action stri
var allowed bool
var wwwAuthenticateHeader string

signedString := strings.TrimPrefix(authHeader, "Bearer ")
if namespace == "" {
namespace = authorizer.DefaultNamespace
}

signedString := bearerTokenMatch.ReplaceAllString(authHeader, "$1")

// TODO log error
token, err := authorizer.TokenDecoder.DecodeToken(signedString)
Expand Down Expand Up @@ -194,9 +200,6 @@ func (authorizer *Authorizer) authorizeBearerAuth(authHeader string, action stri
}

if !allowed {
if namespace == "" {
namespace = authorizer.DefaultNamespace
}
wwwAuthenticateHeader = fmt.Sprintf("Bearer realm=\"%s\",service=\"%s\",scope=\"%s:%s:%s\"",
authorizer.Realm, authorizer.Service, authorizer.AccessEntryType, namespace, action)
}
Expand Down
126 changes: 118 additions & 8 deletions authorization_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ type AuthorizationTestSuite struct {

CustomAccessEntryTypeAuthorizer *Authorizer

CustomDefaultNamespaceAuthorizer *Authorizer
EmptyDefaultNamespaceAuthorizer *Authorizer

BasicBadAuthorizationHeader string
BasicGoodAuthorizationHeader string
BasicExpectedWWWAuthHeader string
Expand Down Expand Up @@ -113,6 +116,22 @@ func (suite *AuthorizationTestSuite) SetupSuite() {
})
suite.Nil(err)

suite.CustomDefaultNamespaceAuthorizer, err = NewAuthorizer(&AuthorizerOptions{
Realm: "https://my.site.io/oauth2/token",
Service: "my.site.io",
PublicKeyPath: testPublicKey,
DefaultNamespace: "woo",
})
suite.Nil(err)

suite.EmptyDefaultNamespaceAuthorizer, err = NewAuthorizer(&AuthorizerOptions{
Realm: "https://my.site.io/oauth2/token",
Service: "my.site.io",
PublicKeyPath: testPublicKey,
EmptyDefaultNamespace: true,
})
suite.Nil(err)

suite.BasicBadAuthorizationHeader = generateBasicAuthHeader("cm-test-baduser", "cm-test-badpass")
suite.BasicGoodAuthorizationHeader = generateBasicAuthHeader("cm-test-user", "cm-test-pass")
suite.BasicExpectedWWWAuthHeader = "Basic realm=\"https://my.site.io/oauth2/token\""
Expand Down Expand Up @@ -215,7 +234,7 @@ func (suite *AuthorizationTestSuite) TestAuthorizeBearerRequest() {
signedString, err := suite.TokenGenerator.GenerateToken(access, 0)
suite.Nil(err)
authHeader := fmt.Sprintf("Bearer %s", signedString)
permission, err = suite.BearerAuthAuthorizer.Authorize(authHeader, PullAction, DefaultNamespace)
permission, err = suite.BearerAuthAuthorizer.Authorize(authHeader, PullAction, "")
suite.True(permission.Allowed)
suite.Equal("", permission.WWWAuthenticateHeader)
suite.Nil(err)
Expand All @@ -242,7 +261,7 @@ func (suite *AuthorizationTestSuite) TestAuthorizeBearerRequest() {
suite.Nil(err)
authHeader = fmt.Sprintf("Bearer %s", signedString)

permission, err = suite.BearerAuthAuthorizer.Authorize(authHeader, PullAction, DefaultNamespace)
permission, err = suite.BearerAuthAuthorizer.Authorize(authHeader, PullAction, "")
suite.True(permission.Allowed)
suite.Equal("", permission.WWWAuthenticateHeader)
suite.Nil(err)
Expand All @@ -257,7 +276,7 @@ func (suite *AuthorizationTestSuite) TestAuthorizeBearerRequest() {
suite.Equal("", permission.WWWAuthenticateHeader)
suite.Nil(err)

permission, err = suite.BearerAuthAuthorizer.Authorize(authHeader, PushAction, DefaultNamespace)
permission, err = suite.BearerAuthAuthorizer.Authorize(authHeader, PushAction, "")
suite.False(permission.Allowed)
suite.Equal(suite.BearerPushScopeExpectedWWWAuthHeader, permission.WWWAuthenticateHeader)
suite.Nil(err)
Expand Down Expand Up @@ -286,7 +305,7 @@ func (suite *AuthorizationTestSuite) TestAuthorizeBearerRequest() {
fmt.Println("Sleeping for 2 seconds to test token expiration...")
time.Sleep(time.Second * 2)
authHeader = fmt.Sprintf("Bearer %s", signedString)
permission, err = suite.BearerAuthAuthorizer.Authorize(authHeader, PullAction, DefaultNamespace)
permission, err = suite.BearerAuthAuthorizer.Authorize(authHeader, PullAction, "")
suite.False(permission.Allowed)
suite.Equal(suite.BearerPullScopeExpectedWWWAuthHeader, permission.WWWAuthenticateHeader)
suite.Nil(err)
Expand All @@ -302,7 +321,7 @@ func (suite *AuthorizationTestSuite) TestAuthorizeBearerRequest() {
signedString, err = suite.TokenGenerator.GenerateToken(access, 0)
suite.Nil(err)
authHeader = fmt.Sprintf("Bearer %s", signedString)
permission, err = suite.BearerAuthAuthorizer.Authorize(authHeader, PullAction, DefaultNamespace)
permission, err = suite.BearerAuthAuthorizer.Authorize(authHeader, PullAction, "")
suite.False(permission.Allowed)
suite.Equal(suite.BearerPullScopeExpectedWWWAuthHeader, permission.WWWAuthenticateHeader)
suite.Nil(err)
Expand All @@ -318,7 +337,7 @@ func (suite *AuthorizationTestSuite) TestAuthorizeBearerRequest() {
signedString, err = suite.TokenGenerator.GenerateToken(access, 0)
suite.Nil(err)
authHeader = fmt.Sprintf("Bearer %s", signedString)
permission, err = suite.BearerAuthAuthorizer.Authorize(authHeader, PullAction, DefaultNamespace)
permission, err = suite.BearerAuthAuthorizer.Authorize(authHeader, PullAction, "")
suite.False(permission.Allowed)
suite.Equal(suite.BearerPullScopeExpectedWWWAuthHeader, permission.WWWAuthenticateHeader)
suite.Nil(err)
Expand All @@ -336,7 +355,7 @@ func (suite *AuthorizationTestSuite) TestCustomAccessEntryTypeAuthorizer() {
signedString, err := suite.TokenGenerator.GenerateToken(access, 0)
suite.Nil(err)
authHeader := fmt.Sprintf("Bearer %s", signedString)
permission, err := suite.CustomAccessEntryTypeAuthorizer.Authorize(authHeader, PullAction, DefaultNamespace)
permission, err := suite.CustomAccessEntryTypeAuthorizer.Authorize(authHeader, PullAction, "")
suite.False(permission.Allowed)
suite.NotEmpty(permission.WWWAuthenticateHeader)
suite.Nil(err)
Expand All @@ -352,12 +371,103 @@ func (suite *AuthorizationTestSuite) TestCustomAccessEntryTypeAuthorizer() {
signedString, err = suite.TokenGenerator.GenerateToken(access, 0)
suite.Nil(err)
authHeader = fmt.Sprintf("Bearer %s", signedString)
permission, err = suite.CustomAccessEntryTypeAuthorizer.Authorize(authHeader, PullAction, DefaultNamespace)
permission, err = suite.CustomAccessEntryTypeAuthorizer.Authorize(authHeader, PullAction, "")
suite.True(permission.Allowed)
suite.Empty(permission.WWWAuthenticateHeader)
suite.Nil(err)
}

func (suite *AuthorizationTestSuite) TestCustomDefaultNamespaceAuthorizer() {
// Token using default namespace does not work when authorizer configured with custom default namespace
access := []AccessEntry{
{
Name: DefaultNamespace,
Type: AccessEntryType,
Actions: []string{PullAction},
},
}
signedString, err := suite.TokenGenerator.GenerateToken(access, 0)
suite.Nil(err)
authHeader := fmt.Sprintf("Bearer %s", signedString)
permission, err := suite.CustomDefaultNamespaceAuthorizer.Authorize(authHeader, PullAction, "")
suite.False(permission.Allowed)
suite.NotEmpty(permission.WWWAuthenticateHeader)
suite.Nil(err)

// Using custom custom default namespace provides access
access = []AccessEntry{
{
Name: "woo",
Type: AccessEntryType,
Actions: []string{PullAction},
},
}
signedString, err = suite.TokenGenerator.GenerateToken(access, 0)
suite.Nil(err)

authHeader = fmt.Sprintf("Bearer %s", signedString)
permission, err = suite.CustomDefaultNamespaceAuthorizer.Authorize(authHeader, PullAction, "")
suite.True(permission.Allowed)
suite.Empty(permission.WWWAuthenticateHeader)
suite.Nil(err)
}

func (suite *AuthorizationTestSuite) TestEmptyDefaultNamespaceAuthorizer() {
// Token using default namespace does not work when authorizer configured with empty default namespace
access := []AccessEntry{
{
Name: DefaultNamespace,
Type: AccessEntryType,
Actions: []string{PullAction},
},
}
signedString, err := suite.TokenGenerator.GenerateToken(access, 0)
suite.Nil(err)
authHeader := fmt.Sprintf("Bearer %s", signedString)
permission, err := suite.EmptyDefaultNamespaceAuthorizer.Authorize(authHeader, PullAction, "")
suite.False(permission.Allowed)
suite.NotEmpty(permission.WWWAuthenticateHeader)
suite.Nil(err)

// Using empty string namespace provides access
access = []AccessEntry{
{
Name: "",
Type: AccessEntryType,
Actions: []string{PullAction},
},
}
signedString, err = suite.TokenGenerator.GenerateToken(access, 0)
suite.Nil(err)

authHeader = fmt.Sprintf("Bearer %s", signedString)
permission, err = suite.EmptyDefaultNamespaceAuthorizer.Authorize(authHeader, PullAction, "")
suite.True(permission.Allowed)
suite.Empty(permission.WWWAuthenticateHeader)
suite.Nil(err)
}

func (suite *AuthorizationTestSuite) TestTokenBearerCapitalization() {
// check that the prefixing "Bearer" used in token auth can be of any capitalization
for _, h := range []string{"Bearer", "bearer", "BEARER", "BeArEr"} {
access := []AccessEntry{
{
Name: "",
Type: AccessEntryType,
Actions: []string{PullAction},
},
}
signedString, err := suite.TokenGenerator.GenerateToken(access, 0)
suite.Nil(err)
authHeader := fmt.Sprintf("%s %s", h, signedString)
permission, err := suite.EmptyDefaultNamespaceAuthorizer.Authorize(authHeader, PullAction, "")
suite.True(permission.Allowed)
suite.Empty(permission.WWWAuthenticateHeader)
suite.Nil(err)
}

}

func TestAuthorizationTestSuite(t *testing.T) {
suite.Run(t, new(AuthorizationTestSuite))
}

0 comments on commit 7bbf065

Please sign in to comment.