diff --git a/common/authorization/default_jwt_claim_mapper.go b/common/authorization/default_jwt_claim_mapper.go index 1c1c8152a66..17a79bf8ff3 100644 --- a/common/authorization/default_jwt_claim_mapper.go +++ b/common/authorization/default_jwt_claim_mapper.go @@ -28,7 +28,7 @@ import ( "fmt" "strings" - "github.com/dgrijalva/jwt-go/v4" + "github.com/golang-jwt/jwt/v4" "go.temporal.io/api/serviceerror" "go.temporal.io/server/common/config" @@ -130,12 +130,7 @@ func parseJWT(tokenString string, keyProvider TokenKeyProvider) (jwt.MapClaims, func parseJWTWithAudience(tokenString string, keyProvider TokenKeyProvider, audience string) (jwt.MapClaims, error) { - var parser *jwt.Parser - if strings.TrimSpace(audience) == "" { - parser = jwt.NewParser(jwt.WithoutAudienceValidation()) - } else { - parser = jwt.NewParser(jwt.WithAudience(audience)) - } + parser := jwt.NewParser(jwt.WithValidMethods(keyProvider.SupportedMethods())) token, err := parser.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { kid, ok := token.Header["kid"].(string) @@ -159,11 +154,17 @@ func parseJWTWithAudience(tokenString string, keyProvider TokenKeyProvider, audi if err != nil { return nil, err } - - if claims, ok := token.Claims.(jwt.MapClaims); ok { - return claims, nil + claims, ok := token.Claims.(jwt.MapClaims) + if !ok { + return nil, serviceerror.NewPermissionDenied("invalid token with no claims", "") + } + if err := claims.Valid(); err != nil { + return nil, err + } + if strings.TrimSpace(audience) != "" && !claims.VerifyAudience(audience, true) { + return nil, serviceerror.NewPermissionDenied("audience mismatch", "") } - return nil, serviceerror.NewPermissionDenied("invalid token with no claims", "") + return claims, nil } func permissionToRole(permission string) Role { diff --git a/common/authorization/default_jwt_claim_mapper_test.go b/common/authorization/default_jwt_claim_mapper_test.go index f60eca208c3..569597ac379 100644 --- a/common/authorization/default_jwt_claim_mapper_test.go +++ b/common/authorization/default_jwt_claim_mapper_test.go @@ -34,7 +34,7 @@ import ( "testing" "time" - "github.com/dgrijalva/jwt-go/v4" + "github.com/golang-jwt/jwt/v4" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" @@ -270,6 +270,8 @@ type ( } ) +var _ TokenKeyProvider = (*tokenGenerator)(nil) + func newTokenGenerator() *tokenGenerator { rsaKey, err := rsa.GenerateKey(rand.Reader, 2048) @@ -292,11 +294,11 @@ func newTokenGenerator() *tokenGenerator { type ( CustomClaims struct { Permissions []string `json:"permissions"` - jwt.StandardClaims + jwt.RegisteredClaims } ) -func (CustomClaims) Valid(*jwt.ValidationHelper) error { +func (CustomClaims) Valid() error { return nil } @@ -311,8 +313,8 @@ func (tg *tokenGenerator) generateECDSAToken(subject string, permissions []strin func (tg *tokenGenerator) generateToken(alg keyAlgorithm, subject string, permissions []string, options errorTestOptions) (string, error) { claims := CustomClaims{ permissions, - jwt.StandardClaims{ - ExpiresAt: jwt.At(time.Now().Add(time.Hour)), + jwt.RegisteredClaims{ + ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)), Issuer: "test", Audience: []string{"test-audience"}, }, @@ -356,5 +358,8 @@ func (tg *tokenGenerator) HmacKey(alg string, kid string) ([]byte, error) { func (tg *tokenGenerator) RsaKey(alg string, kid string) (*rsa.PublicKey, error) { return tg.rsaPublicKey, nil } +func (tg *tokenGenerator) SupportedMethods() []string { + return []string{jwt.SigningMethodRS256.Name, jwt.SigningMethodES256.Name} +} func (tg *tokenGenerator) Close() { } diff --git a/common/authorization/default_token_key_provider.go b/common/authorization/default_token_key_provider.go index c8612288b33..68ae095822c 100644 --- a/common/authorization/default_token_key_provider.go +++ b/common/authorization/default_token_key_provider.go @@ -34,6 +34,7 @@ import ( "sync" "time" + "github.com/golang-jwt/jwt/v4" "gopkg.in/square/go-jose.v2" "go.temporal.io/server/common/config" @@ -83,7 +84,7 @@ func (a *defaultTokenKeyProvider) Close() { } func (a *defaultTokenKeyProvider) RsaKey(alg string, kid string) (*rsa.PublicKey, error) { - if !strings.EqualFold(alg, "rs256") { + if !strings.EqualFold(alg, jwt.SigningMethodRS256.Name) { return nil, fmt.Errorf("unexpected signing algorithm: %s", alg) } @@ -97,7 +98,7 @@ func (a *defaultTokenKeyProvider) RsaKey(alg string, kid string) (*rsa.PublicKey } func (a *defaultTokenKeyProvider) EcdsaKey(alg string, kid string) (*ecdsa.PublicKey, error) { - if !strings.EqualFold(alg, "es256") { + if !strings.EqualFold(alg, jwt.SigningMethodES256.Name) { return nil, fmt.Errorf("unexpected signing algorithm: %s", alg) } @@ -110,6 +111,10 @@ func (a *defaultTokenKeyProvider) EcdsaKey(alg string, kid string) (*ecdsa.Publi return key, nil } +func (a *defaultTokenKeyProvider) SupportedMethods() []string { + return []string{jwt.SigningMethodRS256.Name, jwt.SigningMethodES256.Name} +} + func (a *defaultTokenKeyProvider) timerCallback() { for { select { diff --git a/common/authorization/token_key_provider.go b/common/authorization/token_key_provider.go index f43ad2226f5..bc678e7f106 100644 --- a/common/authorization/token_key_provider.go +++ b/common/authorization/token_key_provider.go @@ -35,6 +35,7 @@ type TokenKeyProvider interface { EcdsaKey(alg string, kid string) (*ecdsa.PublicKey, error) HmacKey(alg string, kid string) ([]byte, error) RsaKey(alg string, kid string) (*rsa.PublicKey, error) + SupportedMethods() []string Close() } diff --git a/go.mod b/go.mod index 80f90e95172..89c79aae31d 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,6 @@ require ( github.com/blang/semver/v4 v4.0.0 github.com/brianvoe/gofakeit/v6 v6.10.0 github.com/cactus/go-statsd-client/statsd v0.0.0-20200423205355-cb0885a1018c - github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 github.com/emirpasic/gods v1.12.0 github.com/fatih/color v1.13.0 @@ -64,50 +63,33 @@ require ( require ( cloud.google.com/go v0.97.0 // indirect - github.com/apache/thrift v0.0.0-20161221203622-b2a4d4ae21c7 // indirect github.com/benbjohnson/clock v1.1.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect - github.com/golang/snappy v0.0.4 // indirect github.com/google/go-cmp v0.5.6 // indirect github.com/googleapis/gax-go/v2 v2.1.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect - github.com/hashicorp/yamux v0.0.0-20210826001029-26ff87cf9493 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/mattn/go-colorable v0.1.11 // indirect github.com/mattn/go-isatty v0.0.14 // indirect - github.com/mattn/go-runewidth v0.0.13 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/mitchellh/go-testing-interface v1.14.1 // indirect - github.com/oklog/run v1.1.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.32.1 // indirect - github.com/prometheus/procfs v0.7.3 // indirect - github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/robfig/cron v1.2.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sirupsen/logrus v1.8.1 // indirect github.com/stretchr/objx v0.3.0 // indirect - github.com/twmb/murmur3 v1.1.6 // indirect - github.com/uber-common/bark v1.3.0 // indirect go.opencensus.io v0.23.0 // indirect go.opentelemetry.io/otel/internal/metric v0.24.0 // indirect go.opentelemetry.io/otel/trace v1.1.0 // indirect - go.uber.org/dig v1.13.0 // indirect - golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect golang.org/x/net v0.0.0-20211215060638-4ddde0e984e9 // indirect golang.org/x/sys v0.0.0-20211215211219-4abf325e0275 // indirect golang.org/x/text v0.3.7 // indirect @@ -117,3 +99,24 @@ require ( google.golang.org/protobuf v1.27.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect ) + +require ( + github.com/apache/thrift v0.0.0-20161221203622-b2a4d4ae21c7 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect + github.com/golang-jwt/jwt/v4 v4.2.0 + github.com/golang/snappy v0.0.4 // indirect + github.com/hashicorp/yamux v0.0.0-20210826001029-26ff87cf9493 // indirect + github.com/mattn/go-colorable v0.1.11 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/oklog/run v1.1.0 // indirect + github.com/prometheus/common v0.32.1 // indirect + github.com/prometheus/procfs v0.7.3 // indirect + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/twmb/murmur3 v1.1.6 // indirect + github.com/uber-common/bark v1.3.0 // indirect + go.uber.org/dig v1.13.0 // indirect + golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect +) diff --git a/go.sum b/go.sum index d98bc80a332..506020a55f2 100644 --- a/go.sum +++ b/go.sum @@ -107,8 +107,6 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 h1:CaO/zOnF8VvUfEbhRatPcwKVWamvbYd8tQGRWacE9kU= -github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4= github.com/dgryski/go-farm v0.0.0-20140601200337-fc41e106ee0e/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= @@ -154,6 +152,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/status v1.1.0 h1:+eIkrewn5q6b30y+g/BJINVVdi2xH7je5MPJ3ZPK3JA= github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= +github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= +github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=