Skip to content

Commit f91034a

Browse files
douglasmuraokadavimacedo
authored andcommitted
GraphQL: Improve session token error messages (#5753)
* GraphQL: Improve session token error message Fixes the session token related error messages during GraphQL operations. If any authentication error were thrown, it was not correctly handled by the GraphQL express middleware, and ended responding the request with a JSON parsing error. * Refactor handleError usage * Use handleParseErrors middleware to handle invalid session token error * fix: Status code 400 when session token is invalid * fix: Undo handleParseErrors middleware change
1 parent 1c62ab6 commit f91034a

File tree

4 files changed

+125
-12
lines changed

4 files changed

+125
-12
lines changed

spec/ParseGraphQLServer.spec.js

Lines changed: 107 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3248,8 +3248,8 @@ describe('ParseGraphQLServer', () => {
32483248
});
32493249
expect(logOut.data.users.logOut).toBeTruthy();
32503250

3251-
await expectAsync(
3252-
apolloClient.query({
3251+
try {
3252+
await apolloClient.query({
32533253
query: gql`
32543254
query GetCurrentUser {
32553255
users {
@@ -3264,8 +3264,111 @@ describe('ParseGraphQLServer', () => {
32643264
'X-Parse-Session-Token': sessionToken,
32653265
},
32663266
},
3267-
})
3268-
).toBeRejected();
3267+
});
3268+
fail('should not retrieve current user due to session token');
3269+
} catch (err) {
3270+
const { statusCode, result } = err.networkError;
3271+
expect(statusCode).toBe(400);
3272+
expect(result).toEqual({
3273+
code: 209,
3274+
error: 'Invalid session token',
3275+
});
3276+
}
3277+
});
3278+
});
3279+
3280+
describe('Session Token', () => {
3281+
it('should fail due to invalid session token', async () => {
3282+
try {
3283+
await apolloClient.query({
3284+
query: gql`
3285+
query GetCurrentUser {
3286+
users {
3287+
me {
3288+
username
3289+
}
3290+
}
3291+
}
3292+
`,
3293+
context: {
3294+
headers: {
3295+
'X-Parse-Session-Token': 'foo',
3296+
},
3297+
},
3298+
});
3299+
fail('should not retrieve current user due to session token');
3300+
} catch (err) {
3301+
const { statusCode, result } = err.networkError;
3302+
expect(statusCode).toBe(400);
3303+
expect(result).toEqual({
3304+
code: 209,
3305+
error: 'Invalid session token',
3306+
});
3307+
}
3308+
});
3309+
3310+
it('should fail due to empty session token', async () => {
3311+
try {
3312+
await apolloClient.query({
3313+
query: gql`
3314+
query GetCurrentUser {
3315+
users {
3316+
me {
3317+
username
3318+
}
3319+
}
3320+
}
3321+
`,
3322+
context: {
3323+
headers: {
3324+
'X-Parse-Session-Token': '',
3325+
},
3326+
},
3327+
});
3328+
fail('should not retrieve current user due to session token');
3329+
} catch (err) {
3330+
const { graphQLErrors } = err;
3331+
expect(graphQLErrors.length).toBe(1);
3332+
expect(graphQLErrors[0].message).toBe('Invalid session token');
3333+
}
3334+
});
3335+
3336+
it('should find a user and fail due to empty session token', async () => {
3337+
const car = new Parse.Object('Car');
3338+
await car.save();
3339+
3340+
await parseGraphQLServer.parseGraphQLSchema.databaseController.schemaCache.clear();
3341+
3342+
try {
3343+
await apolloClient.query({
3344+
query: gql`
3345+
query GetCurrentUser {
3346+
users {
3347+
me {
3348+
username
3349+
}
3350+
}
3351+
objects {
3352+
findCar {
3353+
results {
3354+
objectId
3355+
}
3356+
}
3357+
}
3358+
}
3359+
`,
3360+
context: {
3361+
headers: {
3362+
'X-Parse-Session-Token': '',
3363+
},
3364+
},
3365+
});
3366+
fail('should not retrieve current user due to session token');
3367+
} catch (err) {
3368+
const { graphQLErrors } = err;
3369+
expect(graphQLErrors.length).toBe(1);
3370+
expect(graphQLErrors[0].message).toBe('Invalid session token');
3371+
}
32693372
});
32703373
});
32713374

src/GraphQL/ParseGraphQLSchema.js

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import Parse from 'parse/node';
22
import { GraphQLSchema, GraphQLObjectType } from 'graphql';
3-
import { ApolloError } from 'apollo-server-core';
43
import requiredParameter from '../requiredParameter';
54
import * as defaultGraphQLTypes from './loaders/defaultGraphQLTypes';
65
import * as parseClassTypes from './loaders/parseClassTypes';
76
import * as parseClassQueries from './loaders/parseClassQueries';
87
import * as parseClassMutations from './loaders/parseClassMutations';
98
import * as defaultGraphQLQueries from './loaders/defaultGraphQLQueries';
109
import * as defaultGraphQLMutations from './loaders/defaultGraphQLMutations';
10+
import { toGraphQLError } from './parseGraphQLUtils';
1111

1212
class ParseGraphQLSchema {
1313
constructor(databaseController, log) {
@@ -100,17 +100,12 @@ class ParseGraphQLSchema {
100100
}
101101

102102
handleError(error) {
103-
let code, message;
104103
if (error instanceof Parse.Error) {
105104
this.log.error('Parse error: ', error);
106-
code = error.code;
107-
message = error.message;
108105
} else {
109106
this.log.error('Uncaught internal server error.', error, error.stack);
110-
code = Parse.Error.INTERNAL_SERVER_ERROR;
111-
message = 'Internal server error.';
112107
}
113-
throw new ApolloError(message, code);
108+
throw toGraphQLError(error);
114109
}
115110
}
116111

src/GraphQL/ParseGraphQLServer.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { graphqlExpress } from 'apollo-server-express/dist/expressApollo';
55
import { renderPlaygroundPage } from '@apollographql/graphql-playground-html';
66
import { execute, subscribe } from 'graphql';
77
import { SubscriptionServer } from 'subscriptions-transport-ws';
8-
import { handleParseHeaders } from '../middlewares';
8+
import { handleParseErrors, handleParseHeaders } from '../middlewares';
99
import requiredParameter from '../requiredParameter';
1010
import defaultLogger from '../logger';
1111
import { ParseGraphQLSchema } from './ParseGraphQLSchema';
@@ -55,6 +55,7 @@ class ParseGraphQLServer {
5555
app.use(this.config.graphQLPath, corsMiddleware());
5656
app.use(this.config.graphQLPath, bodyParser.json());
5757
app.use(this.config.graphQLPath, handleParseHeaders);
58+
app.use(this.config.graphQLPath, handleParseErrors);
5859
app.use(
5960
this.config.graphQLPath,
6061
graphqlExpress(async req => await this._getGraphQLOptions(req))

src/GraphQL/parseGraphQLUtils.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import Parse from 'parse/node';
2+
import { ApolloError } from 'apollo-server-core';
3+
4+
export function toGraphQLError(error) {
5+
let code, message;
6+
if (error instanceof Parse.Error) {
7+
code = error.code;
8+
message = error.message;
9+
} else {
10+
code = Parse.Error.INTERNAL_SERVER_ERROR;
11+
message = 'Internal server error';
12+
}
13+
return new ApolloError(message, code);
14+
}

0 commit comments

Comments
 (0)