-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
fix(auth): Treat authData[provider]=null as unlink; skip provider validation for unlink #9856
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
base: alpha
Are you sure you want to change the base?
Changes from all commits
7669bd9
7db1f8e
2979264
4e3ac64
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
describe('RestWrite.handleAuthData', () => { | ||
const MOCK_USER_ID = 'mockUserId'; | ||
const MOCK_ACCESS_TOKEN = 'mockAccessToken123'; | ||
|
||
const createMockUser = () => ({ | ||
id: MOCK_USER_ID, | ||
code: 'C1', | ||
}); | ||
|
||
const mockGooglePlayGamesAPI = () => { | ||
mockFetch([ | ||
{ | ||
url: 'https://oauth2.googleapis.com/token', | ||
method: 'POST', | ||
response: { | ||
ok: true, | ||
json: () => Promise.resolve({ access_token: MOCK_ACCESS_TOKEN }), | ||
}, | ||
}, | ||
{ | ||
url: `https://www.googleapis.com/games/v1/players/${MOCK_USER_ID}`, | ||
method: 'GET', | ||
response: { | ||
ok: true, | ||
json: () => Promise.resolve({ playerId: MOCK_USER_ID }), | ||
}, | ||
}, | ||
]); | ||
}; | ||
|
||
const setupAuthConfig = () => { | ||
return reconfigureServer({ | ||
auth: { | ||
gpgames: { | ||
clientId: 'validClientId', | ||
clientSecret: 'validClientSecret', | ||
} | ||
}, | ||
}); | ||
}; | ||
|
||
beforeEach(async () => { | ||
await setupAuthConfig(); | ||
}); | ||
|
||
it('should unlink provider via null', async () => { | ||
mockGooglePlayGamesAPI(); | ||
|
||
const authData = createMockUser(); | ||
const user = await Parse.User.logInWith('gpgames', { authData }); | ||
const sessionToken = user.getSessionToken(); | ||
|
||
await user.fetch({ sessionToken }); | ||
const currentAuthData = user.get('authData') || {}; | ||
|
||
user.set('authData', { | ||
...currentAuthData, | ||
gpgames: null, | ||
}); | ||
await user.save(null, { sessionToken }); | ||
|
||
const updatedUser = await new Parse.Query(Parse.User).get(user.id, { useMasterKey: true }); | ||
const finalAuthData = updatedUser.get('authData') || {}; | ||
|
||
expect(finalAuthData.gpgames).toBeUndefined(); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -538,7 +538,15 @@ RestWrite.prototype.ensureUniqueAuthDataId = async function () { | |
}; | ||
|
||
RestWrite.prototype.handleAuthData = async function (authData) { | ||
const r = await Auth.findUsersWithAuthData(this.config, authData, true); | ||
const withoutUnlinked = {}; | ||
for (const provider of Object.keys(authData)) { | ||
if (authData[provider] === null || authData[provider] === undefined) { | ||
continue; | ||
} | ||
withoutUnlinked[provider] = authData[provider]; | ||
} | ||
Comment on lines
+542
to
+547
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nitpick: using dedicated tools and functional prog to perform ops on objects, may be you will learn something const authDataWithoutNullish = Object.fromEntries(Object.entries(authData).filter([_, data] => data ?? false)) When you want to perform filtering on objects, combining Object.fromEntries + Object.entries + .filter() works well (in case of functional programming) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Object.fromEntries combined with Object.entries is underrated: https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries |
||
|
||
const r = await Auth.findUsersWithAuthData(this.config, withoutUnlinked, true); | ||
const results = this.filteredObjectsByACL(r); | ||
|
||
const userId = this.getUserId(); | ||
|
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue: You should not fall back to "{}". In this test, you expect to receive authData. Otherwise, if authData becomes protected in the future, the test could produce false positives.
Additionally, you need to set another authData in this test to ensure that: