Rework include-subgroups for cryptographic tokens.
This commit is contained in:
+18
-8
@@ -188,6 +188,22 @@ func parseJWT(token string, keys []map[string]any) (*JWT, error) {
|
|||||||
return (*JWT)(t), nil
|
return (*JWT)(t), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func matchGroup(pth, group string, includeSubgroups bool) bool {
|
||||||
|
if !includeSubgroups {
|
||||||
|
return pth == "/group/"+group+"/"
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.HasPrefix(pth, "/group/") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.HasSuffix(pth, "/") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.HasPrefix("/group/"+group+"/", pth)
|
||||||
|
}
|
||||||
|
|
||||||
func (token *JWT) Check(host, group string, username *string) (string, []string, error) {
|
func (token *JWT) Check(host, group string, username *string) (string, []string, error) {
|
||||||
sub, err := token.Claims.GetSubject()
|
sub, err := token.Claims.GetSubject()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -205,7 +221,7 @@ func (token *JWT) Check(host, group string, username *string) (string, []string,
|
|||||||
if !ok {
|
if !ok {
|
||||||
return "", nil, errors.New("unexpected type for token")
|
return "", nil, errors.New("unexpected type for token")
|
||||||
}
|
}
|
||||||
incSubgroups, _ := claims["include-subgroups"].(bool)
|
includeSubgroups, _ := claims["include-subgroups"].(bool)
|
||||||
|
|
||||||
ok = false
|
ok = false
|
||||||
for _, u := range aud {
|
for _, u := range aud {
|
||||||
@@ -221,13 +237,7 @@ func (token *JWT) Check(host, group string, username *string) (string, []string,
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// aud path takes the form /group/<groupname>/
|
if matchGroup(url.Path, group, includeSubgroups) {
|
||||||
if !strings.HasPrefix(url.Path, "/group/") || !strings.HasSuffix(url.Path, "/") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
tokenGroup := url.Path[len("/group/") : len(url.Path)-1]
|
|
||||||
if group == tokenGroup ||
|
|
||||||
incSubgroups && (tokenGroup == "" || strings.HasPrefix(group, tokenGroup+"/")) {
|
|
||||||
ok = true
|
ok = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,42 @@ func TestJWKRS256(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMatchGroup(t *testing.T) {
|
||||||
|
type tt struct {
|
||||||
|
p, g string
|
||||||
|
s bool
|
||||||
|
}
|
||||||
|
good := []tt{
|
||||||
|
{"/group/a/", "a", false},
|
||||||
|
{"/group/a/b/", "a/b", false},
|
||||||
|
{"/group/a/", "a", true},
|
||||||
|
{"/group/a/", "a/b", true},
|
||||||
|
{"/group/a/b/", "a/b", true},
|
||||||
|
{"/group/a/b/", "a/b/c", true},
|
||||||
|
}
|
||||||
|
|
||||||
|
bad := []tt{
|
||||||
|
{"/group/a/", "b", false},
|
||||||
|
{"/group/a", "a", false},
|
||||||
|
{"/group/a", "a", true},
|
||||||
|
{"/group/a/", "a/b", false},
|
||||||
|
{"/group/a/b/", "a", false},
|
||||||
|
{"/group/a/b/", "a", true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range good {
|
||||||
|
if !matchGroup(test.p, test.g, test.s) {
|
||||||
|
t.Errorf("%v %v %v didn't match", test.p, test.g, test.s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range bad {
|
||||||
|
if matchGroup(test.p, test.g, test.s) {
|
||||||
|
t.Errorf("%v %v %v matched", test.p, test.g, test.s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestJWT(t *testing.T) {
|
func TestJWT(t *testing.T) {
|
||||||
key := `{"alg":"HS256","k":"H7pCkktUl5KyPCZ7CKw09y1j460tfIv4dRcS1XstUKY","key_ops":["sign","verify"],"kty":"oct"}`
|
key := `{"alg":"HS256","k":"H7pCkktUl5KyPCZ7CKw09y1j460tfIv4dRcS1XstUKY","key_ops":["sign","verify"],"kty":"oct"}`
|
||||||
var k map[string]interface{}
|
var k map[string]interface{}
|
||||||
|
|||||||
Reference in New Issue
Block a user