9.2 KiB
The OAuth Authentication Nightmare: Why I'm Considering Moving from Appwrite to Supabase
A developer's journey through mobile OAuth hell and the quest for better solutions
The Problem That Started It All
I was building TaskTracker, a Flutter mobile application, and decided to use Appwrite as my Backend-as-a-Service (BaaS). Everything seemed promising - great documentation, modern API, and OAuth support out of the box. What could go wrong?
Everything.
After successfully implementing email/password authentication, I moved on to Google OAuth for a better user experience. The implementation seemed straightforward - just call createOAuth2Session() and you're done, right?
Wrong.
The Mysterious ImeTracker Error
After clicking the Google OAuth button, Chrome Custom Tabs would open (not the native Android Google Sign-In UI, which was my first red flag). I'd select my Google account, authenticate successfully, and then... nothing. The browser would close, and I'd see this cryptic error in the logs:
I/ImeTracker( 5434): com.Xperience.TaskTracker.tasktracker:efd1ad6a:
onCancelled at PHASE_CLIENT_ALREADY_HIDDEN
The error message suggested I had cancelled the authentication, but I hadn't touched anything. The OAuth flow was completing on Google's end, but my app wasn't receiving the callback properly.
The Troubleshooting Marathon
Attempt #1: Explicit Callback URLs
My first thought was that the callback URLs needed to be explicitly defined. I tried specifying success and failure URLs:
await widget.account.createOAuth2Session(
provider: provider,
success: 'appwrite-callback-tasktracker://success',
failure: 'appwrite-callback-tasktracker://failure',
scopes: ['email', 'profile'],
);
Result: Even worse. I got a new error:
Invalid success param, URL host must be one of localhost, supab.playpoolstudios.com
So Appwrite's server was rejecting my custom URL scheme entirely. This made no sense for a mobile application where custom URL schemes are the standard for OAuth callbacks.
Attempt #2: Android Manifest Configuration
Maybe the issue was with my Android configuration? I updated the AndroidManifest.xml to be more explicit about handling OAuth callbacks:
<intent-filter android:label="flutter_web_auth_2" android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="appwrite-callback-tasktracker" android:host="success" />
<data android:scheme="appwrite-callback-tasktracker" android:host="failure" />
</intent-filter>
Result: Still nothing. The callback wasn't being intercepted properly.
Attempt #3: Appwrite Console Platform Configuration
Perhaps I needed to register my Android app as a platform in the Appwrite Console? I went through the process:
- Added Android platform
- Entered package name:
com.Xperience.TaskTracker.tasktracker - Configured OAuth provider settings
Result: No improvement. The OAuth flow still failed silently.
Attempt #4: The GitHub Workaround
After hours of searching, I found a GitHub issue with a workaround suggesting a two-step OAuth process:
// Step 1: Manually trigger OAuth with flutter_web_auth_2
final result = await FlutterWebAuth2.authenticate(
url: '$endpoint/account/sessions/oauth2/$provider?project=$projectId',
callbackUrlScheme: 'appwrite-callback-$projectId',
);
// Step 2: Create Appwrite session
await widget.account.createOAuth2Session(provider: provider);
This workaround essentially bypasses Appwrite's OAuth handling by manually triggering the web authentication, then trying to create a session afterward.
Result: Still testing, but the fact that such a workaround exists is telling.
The Fundamental Issues
After all this troubleshooting, I've identified several core problems with Appwrite's mobile OAuth implementation:
1. Poor Mobile-First Design
Appwrite's OAuth is clearly designed for web applications. The restriction that callback URLs must use the server's domain (supab.playpoolstudios.com) makes no sense for mobile apps that need custom URL schemes like appwrite-callback-*://.
2. Chrome Custom Tabs Instead of Native UI
On Android, the OAuth flow opens Chrome Custom Tabs instead of the native Google Sign-In UI. This creates a clunky user experience and introduces unnecessary complexity with session management between the browser and the app.
3. Silent Failures
The OAuth process fails silently with no meaningful error messages. The ImeTracker error is just a symptom - a side effect of the keyboard state when the browser closes - not the actual problem.
4. Lack of Documentation
The official Appwrite documentation doesn't cover mobile OAuth edge cases, troubleshooting steps, or known issues. I had to dig through GitHub issues to find any information.
5. Workarounds Required
The fact that a two-step workaround exists (and is recommended in GitHub issues) suggests this is a known problem that hasn't been properly fixed.
Why I'm Looking at Supabase
After spending hours (days?) on this issue, I started researching alternatives. Supabase keeps coming up, and here's why it's appealing:
1. PostgreSQL Foundation
Supabase is built on PostgreSQL, a mature, battle-tested database. This means:
- Better query capabilities
- Mature ecosystem
- Reliable data integrity
- Easy migration path if needed
2. Better OAuth Documentation
Supabase has extensive documentation for mobile OAuth, including Flutter-specific guides and examples. They support:
- Deep linking configuration
- Platform-specific setup guides
- Native SDK implementations
- Working code examples
3. Active Community Support
The Supabase community is larger and more active. Issues get addressed faster, and there are more third-party tutorials and resources available.
4. Row Level Security (RLS)
Supabase's RLS is more powerful and flexible than Appwrite's permissions system, giving you fine-grained control over data access at the database level.
5. Edge Functions with Deno
Supabase Edge Functions run on Deno, which is modern, secure, and has better TypeScript support than Appwrite's functions.
6. Transparent Pricing
Supabase has clearer pricing and a more generous free tier for development and testing.
The Verdict
I wanted to love Appwrite. The API is clean, the dashboard is beautiful, and the promise of an open-source Firebase alternative is compelling. But when basic functionality like mobile OAuth doesn't work reliably, it becomes a blocker for production applications.
The problems I encountered are not edge cases - mobile OAuth is a fundamental feature for modern apps. The fact that it requires workarounds and extensive troubleshooting suggests that Appwrite isn't ready for serious mobile development.
What Appwrite Needs to Fix:
- Native mobile OAuth support with proper deep linking
- Better error messages that actually help developers diagnose issues
- Comprehensive mobile documentation with troubleshooting guides
- Native SDK improvements for mobile platforms
- Faster issue resolution and community support
The Supabase Migration Plan:
If I decide to switch (which I'm seriously considering), the migration would involve:
- Data Migration: Export data from Appwrite, transform to PostgreSQL format
- Auth Migration: Implement Supabase Auth with Flutter
- Real-time Features: Switch to Supabase's real-time subscriptions
- File Storage: Migrate to Supabase Storage
- Functions: Rewrite cloud functions as Supabase Edge Functions
Is it worth the effort? Given the time I've already wasted on OAuth alone, probably yes.
Conclusion
Appwrite has potential, but it's not production-ready for mobile applications that require OAuth authentication. The lack of proper mobile support, combined with silent failures and poor documentation, makes it a risky choice for serious projects.
Supabase, while not perfect, offers a more mature and mobile-friendly solution with better documentation, active community support, and proven reliability.
For fellow developers considering their BaaS options: test your critical features early. Don't commit to a platform until you've verified that core functionality like authentication actually works for your use case.
As for me, I'll probably start a Supabase proof-of-concept this weekend. If it goes well, TaskTracker will be migrating sooner rather than later.
Update
If you're experiencing similar issues with Appwrite OAuth, here are some resources that might help:
- Appwrite GitHub Issues - Search for mobile OAuth problems
- Supabase Flutter Documentation
- Flutter Web Auth 2 Package - The underlying package Appwrite uses
Have you experienced similar issues? Share your experience in the comments. Are you using Appwrite or Supabase? What has your experience been?
Written by a frustrated developer who just wants OAuth to work
Date: October 13, 2025