From d9e956be4845dab450a8dfd51d6fe7476095b62e Mon Sep 17 00:00:00 2001 From: Juliusz Chroboczek Date: Sat, 11 May 2024 22:45:52 +0200 Subject: [PATCH] More JWT paranoia. --- README | 5 +++-- group/description.go | 2 +- token/jwt.go | 13 ++++++++++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/README b/README index 4bc1a4f..a69a973 100644 --- a/README +++ b/README @@ -301,8 +301,9 @@ existing authentication and authorisation infrastructure, such as LDAP, OAuth2 or even Unix passwords. When an authorisation server is used, the group configuration file -specifies one or more public keys in JWK format. In addition, it may -specify either an authorisation server or an authorisation portal. +specifies one or more public keys in JWK format (with the restriction that +the "alg" key must be specified). In addition, it may specify either an +authorisation server or an authorisation portal. { "authKeys": [{ diff --git a/group/description.go b/group/description.go index 19e575a..2dab8a6 100644 --- a/group/description.go +++ b/group/description.go @@ -581,7 +581,7 @@ func SetWildcardUser(group string, user *UserDescription) error { func SetKeys(group string, keys []map[string]any) error { if keys != nil { - _, err := token.ParseKeys(keys, "") + _, err := token.ParseKeys(keys, "", "") if err != nil { return err } diff --git a/token/jwt.go b/token/jwt.go index 9ee8f7e..4ff31dc 100644 --- a/token/jwt.go +++ b/token/jwt.go @@ -96,10 +96,13 @@ func ParseKey(key map[string]any) (any, error) { } } -func ParseKeys(keys []map[string]any, kid string) ([]jwt.VerificationKey, error) { +func ParseKeys(keys []map[string]any, alg, kid string) ([]jwt.VerificationKey, error) { ks := make([]jwt.VerificationKey, 0, len(keys)) for _, ky := range keys { - // return all keys if kid is not specified + // return all keys if alg and kid are not specified + if alg != "" && ky["alg"] != alg { + continue + } if kid != "" && ky["kid"] != kid { continue } @@ -135,8 +138,12 @@ func parseJWT(token string, keys []map[string]any) (*JWT, error) { t, err := jwt.Parse( token, func(t *jwt.Token) (any, error) { + alg, _ := t.Header["alg"].(string) + if alg == "" { + return nil, errors.New("alg not found") + } kid, _ := t.Header["kid"].(string) - ks, err := ParseKeys(keys, kid) + ks, err := ParseKeys(keys, alg, kid) if err != nil { return nil, err }