From 03bf344275b80f4e0c350f7ff06a4440627d52e3 Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Thu, 16 Jul 2020 07:30:52 +0530 Subject: [PATCH 1/2] fix(GraphQL): Maintain backward compatibility for `Dgraph.Authorization` in schema. (#5998) * Maintain backward compatibility for `Dgraph.Authorization` in schema (cherry picked from commit 93a0813551ced389c77afc57af9a71d267399dd2) --- graphql/authorization/auth.go | 46 ++++++++++++++++++++++++++++++--- graphql/schema/wrappers_test.go | 21 ++++++++++++--- 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/graphql/authorization/auth.go b/graphql/authorization/auth.go index 5dbc1d60b30..06a69dc460b 100644 --- a/graphql/authorization/auth.go +++ b/graphql/authorization/auth.go @@ -24,8 +24,11 @@ import ( "encoding/json" "fmt" "net/http" + "regexp" "strings" + "github.com/vektah/gqlparser/v2/gqlerror" + "github.com/dgrijalva/jwt-go/v4" "github.com/pkg/errors" "google.golang.org/grpc/metadata" @@ -87,12 +90,47 @@ func Parse(schema string) (AuthMeta, error) { authInfo := schema[authInfoIdx:] err := json.Unmarshal([]byte(authInfo[len(AuthMetaHeader):]), &meta) + if err == nil { + return meta, meta.validate() + } + + fmt.Println("Falling back to parsing `Dgraph.Authorization` in old format." + + " Please check the updated syntax at https://graphql.dgraph.io/authorization/") + // Note: This is the old format for passing authorization information and this code + // is there to maintain backward compatibility. It may be removed in future release. + + // This regex matches authorization information present in the last line of the schema. + // Format: # Dgraph.Authorization "" + // Example: # Dgraph.Authorization X-Test-Auth https://xyz.io/jwt/claims HS256 "secretkey" + // On successful regex match the index for the following strings will be returned. + // [0][0]:[0][1] : # Dgraph.Authorization X-Test-Auth https://xyz.io/jwt/claims HS256 "secretkey" + // [0][2]:[0][3] : Authorization, [0][4]:[0][5] : X-Test-Auth, + // [0][6]:[0][7] : https://xyz.io/jwt/claims, + // [0][8]:[0][9] : HS256, [0][10]:[0][11] : secretkey + authMetaRegex, err := + regexp.Compile(`^#[\s]([^\s]+)[\s]+([^\s]+)[\s]+([^\s]+)[\s]+([^\s]+)[\s]+"([^\"]+)"`) if err != nil { - return meta, fmt.Errorf("Unable to parse Dgraph.Authorization. " + - "It may be that you are using the pre-release syntax. " + - "Please check the correct syntax at https://graphql.dgraph.io/authorization/") + return meta, gqlerror.Errorf("JWT parsing failed: %v", err) + } + + idx := authMetaRegex.FindAllStringSubmatchIndex(authInfo, -1) + if len(idx) != 1 || len(idx[0]) != 12 || + !strings.HasPrefix(authInfo, authInfo[idx[0][0]:idx[0][1]]) { + return meta, gqlerror.Errorf("Invalid `Dgraph.Authorization` format: %s", authInfo) + } + + meta.Header = authInfo[idx[0][4]:idx[0][5]] + meta.Namespace = authInfo[idx[0][6]:idx[0][7]] + meta.Algo = authInfo[idx[0][8]:idx[0][9]] + meta.VerificationKey = authInfo[idx[0][10]:idx[0][11]] + if meta.Algo == HMAC256 { + return meta, nil + } + if meta.Algo != RSA256 { + return meta, errors.Errorf( + "invalid jwt algorithm: found %s, but supported options are HS256 or RS256", meta.Algo) } - return meta, meta.validate() + return meta, nil } func ParseAuthMeta(schema string) error { diff --git a/graphql/schema/wrappers_test.go b/graphql/schema/wrappers_test.go index e67e164de9d..af6e4ebeb28 100644 --- a/graphql/schema/wrappers_test.go +++ b/graphql/schema/wrappers_test.go @@ -980,11 +980,26 @@ func TestParseSecrets(t *testing.T) { # Dgraph.Authorization X-Test-Dgraph https://dgraph.io/jwt/claims HS256 "key" # Dgraph.Secret STRIPE_API_KEY "stripe-api-key-value" `, + map[string]string{"GITHUB_API_TOKEN": "some-super-secret-token", + "STRIPE_API_KEY": "stripe-api-key-value"}, + "X-Test-Dgraph", + nil, + }, + { + "Dgraph.Authorization old format error", + ` + type User { + id: ID! + name: String! + } + + # Dgraph.Secret "GITHUB_API_TOKEN" "some-super-secret-token" + # Dgraph.Authorization X-Test-Dgraph https://dgraph.io/jwt/claims "key" + # Dgraph.Secret STRIPE_API_KEY "stripe-api-key-value" + `, nil, "", - errors.New("Unable to parse Dgraph.Authorization. " + - "It may be that you are using the pre-release syntax. " + - "Please check the correct syntax at https://graphql.dgraph.io/authorization/"), + errors.New("input: Invalid `Dgraph.Authorization` format: # Dgraph.Authorization X-Test-Dgraph https://dgraph.io/jwt/claims \"key\""), }, { "should throw an error if multiple authorization values are specified", From 65a5312bb0594852ea0d4597ef12f8970eff79e9 Mon Sep 17 00:00:00 2001 From: parasssh Date: Thu, 16 Jul 2020 11:35:36 -0700 Subject: [PATCH 2/2] use glog.Warn --- graphql/authorization/auth.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/graphql/authorization/auth.go b/graphql/authorization/auth.go index 06a69dc460b..0cf334d7ab8 100644 --- a/graphql/authorization/auth.go +++ b/graphql/authorization/auth.go @@ -27,6 +27,7 @@ import ( "regexp" "strings" + "github.com/golang/glog" "github.com/vektah/gqlparser/v2/gqlerror" "github.com/dgrijalva/jwt-go/v4" @@ -94,7 +95,7 @@ func Parse(schema string) (AuthMeta, error) { return meta, meta.validate() } - fmt.Println("Falling back to parsing `Dgraph.Authorization` in old format." + + glog.Warningln("Falling back to parsing `Dgraph.Authorization` in old format." + " Please check the updated syntax at https://graphql.dgraph.io/authorization/") // Note: This is the old format for passing authorization information and this code // is there to maintain backward compatibility. It may be removed in future release.