diff --git a/security/Token.go b/security/Token.go index 439ded4..6ebc2a7 100644 --- a/security/Token.go +++ b/security/Token.go @@ -34,15 +34,36 @@ type JwtToken struct { } func (token *JwtToken) isValidForScope(allowedScopes []string) bool { - if ok, _ := inArray("*", token.Scopes); ok { + permissiveTokenScopes := []string{} + nonPermissiveTokenScopes := []string{} + + for _, tokenScope := range token.Scopes { + if strings.HasPrefix(tokenScope, "-") { + nonPermissiveTokenScopes = append(nonPermissiveTokenScopes, tokenScope[1:]) + } else { + permissiveTokenScopes = append(permissiveTokenScopes, tokenScope) + } + } + + if len(nonPermissiveTokenScopes) > 0 { + if isScopePresent(nonPermissiveTokenScopes, allowedScopes) { + return false + } + } + + return isScopePresent(permissiveTokenScopes, allowedScopes) +} + +func isScopePresent(scopes []string, scopeToCheck []string) bool { + if ok, _ := inArray("*", scopes); ok { return true } allScopesMatched := true - for _, allowedScope := range allowedScopes { - if ok, _ := inArray(allowedScope, token.Scopes); !ok { + for _, allowedScope := range scopeToCheck { + if ok, _ := inArray(allowedScope, scopes); !ok { scopeParts := strings.Split(allowedScope, ":") - if ok, _ := inArray(scopeParts[0]+":*", token.Scopes); !ok { - if ok, _ := inArray("*:"+scopeParts[1], token.Scopes); !ok { + if ok, _ := inArray(scopeParts[0]+":*", scopes); !ok { + if ok, _ := inArray("*:"+scopeParts[1], scopes); !ok { allScopesMatched = false } } diff --git a/security/Token_test.go b/security/Token_test.go index 1374c19..d8d1045 100644 --- a/security/Token_test.go +++ b/security/Token_test.go @@ -14,6 +14,8 @@ var scopeCombinations = []struct { {[]string{"appliance:*", "trustedGroup:*"}, []string{"trustedGroup:read"}, true}, {[]string{"trustedGroup:read"}, []string{"trustedGroup:read"}, true}, {[]string{"trustedGroup:write"}, []string{"trustedGroup:read"}, false}, + {[]string{"*", "-trustedGroup:*"}, []string{"trustedGroup:read"}, false}, + {[]string{"trusterdGroup:*", "-trustedGroup:read"}, []string{"trustedGroup:read"}, false}, } func TestScopes(t *testing.T) {