Merge pull request from GHSA-236h-rqv8-8q73

* Fix graphql viewer breach

* fix

* remove comment
This commit is contained in:
Antoine Cormouls
2020-07-17 18:50:41 +02:00
committed by GitHub
parent f6ed5067b0
commit 78239ac907
3 changed files with 226 additions and 181 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -41,7 +41,7 @@ const load = parseGraphQLSchema => {
const { fields } = args; const { fields } = args;
const { config, auth, info } = context; const { config, auth, info } = context;
const { sessionToken } = await objectsMutations.createObject( const { sessionToken, objectId } = await objectsMutations.createObject(
'_User', '_User',
fields, fields,
config, config,
@@ -49,15 +49,14 @@ const load = parseGraphQLSchema => {
info info
); );
info.sessionToken = sessionToken; context.info.sessionToken = sessionToken;
return { return {
viewer: await getUserFromSessionToken( viewer: await getUserFromSessionToken(
config, context,
info,
mutationInfo, mutationInfo,
'viewer.user.', 'viewer.user.',
true objectId
), ),
}; };
} catch (e) { } catch (e) {
@@ -120,7 +119,7 @@ const load = parseGraphQLSchema => {
const { fields, authData } = args; const { fields, authData } = args;
const { config, auth, info } = context; const { config, auth, info } = context;
const { sessionToken } = await objectsMutations.createObject( const { sessionToken, objectId } = await objectsMutations.createObject(
'_User', '_User',
{ ...fields, authData }, { ...fields, authData },
config, config,
@@ -128,15 +127,14 @@ const load = parseGraphQLSchema => {
info info
); );
info.sessionToken = sessionToken; context.info.sessionToken = sessionToken;
return { return {
viewer: await getUserFromSessionToken( viewer: await getUserFromSessionToken(
config, context,
info,
mutationInfo, mutationInfo,
'viewer.user.', 'viewer.user.',
true objectId
), ),
}; };
} catch (e) { } catch (e) {
@@ -183,7 +181,7 @@ const load = parseGraphQLSchema => {
const { username, password } = args; const { username, password } = args;
const { config, auth, info } = context; const { config, auth, info } = context;
const { sessionToken } = ( const { sessionToken, objectId } = (
await usersRouter.handleLogIn({ await usersRouter.handleLogIn({
body: { body: {
username, username,
@@ -196,15 +194,14 @@ const load = parseGraphQLSchema => {
}) })
).response; ).response;
info.sessionToken = sessionToken; context.info.sessionToken = sessionToken;
return { return {
viewer: await getUserFromSessionToken( viewer: await getUserFromSessionToken(
config, context,
info,
mutationInfo, mutationInfo,
'viewer.user.', 'viewer.user.',
true objectId
), ),
}; };
} catch (e) { } catch (e) {
@@ -236,11 +233,10 @@ const load = parseGraphQLSchema => {
const { config, auth, info } = context; const { config, auth, info } = context;
const viewer = await getUserFromSessionToken( const viewer = await getUserFromSessionToken(
config, context,
info,
mutationInfo, mutationInfo,
'viewer.user.', 'viewer.user.',
true auth.user.id
); );
await usersRouter.handleLogOut({ await usersRouter.handleLogOut({

View File

@@ -2,16 +2,16 @@ import { GraphQLNonNull } from 'graphql';
import getFieldNames from 'graphql-list-fields'; import getFieldNames from 'graphql-list-fields';
import Parse from 'parse/node'; import Parse from 'parse/node';
import rest from '../../rest'; import rest from '../../rest';
import Auth from '../../Auth';
import { extractKeysAndInclude } from './parseClassTypes'; import { extractKeysAndInclude } from './parseClassTypes';
import { Auth } from '../../Auth';
const getUserFromSessionToken = async ( const getUserFromSessionToken = async (
config, context,
info,
queryInfo, queryInfo,
keysPrefix, keysPrefix,
validatedToken userId
) => { ) => {
const { info, config } = context;
if (!info || !info.sessionToken) { if (!info || !info.sessionToken) {
throw new Parse.Error( throw new Parse.Error(
Parse.Error.INVALID_SESSION_TOKEN, Parse.Error.INVALID_SESSION_TOKEN,
@@ -27,7 +27,7 @@ const getUserFromSessionToken = async (
const { keys } = keysAndInclude; const { keys } = keysAndInclude;
let { include } = keysAndInclude; let { include } = keysAndInclude;
if (validatedToken && !keys && !include) { if (userId && !keys && !include) {
return { return {
sessionToken, sessionToken,
}; };
@@ -35,40 +35,47 @@ const getUserFromSessionToken = async (
include = 'user'; include = 'user';
} }
if (userId) {
// We need to re create the auth context
// to avoid security breach if userId is provided
context.auth = new Auth({
config,
isMaster: context.auth.isMaster,
user: { id: userId },
});
}
const options = {}; const options = {};
if (keys) { if (keys) {
options.keys = keys options.keys = keys
.split(',') .split(',')
.map(key => `user.${key}`) .map(key => `${key}`)
.join(','); .join(',');
} }
if (include) { if (include) {
options.include = include options.include = include
.split(',') .split(',')
.map(included => `user.${included}`) .map(included => `${included}`)
.join(','); .join(',');
} }
const response = await rest.find( const response = await rest.find(
config, config,
Auth.master(config), context.auth,
'_Session', '_User',
{ sessionToken }, // Get the user it self from auth object
{ objectId: context.auth.user.id },
options, options,
info.clientVersion, info.clientVersion,
info.context, info.context
); );
if ( if (!response.results || response.results.length == 0) {
!response.results ||
response.results.length == 0 ||
!response.results[0].user
) {
throw new Parse.Error( throw new Parse.Error(
Parse.Error.INVALID_SESSION_TOKEN, Parse.Error.INVALID_SESSION_TOKEN,
'Invalid session token' 'Invalid session token'
); );
} else { } else {
const user = response.results[0].user; const user = response.results[0];
return { return {
sessionToken, sessionToken,
user, user,
@@ -89,10 +96,8 @@ const load = parseGraphQLSchema => {
type: new GraphQLNonNull(parseGraphQLSchema.viewerType), type: new GraphQLNonNull(parseGraphQLSchema.viewerType),
async resolve(_source, _args, context, queryInfo) { async resolve(_source, _args, context, queryInfo) {
try { try {
const { config, info } = context;
return await getUserFromSessionToken( return await getUserFromSessionToken(
config, context,
info,
queryInfo, queryInfo,
'user.', 'user.',
false false