Let auth data be updated on login (#2219)
* Let user update authData token upon login * Adds tests that ensures linked authData isnt overriden * fixes focused testing problem
This commit is contained in:
@@ -907,13 +907,11 @@ describe('Parse.User testing', () => {
|
|||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Note that this mocks out client-side Facebook action rather than
|
var getMockFacebookProviderWithIdToken = function(id, token) {
|
||||||
// server-side.
|
|
||||||
var getMockFacebookProvider = function() {
|
|
||||||
return {
|
return {
|
||||||
authData: {
|
authData: {
|
||||||
id: "8675309",
|
id: id,
|
||||||
access_token: "jenny",
|
access_token: token,
|
||||||
expiration_date: new Date().toJSON(),
|
expiration_date: new Date().toJSON(),
|
||||||
},
|
},
|
||||||
shouldError: false,
|
shouldError: false,
|
||||||
@@ -951,6 +949,12 @@ describe('Parse.User testing', () => {
|
|||||||
this.restoreAuthentication(null);
|
this.restoreAuthentication(null);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that this mocks out client-side Facebook action rather than
|
||||||
|
// server-side.
|
||||||
|
var getMockFacebookProvider = function() {
|
||||||
|
return getMockFacebookProviderWithIdToken('8675309', 'jenny');
|
||||||
};
|
};
|
||||||
|
|
||||||
var getMockMyOauthProvider = function() {
|
var getMockMyOauthProvider = function() {
|
||||||
@@ -1025,6 +1029,40 @@ describe('Parse.User testing', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it_exclude_dbs(['postgres'])("log in with provider and update token", (done) => {
|
||||||
|
var provider = getMockFacebookProvider();
|
||||||
|
var secondProvider = getMockFacebookProviderWithIdToken('8675309', 'jenny_valid_token');
|
||||||
|
var errorHandler = function(err) {
|
||||||
|
fail('should not fail');
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
Parse.User._registerAuthenticationProvider(provider);
|
||||||
|
Parse.User._logInWith("facebook", {
|
||||||
|
success: (model) => {
|
||||||
|
Parse.User._registerAuthenticationProvider(secondProvider);
|
||||||
|
return Parse.User.logOut().then(() => {
|
||||||
|
Parse.User._logInWith("facebook", {
|
||||||
|
success: (model) => {
|
||||||
|
expect(secondProvider.synchronizedAuthToken).toEqual('jenny_valid_token');
|
||||||
|
// Make sure we can login with the new token again
|
||||||
|
Parse.User.logOut().then(() => {
|
||||||
|
Parse.User._logInWith("facebook", {
|
||||||
|
success: done,
|
||||||
|
error: errorHandler
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
error: errorHandler
|
||||||
|
});
|
||||||
|
})
|
||||||
|
},
|
||||||
|
error: errorHandler
|
||||||
|
}).catch((err) => {
|
||||||
|
errorHandler(err);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it_exclude_dbs(['postgres'])('returns authData when authed and logged in with provider (regression test for #1498)', done => {
|
it_exclude_dbs(['postgres'])('returns authData when authed and logged in with provider (regression test for #1498)', done => {
|
||||||
Parse.Object.enableSingleInstance();
|
Parse.Object.enableSingleInstance();
|
||||||
let provider = getMockFacebookProvider();
|
let provider = getMockFacebookProvider();
|
||||||
@@ -1428,6 +1466,47 @@ describe('Parse.User testing', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it_exclude_dbs(['postgres'])("link multiple providers and updates token", (done) => {
|
||||||
|
var provider = getMockFacebookProvider();
|
||||||
|
var secondProvider = getMockFacebookProviderWithIdToken('8675309', 'jenny_valid_token');
|
||||||
|
|
||||||
|
var errorHandler = function(model, error) {
|
||||||
|
console.error(error);
|
||||||
|
fail('Should not fail');
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
var mockProvider = getMockMyOauthProvider();
|
||||||
|
Parse.User._registerAuthenticationProvider(provider);
|
||||||
|
Parse.User._logInWith("facebook", {
|
||||||
|
success: function(model) {
|
||||||
|
Parse.User._registerAuthenticationProvider(mockProvider);
|
||||||
|
let objectId = model.id;
|
||||||
|
model._linkWith("myoauth", {
|
||||||
|
success: function(model) {
|
||||||
|
Parse.User._registerAuthenticationProvider(secondProvider);
|
||||||
|
Parse.User.logOut().then(() => {
|
||||||
|
return Parse.User._logInWith("facebook", {
|
||||||
|
success: () => {
|
||||||
|
Parse.User.logOut().then(() => {
|
||||||
|
return Parse.User._logInWith("myoauth", {
|
||||||
|
success: (user) => {
|
||||||
|
expect(user.id).toBe(objectId);
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
error: errorHandler
|
||||||
|
});
|
||||||
|
})
|
||||||
|
},
|
||||||
|
error: errorHandler
|
||||||
|
})
|
||||||
|
},
|
||||||
|
error: errorHandler
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it_exclude_dbs(['postgres'])("link multiple providers and update token", (done) => {
|
it_exclude_dbs(['postgres'])("link multiple providers and update token", (done) => {
|
||||||
var provider = getMockFacebookProvider();
|
var provider = getMockFacebookProvider();
|
||||||
var mockProvider = getMockMyOauthProvider();
|
var mockProvider = getMockMyOauthProvider();
|
||||||
|
|||||||
@@ -281,17 +281,17 @@ function range(n) {
|
|||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
function mockFacebook() {
|
function mockFacebookAuthenticator(id, token) {
|
||||||
var facebook = {};
|
var facebook = {};
|
||||||
facebook.validateAuthData = function(authData) {
|
facebook.validateAuthData = function(authData) {
|
||||||
if (authData.id === '8675309' && authData.access_token === 'jenny') {
|
if (authData.id === id && authData.access_token.startsWith(token)) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
} else {
|
} else {
|
||||||
throw undefined;
|
throw undefined;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
facebook.validateAppId = function(appId, authData) {
|
facebook.validateAppId = function(appId, authData) {
|
||||||
if (authData.access_token === 'jenny') {
|
if (authData.access_token.startsWith(token)) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
} else {
|
} else {
|
||||||
throw undefined;
|
throw undefined;
|
||||||
@@ -300,6 +300,10 @@ function mockFacebook() {
|
|||||||
return facebook;
|
return facebook;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mockFacebook() {
|
||||||
|
return mockFacebookAuthenticator('8675309', 'jenny');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// This is polluting, but, it makes it way easier to directly port old tests.
|
// This is polluting, but, it makes it way easier to directly port old tests.
|
||||||
@@ -320,6 +324,7 @@ global.jequal = jequal;
|
|||||||
global.range = range;
|
global.range = range;
|
||||||
global.reconfigureServer = reconfigureServer;
|
global.reconfigureServer = reconfigureServer;
|
||||||
global.defaultConfiguration = defaultConfiguration;
|
global.defaultConfiguration = defaultConfiguration;
|
||||||
|
global.mockFacebookAuthenticator = mockFacebookAuthenticator;
|
||||||
|
|
||||||
global.it_exclude_dbs = excluded => {
|
global.it_exclude_dbs = excluded => {
|
||||||
if (excluded.includes(process.env.PARSE_SERVER_TEST_DB)) {
|
if (excluded.includes(process.env.PARSE_SERVER_TEST_DB)) {
|
||||||
|
|||||||
@@ -290,14 +290,41 @@ RestWrite.prototype.handleAuthData = function(authData) {
|
|||||||
if (results.length > 0) {
|
if (results.length > 0) {
|
||||||
if (!this.query) {
|
if (!this.query) {
|
||||||
// Login with auth data
|
// Login with auth data
|
||||||
// Short circuit
|
|
||||||
delete results[0].password;
|
delete results[0].password;
|
||||||
|
let userResult = results[0];
|
||||||
|
|
||||||
// need to set the objectId first otherwise location has trailing undefined
|
// need to set the objectId first otherwise location has trailing undefined
|
||||||
this.data.objectId = results[0].objectId;
|
this.data.objectId = userResult.objectId;
|
||||||
|
|
||||||
|
// Determine if authData was updated
|
||||||
|
let mutatedAuthData = {};
|
||||||
|
Object.keys(authData).forEach((provider) => {
|
||||||
|
let providerData = authData[provider];
|
||||||
|
let userAuthData = userResult.authData[provider];
|
||||||
|
if (!_.isEqual(providerData, userAuthData)) {
|
||||||
|
mutatedAuthData[provider] = providerData;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.response = {
|
this.response = {
|
||||||
response: results[0],
|
response: userResult,
|
||||||
location: this.location()
|
location: this.location()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// We have authData that is updated on login
|
||||||
|
// that can happen when token are refreshed,
|
||||||
|
// We should update the token and let the user in
|
||||||
|
if (Object.keys(mutatedAuthData).length > 0) {
|
||||||
|
// Assign the new authData in the response
|
||||||
|
Object.keys(mutatedAuthData).forEach((provider) => {
|
||||||
|
this.response.response.authData[provider] = mutatedAuthData[provider];
|
||||||
|
});
|
||||||
|
// Run the DB update directly, as 'master'
|
||||||
|
// Just update the authData part
|
||||||
|
return this.config.database.update(this.className, {objectId: this.data.objectId}, {authData: mutatedAuthData}, {});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
} else if (this.query && this.query.objectId) {
|
} else if (this.query && this.query.objectId) {
|
||||||
// Trying to update auth data but users
|
// Trying to update auth data but users
|
||||||
// are different
|
// are different
|
||||||
|
|||||||
Reference in New Issue
Block a user