diff --git a/graphql/e2e/subscription/subscription_test.go b/graphql/e2e/subscription/subscription_test.go index 5da20a20f12..40ea867520f 100644 --- a/graphql/e2e/subscription/subscription_test.go +++ b/graphql/e2e/subscription/subscription_test.go @@ -427,6 +427,80 @@ func TestSubscriptionWithAuthShouldExpireWithJWT(t *testing.T) { require.Nil(t, res) } +func TestSubscriptionAuthWithoutExpiry(t *testing.T) { + dg, err := testutil.DgraphClient(groupOnegRPC) + require.NoError(t, err) + testutil.DropAll(t, dg) + + add := &common.GraphQLParams{ + Query: `mutation updateGQLSchema($sch: String!) { + updateGQLSchema(input: { set: { schema: $sch }}) { + gqlSchema { + schema + } + } + }`, + Variables: map[string]interface{}{"sch": schAuth}, + } + addResult := add.ExecuteAsPost(t, adminEndpoint) + require.Nil(t, addResult.Errors) + time.Sleep(time.Second * 2) + + metaInfo := &testutil.AuthMeta{ + PublicKey: "secret", + Namespace: "https://dgraph.io", + Algo: "HS256", + Header: "Authorization", + } + metaInfo.AuthVars = map[string]interface{}{ + "USER": "jatin", + "ROLE": "USER", + } + + add = &common.GraphQLParams{ + Query: `mutation{ + addTodo(input: [ + {text : "GraphQL is exciting!!", + owner : "jatin"} + ]) + { + todo{ + text + owner + } + } + }`, + } + + addResult = add.ExecuteAsPost(t, graphQLEndpoint) + require.Nil(t, addResult.Errors) + + jwtToken, err := metaInfo.GetSignedToken("secret", -1) + require.NoError(t, err) + + payload := fmt.Sprintf(`{"Authorization": "%s"}`, jwtToken) + subscriptionClient, err := common.NewGraphQLSubscription(subscriptionEndpoint, &schema.Request{ + Query: `subscription{ + queryTodo{ + owner + text + } + }`, + }, payload) + require.Nil(t, err) + + res, err := subscriptionClient.RecvMsg() + require.NoError(t, err) + + var resp common.GraphQLResponse + err = json.Unmarshal(res, &resp) + require.NoError(t, err) + + require.Nil(t, resp.Errors) + require.JSONEq(t, `{"queryTodo":[{"owner":"jatin","text":"GraphQL is exciting!!"}]}`, + string(resp.Data)) +} + func TestSubscriptionAuth_SameQueryAndClaimsButDifferentExpiry_ShouldExpireIndependently(t *testing.T) { t.Skip() dg, err := testutil.DgraphClient(groupOnegRPC) diff --git a/graphql/web/http.go b/graphql/web/http.go index b53f76b6d6c..7409d5080f5 100644 --- a/graphql/web/http.go +++ b/graphql/web/http.go @@ -20,11 +20,10 @@ import ( "compress/gzip" "context" "encoding/json" - "strconv" - "time" - "github.com/dgrijalva/jwt-go/v4" "google.golang.org/grpc/metadata" + "strconv" + "time" "io" "io/ioutil" @@ -127,13 +126,11 @@ func (gs *graphqlSubscription) Subscribe( // library (graphql-transport-ws) passes the headers which are part of the INIT payload to us in the context. // And we are extracting the Auth JWT from those and passing them along. - - header, _ := ctx.Value("Header").(json.RawMessage) customClaims := &authorization.CustomClaims{ - StandardClaims: jwt.StandardClaims{ - ExpiresAt: jwt.At(time.Time{}), - }, + StandardClaims: jwt.StandardClaims{}, } + header, _ := ctx.Value("Header").(json.RawMessage) + if len(header) > 0 { payload := make(map[string]interface{}) if err := json.Unmarshal(header, &payload); err != nil { @@ -155,7 +152,11 @@ func (gs *graphqlSubscription) Subscribe( } } } - + // for the cases when no expiry is given in jwt or subscription doesn't have any authorization, + // we set their expiry to zero time + if customClaims.StandardClaims.ExpiresAt == nil { + customClaims.StandardClaims.ExpiresAt = jwt.At(time.Time{}) + } req := &schema.Request{ OperationName: operationName, Query: document, diff --git a/testutil/graphql.go b/testutil/graphql.go index 1c17260046c..009f9c81b45 100644 --- a/testutil/graphql.go +++ b/testutil/graphql.go @@ -158,10 +158,12 @@ func (a *AuthMeta) GetSignedToken(privateKeyFile string, a.Namespace, a.AuthVars, jwt.StandardClaims{ - ExpiresAt: jwt.At(time.Now().Add(expireAfter)), - Issuer: "test", + Issuer: "test", }, } + if expireAfter != -1 { + claims.ExpiresAt = jwt.At(time.Now().Add(expireAfter)) + } var signedString string var err error