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(AuthAdapters): Do not revalidate auth data if hasn't changed #3872

Merged
merged 2 commits into from
May 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions spec/ParseUser.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1730,6 +1730,57 @@ describe('Parse.User testing', () => {
});
});

it('should allow PUT request with stale auth Data', (done) => {
const provider = {
authData: {
id: '12345',
access_token: 'token'
},
restoreAuthentication: function() {
return true;
},
deauthenticate: function() {
provider.authData = {};
},
authenticate: function(options) {
options.success(this, provider.authData);
},
getAuthType: function() {
return "shortLivedAuth";
}
}
defaultConfiguration.auth.shortLivedAuth.setValidAccessToken('token');
Parse.User._registerAuthenticationProvider(provider);
Parse.User._logInWith("shortLivedAuth", {}).then(() => {
// Simulate a remotely expired token (like a short lived one)
// In this case, we want success as it was valid once.
// If the client needs an updated one, do lock the user out
defaultConfiguration.auth.shortLivedAuth.setValidAccessToken('otherToken');
return rp.put({
url: Parse.serverURL + '/users/' + Parse.User.current().id,
headers: {
'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-Javascript-Key': Parse.javaScriptKey,
'X-Parse-Session-Token': Parse.User.current().getSessionToken(),
'Content-Type': 'application/json'
},
json: {
key: 'value', // update a key
authData: { // pass the original auth data
shortLivedAuth: {
id: '12345',
access_token: 'token'
}
}
}
})
}).then(() => {
done();
}, (err) => {
done.fail(err);
});
});

it('should properly error when password is missing', (done) => {
var provider = getMockFacebookProvider();
Parse.User._registerAuthenticationProvider(provider);
Expand Down
28 changes: 17 additions & 11 deletions src/RestWrite.js
Original file line number Diff line number Diff line change
Expand Up @@ -288,30 +288,32 @@ RestWrite.prototype.handleAuthData = function(authData) {
this.storage['authProvider'] = Object.keys(authData).join(',');

if (results.length > 0) {
const userResult = results[0];
const mutatedAuthData = {};
Object.keys(authData).forEach((provider) => {
const providerData = authData[provider];
const userAuthData = userResult.authData[provider];
if (!_.isEqual(providerData, userAuthData)) {
mutatedAuthData[provider] = providerData;
}
});
const hasMutatedAuthData = Object.keys(mutatedAuthData).length !== 0;
if (!this.query) {
// Login with auth data
delete results[0].password;
const userResult = results[0];

// need to set the objectId first otherwise location has trailing undefined
this.data.objectId = userResult.objectId;

// Determine if authData was updated
const mutatedAuthData = {};
Object.keys(authData).forEach((provider) => {
const providerData = authData[provider];
const userAuthData = userResult.authData[provider];
if (!_.isEqual(providerData, userAuthData)) {
mutatedAuthData[provider] = providerData;
}
});

this.response = {
response: userResult,
location: this.location()
};

// If we didn't change the auth data, just keep going
if (Object.keys(mutatedAuthData).length === 0) {
if (!hasMutatedAuthData) {
return;
}
// We have authData that is updated on login
Expand All @@ -330,10 +332,14 @@ RestWrite.prototype.handleAuthData = function(authData) {
} else if (this.query && this.query.objectId) {
// Trying to update auth data but users
// are different
if (results[0].objectId !== this.query.objectId) {
if (userResult.objectId !== this.query.objectId) {
throw new Parse.Error(Parse.Error.ACCOUNT_ALREADY_LINKED,
'this auth is already used');
}
// No auth data was mutated, just keep going
if (!hasMutatedAuthData) {
return;
}
}
}
return this.handleAuthDataValidation(authData);
Expand Down