Skip to content

Unable to handle exception for expired/invalid signup link #1065

Open
@percarlsen

Description

@percarlsen

Describe the bug
I've run into a problem related to invalid/expired confirmation links when signing up with email. The (relevant part of the) expired link looks as follows: com.example:///email-signup?error=access_denied&error_code=4&error_description=Email+link+is+invalid+or+has+expired#<...>. I was planning on handling this by checking the error_code query parameter in my app, and giving an appropriate message to the user. The issue, however, is that the deeplink navigation triggers supabase to call GoTrueClient.getSessionFromUrl, which raises an exception. So it never makes its way to the router. I've not been able to neither catch nor disable this exception, meaning that the app crashes whenever a user presses an expired link. I've tried the following without success:

  • Use the onException callback in my GoRouter, but this doesn't seem to be triggered.
  • Initialize supabase with client option setting detectSessionInUri = false.
  • I have a try-catch around the supabase.auth.signUp call, but this doesn't matter because the exception is raised when the link is clicked, not when signUp is called.
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: AuthException(message: Email link is invalid or has expired, statusCode: 403, errorCode: access_denied)
#0      GoTrueClient.getSessionFromUrl (package:gotrue/src/gotrue_client.dart:780:7)
gotrue_client.dart:780
#1      SupabaseAuth._handleDeeplink (package:supabase_flutter/src/supabase_auth.dart:295:43)
supabase_auth.dart:295
#2      SupabaseAuth._handleIncomingLinks.<anonymous closure> (package:supabase_flutter/src/supabase_auth.dart:235:13)
supabase_auth.dart:235
#3      _RootZone.runUnaryGuarded (dart:async/zone.dart:1594:10)
zone.dart:1594
#4      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:365:11)
stream_impl.dart:365
#5      _DelayedData.perform (dart:async/stream_impl.dart:541:14)
stream_impl.dart:541
#6      _PendingEvents.handleNext (dart:async/stream_impl.dart:646:11)
stream_impl.dart:646
#7      _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:617:7)
stream_impl.dart:617
#8      _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
schedule_microtask.dart:40
#9      _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)

To Reproduce
Steps to reproduce the behavior:

  1. Setup a flutter app with supabase_flutter, email+password authentication and GoRouter (though I don't think the last one is necessary)
  2. Set up deep link navigation from the confirmation email link
  3. Sign up, wait for the link to expire, and click it. (Alternatively, resend a new link and then click the old link).

Expected behavior
Clicking the expired link should navigate to that link and not raise an exception. (Alternatively; make it possible to catch that exception.)

Screenshots
NA

Version (please complete the following information):
On Linux/macOS

├── supabase_flutter 2.8.0
│   ├── supabase 2.5.0
│   │   ├── functions_client 2.4.0
│   │   ├── gotrue 2.10.0
│   │   ├── postgrest 2.3.0
│   │   ├── realtime_client 2.4.0
│   │   ├── storage_client 2.2.0

On Windows
NA

Additional context
Deep linking and navigation in this particular app in general works fine, so I'm confident this has nothing to do with the general routing setup.

Metadata

Metadata

Assignees

No one assigned

    Labels

    authThis issue or pull request is related to authenticationbugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions