Skip to content

Commit

Permalink
fix(GraphQl): Panic fix when subscription expiry is not present in jw…
Browse files Browse the repository at this point in the history
…t. (#6129) (#6175)

This PR fixes panic error when expiry is not given in jwt for subscriptions using authorization.

(cherry picked from commit 37823e9)
  • Loading branch information
JatinDev543 authored Aug 13, 2020
1 parent fed5092 commit 9cbe51f
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 11 deletions.
74 changes: 74 additions & 0 deletions graphql/e2e/subscription/subscription_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
19 changes: 10 additions & 9 deletions graphql/web/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand All @@ -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,
Expand Down
6 changes: 4 additions & 2 deletions testutil/graphql.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 9cbe51f

Please sign in to comment.