Remove Facebook AccountKit auth (#6870)

* Remove Facebook AccountKit auth

Account Kit services are no longer available.

https://developers.facebook.com/blog/post/2019/09/09/account-kit-services-no-longer-available-starting-march/

https://www.sinch.com/blog/facebook-account-kit-is-closing-down-are-your-apps-covered/

* remove flaky test
This commit is contained in:
Diamond Lewis
2020-08-20 12:09:54 -05:00
committed by GitHub
parent 4cec333cf9
commit a0ac8e0686
4 changed files with 553 additions and 699 deletions

View File

@@ -25,7 +25,6 @@ describe('AuthenticationProviders', function () {
'gcenter', 'gcenter',
'gpgames', 'gpgames',
'facebook', 'facebook',
'facebookaccountkit',
'github', 'github',
'instagram', 'instagram',
'google', 'google',
@@ -43,7 +42,7 @@ describe('AuthenticationProviders', function () {
'phantauth', 'phantauth',
'microsoft', 'microsoft',
].map(function (providerName) { ].map(function (providerName) {
it('Should validate structure of ' + providerName, (done) => { it('Should validate structure of ' + providerName, done => {
const provider = require('../lib/Adapters/Auth/' + providerName); const provider = require('../lib/Adapters/Auth/' + providerName);
jequal(typeof provider.validateAuthData, 'function'); jequal(typeof provider.validateAuthData, 'function');
jequal(typeof provider.validateAppId, 'function'); jequal(typeof provider.validateAppId, 'function');
@@ -71,7 +70,7 @@ describe('AuthenticationProviders', function () {
return; return;
} }
spyOn(require('../lib/Adapters/Auth/httpsRequest'), 'get').and.callFake( spyOn(require('../lib/Adapters/Auth/httpsRequest'), 'get').and.callFake(
(options) => { options => {
if ( if (
options === options ===
'https://oauth.vk.com/access_token?client_id=appId&client_secret=appSecret&v=5.59&grant_type=client_credentials' 'https://oauth.vk.com/access_token?client_id=appId&client_secret=appSecret&v=5.59&grant_type=client_credentials'
@@ -175,7 +174,7 @@ describe('AuthenticationProviders', function () {
body: jsonBody, body: jsonBody,
}; };
return request(options) return request(options)
.then((response) => { .then(response => {
if (callback) { if (callback) {
callback(null, response, response.data); callback(null, response, response.data);
} }
@@ -184,7 +183,7 @@ describe('AuthenticationProviders', function () {
body: response.data, body: response.data,
}; };
}) })
.catch((error) => { .catch(error => {
if (callback) { if (callback) {
callback(error); callback(error);
} }
@@ -192,7 +191,7 @@ describe('AuthenticationProviders', function () {
}); });
}; };
it('should create user with REST API', (done) => { it('should create user with REST API', done => {
createOAuthUser((error, response, body) => { createOAuthUser((error, response, body) => {
expect(error).toBe(null); expect(error).toBe(null);
const b = body; const b = body;
@@ -203,7 +202,7 @@ describe('AuthenticationProviders', function () {
const q = new Parse.Query('_Session'); const q = new Parse.Query('_Session');
q.equalTo('sessionToken', sessionToken); q.equalTo('sessionToken', sessionToken);
q.first({ useMasterKey: true }) q.first({ useMasterKey: true })
.then((res) => { .then(res => {
if (!res) { if (!res) {
fail('should not fail fetching the session'); fail('should not fail fetching the session');
done(); done();
@@ -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; let objectId;
createOAuthUser((error, response, body) => { createOAuthUser((error, response, body) => {
expect(error).toBe(null); expect(error).toBe(null);
@@ -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') Parse.User.signUp('myUser', 'password')
.then((user) => { .then(user => {
return createOAuthUserWithSessionToken(user.getSessionToken()); return createOAuthUserWithSessionToken(user.getSessionToken());
}) })
.then(() => { .then(() => {
@@ -250,7 +249,7 @@ describe('AuthenticationProviders', function () {
.then(() => { .then(() => {
return Parse.User.signUp('myUser2', 'password'); return Parse.User.signUp('myUser2', 'password');
}) })
.then((user) => { .then(user => {
return createOAuthUserWithSessionToken(user.getSessionToken()); return createOAuthUserWithSessionToken(user.getSessionToken());
}) })
.then(fail, ({ data }) => { .then(fail, ({ data }) => {
@@ -330,7 +329,7 @@ describe('AuthenticationProviders', function () {
expect(typeof authAdapter.validateAppId).toBe('function'); expect(typeof authAdapter.validateAppId).toBe('function');
} }
it('properly loads custom adapter', (done) => { it('properly loads custom adapter', done => {
const validAuthData = { const validAuthData = {
id: 'hello', id: 'hello',
token: 'world', token: 'world',
@@ -370,14 +369,14 @@ describe('AuthenticationProviders', function () {
expect(appIdSpy).not.toHaveBeenCalled(); expect(appIdSpy).not.toHaveBeenCalled();
done(); done();
}, },
(err) => { err => {
jfail(err); jfail(err);
done(); done();
} }
); );
}); });
it('properly loads custom adapter module object', (done) => { it('properly loads custom adapter module object', done => {
const authenticationHandler = authenticationLoader({ const authenticationHandler = authenticationLoader({
customAuthentication: path.resolve('./spec/support/CustomAuth.js'), customAuthentication: path.resolve('./spec/support/CustomAuth.js'),
}); });
@@ -394,14 +393,14 @@ describe('AuthenticationProviders', function () {
() => { () => {
done(); done();
}, },
(err) => { err => {
jfail(err); jfail(err);
done(); done();
} }
); );
}); });
it('properly loads custom adapter module object (again)', (done) => { it('properly loads custom adapter module object (again)', done => {
const authenticationHandler = authenticationLoader({ const authenticationHandler = authenticationLoader({
customAuthentication: { customAuthentication: {
module: path.resolve('./spec/support/CustomAuthFunction.js'), module: path.resolve('./spec/support/CustomAuthFunction.js'),
@@ -421,7 +420,7 @@ describe('AuthenticationProviders', function () {
() => { () => {
done(); done();
}, },
(err) => { err => {
jfail(err); jfail(err);
done(); done();
} }
@@ -512,84 +511,6 @@ describe('AuthenticationProviders', function () {
expect(appIds).toEqual(['a', 'b']); expect(appIds).toEqual(['a', 'b']);
expect(providerOptions).toEqual(options.custom); 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', () => { describe('instagram auth adapter', () => {
@@ -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 = { const authData = {
id: 'fake-id', id: 'fake-id',
mail: 'fake@mail.com', mail: 'fake@mail.com',
access_token: 'very.long.bad.token', 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.code).toBe(101);
expect(err.message).toBe( expect(err.message).toBe(
'Microsoft Graph auth is invalid for this user.' 'Microsoft Graph auth is invalid for this user.'

File diff suppressed because it is too large Load Diff

View File

@@ -1,60 +0,0 @@
const crypto = require('crypto');
const httpsRequest = require('./httpsRequest');
const Parse = require('parse/node').Parse;
const graphRequest = path => {
return httpsRequest.get(`https://graph.accountkit.com/v1.1/${path}`);
};
function getRequestPath(authData, options) {
const access_token = authData.access_token,
appSecret = options && options.appSecret;
if (appSecret) {
const appsecret_proof = crypto
.createHmac('sha256', appSecret)
.update(access_token)
.digest('hex');
return `me?access_token=${access_token}&appsecret_proof=${appsecret_proof}`;
}
return `me?access_token=${access_token}`;
}
function validateAppId(appIds, authData, options) {
if (!appIds.length) {
return Promise.reject(
new Parse.Error(
Parse.Error.OBJECT_NOT_FOUND,
'Facebook app id for Account Kit is not configured.'
)
);
}
return graphRequest(getRequestPath(authData, options)).then(data => {
if (data && data.application && appIds.indexOf(data.application.id) != -1) {
return;
}
throw new Parse.Error(
Parse.Error.OBJECT_NOT_FOUND,
'Facebook app id for Account Kit is invalid for this user.'
);
});
}
function validateAuthData(authData, options) {
return graphRequest(getRequestPath(authData, options)).then(data => {
if (data && data.error) {
throw data.error;
}
if (data && data.id == authData.id) {
return;
}
throw new Parse.Error(
Parse.Error.OBJECT_NOT_FOUND,
'Facebook Account Kit auth is invalid for this user.'
);
});
}
module.exports = {
validateAppId,
validateAuthData,
};

View File

@@ -4,7 +4,6 @@ const apple = require('./apple');
const gcenter = require('./gcenter'); const gcenter = require('./gcenter');
const gpgames = require('./gpgames'); const gpgames = require('./gpgames');
const facebook = require('./facebook'); const facebook = require('./facebook');
const facebookaccountkit = require('./facebookaccountkit');
const instagram = require('./instagram'); const instagram = require('./instagram');
const linkedin = require('./linkedin'); const linkedin = require('./linkedin');
const meetup = require('./meetup'); const meetup = require('./meetup');
@@ -39,7 +38,6 @@ const providers = {
gcenter, gcenter,
gpgames, gpgames,
facebook, facebook,
facebookaccountkit,
instagram, instagram,
linkedin, linkedin,
meetup, meetup,
@@ -62,7 +60,7 @@ const providers = {
}; };
function authDataValidator(adapter, appIds, options) { function authDataValidator(adapter, appIds, options) {
return function(authData) { return function (authData) {
return adapter.validateAuthData(authData, options).then(() => { return adapter.validateAuthData(authData, options).then(() => {
if (appIds) { if (appIds) {
return adapter.validateAppId(appIds, authData, options); return adapter.validateAppId(appIds, authData, options);
@@ -117,13 +115,13 @@ function loadAuthAdapter(provider, authOptions) {
return { adapter, appIds, providerOptions }; return { adapter, appIds, providerOptions };
} }
module.exports = function(authOptions = {}, enableAnonymousUsers = true) { module.exports = function (authOptions = {}, enableAnonymousUsers = true) {
let _enableAnonymousUsers = enableAnonymousUsers; let _enableAnonymousUsers = enableAnonymousUsers;
const setEnableAnonymousUsers = function(enable) { const setEnableAnonymousUsers = function (enable) {
_enableAnonymousUsers = enable; _enableAnonymousUsers = enable;
}; };
// To handle the test cases on configuration // To handle the test cases on configuration
const getValidatorForProvider = function(provider) { const getValidatorForProvider = function (provider) {
if (provider === 'anonymous' && !_enableAnonymousUsers) { if (provider === 'anonymous' && !_enableAnonymousUsers) {
return; return;
} }