You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
AuthData validation is incorrectly triggered on unlink/no-op updates, breaking multi-provider flows #9999
Parse Server validates all existing authData providers during user updates, even when a provider is unchanged and not part of the update.
For code-based auth adapters (requiring code), this causes valid multi-provider update flows to fail, because Parse attempts to revalidate providers that were not modified and therefore do not include a code in the update payload.
This makes partial authData updates non-functional and breaks multi-provider user accounts.
Steps to reproduce
Using any code-based auth adapter (example below uses a gpgames-like adapter that requires code):
it('should handle multiple providers: add one while another remains unchanged',async()=>{constuser=awaitParse.User.logInWith('gpgames',{authData: {id: MOCK_USER_ID,code: 'C1'},});constsessionToken=user.getSessionToken();awaituser.fetch({ sessionToken });constcurrent=user.get('authData')||{};user.set('authData',{
...current,instagram: {id: 'I1',code: 'ic1'},// gpgames is NOT modified});awaituser.save(null,{ sessionToken });constreloaded=awaitnewParse.Query(Parse.User).get(user.id,{useMasterKey: true,});constauthData=reloaded.get('authData')||{};expect(authData.instagram&&authData.instagram.id).toBe('I1');expect(authData.gpgames&&authData.gpgames.id).toBe(MOCK_USER_ID);});
Actual Outcome
user.save() fails with an adapter validation error, for example:
Error: gpgames code is required.
This shows that Parse attempts to validate the existing gpgames provider even though it was not modified and no code was provided in the update.
Expected Outcome
The new provider (instagram) is added successfully.
The existing provider (gpgames) remains unchanged.
Adapter validation is triggered only for providers whose authData was actually modified.
Environment
Server
Parse Server version: 9.1.0
Operating system: Debian 12
Local or remote host: Remote (self-hosted)
Database
System: MongoDB
Database version: 8.1
Local or remote host: MongoDB Atlas
Logs
Error: gpgames code is required.
at validateAuthData (...)
ℹ️ You can help us to fix this issue faster by opening a pull request with a failing test. See our Contribution Guide for how to make a pull request, or read our New Contributor's Guide if this is your first time contributing.
We're experiencing a related issue with the Flutter SDK (parse_server_sdk_flutter).
When a user deletes their account, the Flutter app calls user.unset("authData") which stores {"authData": {"__op": "Delete"}} in the local sembast storage.
If the user later tries to re-register with Google/Apple auth, the SDK sends:
Parse Server then iterates over all keys in authData and treats __op as an auth provider, resulting in:
Error 252: "This authentication method is unsupported." provider: "__op"
This started happening after upgrading from parse_server_sdk_flutter 8.0.0 to 10.6.2. The unset() operation has always stored the __op locally, but something changed in how the SDK serializes/merges local data with new auth data.
Workaround: We added an Express middleware to strip __op from authData before it reaches Parse Server:
Activity
parse-github-assistant commentedon Dec 30, 2025
🚀 Thanks for opening this issue!
ℹ️ You can help us to fix this issue faster by opening a pull request with a failing test. See our Contribution Guide for how to make a pull request, or read our New Contributor's Guide if this is your first time contributing.
pcg92 commentedon Jan 26, 2026
We're experiencing a related issue with the Flutter SDK (
parse_server_sdk_flutter).When a user deletes their account, the Flutter app calls
user.unset("authData")which stores{"authData": {"__op": "Delete"}}in the local sembast storage.If the user later tries to re-register with Google/Apple auth, the SDK sends:
{ "authData": { "google": { "id": "...", "access_token": "...", "id_token": "..." }, "__op": "Delete" } }Parse Server then iterates over all keys in
authDataand treats__opas an auth provider, resulting in:This started happening after upgrading from
parse_server_sdk_flutter 8.0.0to10.6.2. Theunset()operation has always stored the__oplocally, but something changed in how the SDK serializes/merges local data with new auth data.Workaround: We added an Express middleware to strip
__opfromauthDatabefore it reaches Parse Server:This confirms the root cause is the same: Parse Server validates all keys in
authDataas providers, even when they shouldn't be treated as such.mtrezza commentedon Jan 27, 2026
Could you please try out #10025 and see whether it fixes the issue?