Bug report
Describe the bug
Supabase hosted Auth appears to ignore configured SMS test OTP entries when Phone Auth is configured with sms_provider = twilio_verify.
The test OTP entry is visible through the Supabase Management API but /auth/v1/otp does not appear to use the test OTP path, and /auth/v1/verify rejects the configured test code with otp_expired.
This reproduces with raw Supabase Auth REST calls, outside our React Native app and outside supabase-js.
Auth config summary from Management API:
sms_provider: twilio_verify
phone_enabled: true
phone_autoconfirm: true
sms_test_otp_valid_until: 2027-06-30...
sms_test_otp contains: <phone digits without leading +>=000000
Example format:
But verifying 000000 fails with:
{
"error_code": "otp_expired",
"msg": "Token has expired or is invalid"
}
To Reproduce
-
In a hosted Supabase project, enable Phone Auth.
-
Configure SMS provider as Twilio Verify.
-
Add a test OTP entry in the dashboard:
The dashboard requires E.164 without the leading +.
-
Set sms_test_otp_valid_until to a future date.
-
Confirm via Management API that the config exists and is not expired.
-
Request an OTP:
curl -X POST "https://<project-ref>.supabase.co/auth/v1/otp" \
-H "apikey: <publishable-or-anon-key>" \
-H "Authorization: Bearer <publishable-or-anon-key>" \
-H "Content-Type: application/json" \
-d '{"phone":"+12125550124","create_user":false}'
-
Verify using the configured test OTP:
curl -X POST "https://<project-ref>.supabase.co/auth/v1/verify" \
-H "apikey: <publishable-or-anon-key>" \
-H "Authorization: Bearer <publishable-or-anon-key>" \
-H "Content-Type: application/json" \
-d '{"phone":"+12125550124","token":"000000","type":"sms"}'
-
Observe that verification fails with 403 otp_expired.
We also tested phone: "12125550124" without the leading +; it fails the same way.
Expected behavior
Supabase should match the incoming phone number +12125550124 to the configured test OTP entry 12125550124=000000, bypass Twilio Verify, and return a valid Auth session.
The OTP request should appear to use the test OTP path. Based on observed/test behavior, I expected /auth/v1/otp to return something like:
Screenshots
Can provide privately if useful.
System information
- OS: macOS 26.4.1
- Browser: Chrome
- Version of supabase-js: app uses
@supabase/supabase-js ^2.90.1
- Version of Node.js:
v24.11.1
Additional context
None.
Extra checks performed:
- Direct REST reproduction rules out React Native/app code.
- The app uses normal Supabase phone OTP APIs:
signInWithOtp({ phone, options: { shouldCreateUser } })
verifyOtp({ phone, token, type: "sms" })
- Management API confirms the test OTP entry exists and has not expired.
- A no-op Management API PATCH on staging re-saving the same
sms_test_otp and sms_test_otp_valid_until succeeded but did not fix runtime behavior.
- Trying
: as the delimiter was rejected by Supabase validation. The API/dashboard requires <phone-number>=<code> and “E.164 without the leading + sign”.
/auth/v1/otp returned message_id: null, not message_id: "test-otp", which suggests hosted Auth is not applying the test OTP path at send time either.
Bug report
Describe the bug
Supabase hosted Auth appears to ignore configured SMS test OTP entries when Phone Auth is configured with
sms_provider = twilio_verify.The test OTP entry is visible through the Supabase Management API but
/auth/v1/otpdoes not appear to use the test OTP path, and/auth/v1/verifyrejects the configured test code withotp_expired.This reproduces with raw Supabase Auth REST calls, outside our React Native app and outside
supabase-js.Auth config summary from Management API:
Example format:
But verifying
000000fails with:{ "error_code": "otp_expired", "msg": "Token has expired or is invalid" }To Reproduce
In a hosted Supabase project, enable Phone Auth.
Configure SMS provider as Twilio Verify.
Add a test OTP entry in the dashboard:
The dashboard requires E.164 without the leading
+.Set
sms_test_otp_valid_untilto a future date.Confirm via Management API that the config exists and is not expired.
Request an OTP:
Verify using the configured test OTP:
Observe that verification fails with
403 otp_expired.We also tested
phone: "12125550124"without the leading+; it fails the same way.Expected behavior
Supabase should match the incoming phone number
+12125550124to the configured test OTP entry12125550124=000000, bypass Twilio Verify, and return a valid Auth session.The OTP request should appear to use the test OTP path. Based on observed/test behavior, I expected
/auth/v1/otpto return something like:Screenshots
Can provide privately if useful.
System information
@supabase/supabase-js^2.90.1v24.11.1Additional context
None.
Extra checks performed:
signInWithOtp({ phone, options: { shouldCreateUser } })verifyOtp({ phone, token, type: "sms" })sms_test_otpandsms_test_otp_valid_untilsucceeded but did not fix runtime behavior.:as the delimiter was rejected by Supabase validation. The API/dashboard requires<phone-number>=<code>and “E.164 without the leading + sign”./auth/v1/otpreturnedmessage_id: null, notmessage_id: "test-otp", which suggests hosted Auth is not applying the test OTP path at send time either.