Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix beforeLogin for users logging in with AuthData #6872

Merged
merged 12 commits into from
Aug 25, 2020
Merged
309 changes: 182 additions & 127 deletions package-lock.json

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
"license": "BSD-3-Clause",
"dependencies": {
"@apollographql/graphql-playground-html": "1.6.26",
"@graphql-tools/stitch": "6.0.12",
"@graphql-tools/utils": "6.0.12",
"@graphql-tools/stitch": "6.0.13",
"@graphql-tools/utils": "6.0.13",
"@parse/fs-files-adapter": "1.0.1",
"@parse/push-adapter": "3.2.0",
"@parse/s3-files-adapter": "1.4.0",
"@parse/simple-mailgun-adapter": "1.1.0",
"apollo-server-express": "2.15.1",
"apollo-server-express": "2.16.0",
"bcryptjs": "2.4.3",
"body-parser": "1.19.0",
"commander": "5.1.0",
Expand All @@ -41,8 +41,8 @@
"intersect": "1.0.1",
"jsonwebtoken": "8.5.1",
"jwks-rsa": "1.8.1",
"ldapjs": "2.0.0",
"lodash": "4.17.19",
"ldapjs": "2.1.0",
"lodash": "4.17.20",
"lru-cache": "5.1.1",
"mime": "2.4.6",
"mongodb": "3.5.9",
Expand All @@ -53,8 +53,8 @@
"semver": "7.3.2",
"subscriptions-transport-ws": "0.9.17",
"tv4": "1.3.0",
"uuid": "8.2.0",
"winston": "3.2.1",
"uuid": "8.3.0",
"winston": "3.3.2",
"winston-daily-rotate-file": "4.5.0",
"ws": "7.3.1"
},
Expand Down
115 changes: 18 additions & 97 deletions spec/AuthenticationAdapters.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ describe('AuthenticationProviders', function () {
'gcenter',
'gpgames',
'facebook',
'facebookaccountkit',
'github',
'instagram',
'google',
Expand All @@ -43,7 +42,7 @@ describe('AuthenticationProviders', function () {
'phantauth',
'microsoft',
].map(function (providerName) {
it('Should validate structure of ' + providerName, (done) => {
it('Should validate structure of ' + providerName, done => {
const provider = require('../lib/Adapters/Auth/' + providerName);
jequal(typeof provider.validateAuthData, 'function');
jequal(typeof provider.validateAppId, 'function');
Expand Down Expand Up @@ -71,7 +70,7 @@ describe('AuthenticationProviders', function () {
return;
}
spyOn(require('../lib/Adapters/Auth/httpsRequest'), 'get').and.callFake(
(options) => {
options => {
if (
options ===
'https://oauth.vk.com/access_token?client_id=appId&client_secret=appSecret&v=5.59&grant_type=client_credentials'
Expand Down Expand Up @@ -175,7 +174,7 @@ describe('AuthenticationProviders', function () {
body: jsonBody,
};
return request(options)
.then((response) => {
.then(response => {
if (callback) {
callback(null, response, response.data);
}
Expand All @@ -184,15 +183,15 @@ describe('AuthenticationProviders', function () {
body: response.data,
};
})
.catch((error) => {
.catch(error => {
if (callback) {
callback(error);
}
throw error;
});
};

it('should create user with REST API', (done) => {
it('should create user with REST API', done => {
createOAuthUser((error, response, body) => {
expect(error).toBe(null);
const b = body;
Expand All @@ -203,7 +202,7 @@ describe('AuthenticationProviders', function () {
const q = new Parse.Query('_Session');
q.equalTo('sessionToken', sessionToken);
q.first({ useMasterKey: true })
.then((res) => {
.then(res => {
if (!res) {
fail('should not fail fetching the session');
done();
Expand All @@ -219,7 +218,7 @@ describe('AuthenticationProviders', function () {
});
});

it('should only create a single user with REST API', (done) => {
it('should only create a single user with REST API', done => {
let objectId;
createOAuthUser((error, response, body) => {
expect(error).toBe(null);
Expand All @@ -239,9 +238,9 @@ describe('AuthenticationProviders', function () {
});
});

it("should fail to link if session token don't match user", (done) => {
it("should fail to link if session token don't match user", done => {
Parse.User.signUp('myUser', 'password')
.then((user) => {
.then(user => {
return createOAuthUserWithSessionToken(user.getSessionToken());
})
.then(() => {
Expand All @@ -250,7 +249,7 @@ describe('AuthenticationProviders', function () {
.then(() => {
return Parse.User.signUp('myUser2', 'password');
})
.then((user) => {
.then(user => {
return createOAuthUserWithSessionToken(user.getSessionToken());
})
.then(fail, ({ data }) => {
Expand Down Expand Up @@ -330,7 +329,7 @@ describe('AuthenticationProviders', function () {
expect(typeof authAdapter.validateAppId).toBe('function');
}

it('properly loads custom adapter', (done) => {
it('properly loads custom adapter', done => {
const validAuthData = {
id: 'hello',
token: 'world',
Expand Down Expand Up @@ -370,14 +369,14 @@ describe('AuthenticationProviders', function () {
expect(appIdSpy).not.toHaveBeenCalled();
done();
},
(err) => {
err => {
jfail(err);
done();
}
);
});

it('properly loads custom adapter module object', (done) => {
it('properly loads custom adapter module object', done => {
const authenticationHandler = authenticationLoader({
customAuthentication: path.resolve('./spec/support/CustomAuth.js'),
});
Expand All @@ -394,14 +393,14 @@ describe('AuthenticationProviders', function () {
() => {
done();
},
(err) => {
err => {
jfail(err);
done();
}
);
});

it('properly loads custom adapter module object (again)', (done) => {
it('properly loads custom adapter module object (again)', done => {
const authenticationHandler = authenticationLoader({
customAuthentication: {
module: path.resolve('./spec/support/CustomAuthFunction.js'),
Expand All @@ -421,7 +420,7 @@ describe('AuthenticationProviders', function () {
() => {
done();
},
(err) => {
err => {
jfail(err);
done();
}
Expand Down Expand Up @@ -512,84 +511,6 @@ describe('AuthenticationProviders', function () {
expect(appIds).toEqual(['a', 'b']);
expect(providerOptions).toEqual(options.custom);
});

it('properly loads Facebook accountkit adapter with options', () => {
const options = {
facebookaccountkit: {
appIds: ['a', 'b'],
appSecret: 'secret',
},
};
const {
adapter,
appIds,
providerOptions,
} = authenticationLoader.loadAuthAdapter('facebookaccountkit', options);
validateAuthenticationAdapter(adapter);
expect(appIds).toEqual(['a', 'b']);
expect(providerOptions.appSecret).toEqual('secret');
});

it('should fail if Facebook appIds is not configured properly', (done) => {
const options = {
facebookaccountkit: {
appIds: [],
},
};
const { adapter, appIds } = authenticationLoader.loadAuthAdapter(
'facebookaccountkit',
options
);
adapter.validateAppId(appIds).then(done.fail, (err) => {
expect(err.code).toBe(Parse.Error.OBJECT_NOT_FOUND);
done();
});
});

it('should fail to validate Facebook accountkit auth with bad token', (done) => {
const options = {
facebookaccountkit: {
appIds: ['a', 'b'],
},
};
const authData = {
id: 'fakeid',
access_token: 'badtoken',
};
const { adapter } = authenticationLoader.loadAuthAdapter(
'facebookaccountkit',
options
);
adapter.validateAuthData(authData).then(done.fail, (err) => {
expect(err.code).toBe(190);
expect(err.type).toBe('OAuthException');
done();
});
});

it('should fail to validate Facebook accountkit auth with bad token regardless of app secret proof', (done) => {
const options = {
facebookaccountkit: {
appIds: ['a', 'b'],
appSecret: 'badsecret',
},
};
const authData = {
id: 'fakeid',
access_token: 'badtoken',
};
const { adapter, providerOptions } = authenticationLoader.loadAuthAdapter(
'facebookaccountkit',
options
);
adapter
.validateAuthData(authData, providerOptions)
.then(done.fail, (err) => {
expect(err.code).toBe(190);
expect(err.type).toBe('OAuthException');
done();
});
});
});

describe('instagram auth adapter', () => {
Expand Down Expand Up @@ -1653,13 +1574,13 @@ describe('microsoft graph auth adapter', () => {
});
});

it('should fail to validate Microsoft Graph auth with bad token', (done) => {
it('should fail to validate Microsoft Graph auth with bad token', done => {
const authData = {
id: 'fake-id',
mail: 'fake@mail.com',
access_token: 'very.long.bad.token',
};
microsoft.validateAuthData(authData).then(done.fail, (err) => {
microsoft.validateAuthData(authData).then(done.fail, err => {
expect(err.code).toBe(101);
expect(err.message).toBe(
'Microsoft Graph auth is invalid for this user.'
Expand Down
22 changes: 11 additions & 11 deletions spec/FilesController.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const mockAdapter = {

// Small additional tests to improve overall coverage
describe('FilesController', () => {
it('should properly expand objects', (done) => {
it('should properly expand objects', done => {
const config = Config.get(Parse.applicationId);
const gridStoreAdapter = new GridFSBucketAdapter(
'mongodb://localhost:27017/parse'
Expand All @@ -48,7 +48,7 @@ describe('FilesController', () => {
done();
});

it('should create a server log on failure', (done) => {
it('should create a server log on failure', done => {
const logController = new LoggerController(new WinstonLoggerAdapter());

reconfigureServer({ filesAdapter: mockAdapter })
Expand All @@ -57,28 +57,28 @@ describe('FilesController', () => {
() => done.fail('should not succeed'),
() => setImmediate(() => Promise.resolve('done'))
)
.then(() => new Promise((resolve) => setTimeout(resolve, 200)))
.then(() => new Promise(resolve => setTimeout(resolve, 200)))
.then(() =>
logController.getLogs({ from: Date.now() - 1000, size: 1000 })
)
.then((logs) => {
.then(logs => {
// we get two logs here: 1. the source of the failure to save the file
// and 2 the message that will be sent back to the client.

const log1 = logs.find(
(x) => x.message === 'Error creating a file: it failed with xyz'
x => x.message === 'Error creating a file: it failed with xyz'
);
expect(log1.level).toBe('error');

const log2 = logs.find((x) => x.message === 'it failed with xyz');
const log2 = logs.find(x => x.message === 'it failed with xyz');
expect(log2.level).toBe('error');
expect(log2.code).toBe(130);

done();
});
});

it('should create a parse error when a string is returned', (done) => {
it('should create a parse error when a string is returned', done => {
const mock2 = mockAdapter;
mock2.validateFilename = () => {
return 'Bad file! No biscuit!';
Expand All @@ -91,7 +91,7 @@ describe('FilesController', () => {
done();
});

it('should add a unique hash to the file name when the preserveFileName option is false', (done) => {
it('should add a unique hash to the file name when the preserveFileName option is false', done => {
const config = Config.get(Parse.applicationId);
const gridStoreAdapter = new GridFSBucketAdapter(
'mongodb://localhost:27017/parse'
Expand All @@ -114,7 +114,7 @@ describe('FilesController', () => {
done();
});

it('should not add a unique hash to the file name when the preserveFileName option is true', (done) => {
it('should not add a unique hash to the file name when the preserveFileName option is true', done => {
const config = Config.get(Parse.applicationId);
const gridStoreAdapter = new GridFSBucketAdapter(
'mongodb://localhost:27017/parse'
Expand Down Expand Up @@ -145,7 +145,7 @@ describe('FilesController', () => {
expect(result).toEqual({});
});

it('should reject slashes in file names', (done) => {
it('should reject slashes in file names', done => {
const gridStoreAdapter = new GridFSBucketAdapter(
'mongodb://localhost:27017/parse'
);
Expand All @@ -154,7 +154,7 @@ describe('FilesController', () => {
done();
});

it('should also reject slashes in file names', (done) => {
it('should also reject slashes in file names', done => {
const gridStoreAdapter = new GridStoreAdapter(
'mongodb://localhost:27017/parse'
);
Expand Down
Loading