Skip to content

fix: support = delimiter in GOTRUE_SMS_TEST_OTP env var#2529

Open
Reckz69 wants to merge 3 commits into
supabase:masterfrom
Reckz69:fix/test-otp-equals-delimiter
Open

fix: support = delimiter in GOTRUE_SMS_TEST_OTP env var#2529
Reckz69 wants to merge 3 commits into
supabase:masterfrom
Reckz69:fix/test-otp-equals-delimiter

Conversation

@Reckz69
Copy link
Copy Markdown

@Reckz69 Reckz69 commented May 14, 2026

Fix GOTRUE_SMS_TEST_OTP parsing for equals-delimited values

Fixes supabase/supabase#45832

Summary

Fixes an issue where GOTRUE_SMS_TEST_OTP fails to parse when values use = as the key-value delimiter (e.g. phone=otp), which is the format injected by the hosted Supabase platform.

This caused Auth startup failures when SMS test OTPs were configured in hosted environments.


Root Cause

The project currently relies on kelseyhightower/envconfig's default map decoder for parsing GOTRUE_SMS_TEST_OTP.

The default decoder only supports colon-delimited entries:

phone:otp

When the hosted platform injects:

GOTRUE_SMS_TEST_OTP=12125550124=000000

envconfig fails during startup with:

converting '12125550124=000000' to type map[string]string.
details: invalid map item: "12125550124=000000"

Solution

Introduced a custom TestOTPMap type implementing the envconfig.Decoder interface, following the same decoder pattern already used elsewhere in the codebase (JwtKeysDecoder, Rate, HTTPHookSecrets, etc.).

The new decoder supports all of the following formats:

JSON object

{"phone":"otp"}

Colon-delimited (backward compatible)

phone:otp

Equals-delimited (hosted platform compatible)

phone=otp

This preserves backward compatibility while adding support for the hosted platform injection format.


Changes

File Change
internal/conf/configuration.go Added TestOTPMap with custom Decode() implementation and updated TestOTP field type
internal/conf/configuration_test.go Added comprehensive decoder test coverage
internal/api/phone_test.go Updated TestOTP field type
internal/api/anonymous_test.go Updated TestOTP field type

Testing

Unit Tests

Added coverage for:

  • JSON decoding
  • Colon-delimited parsing
  • Equals-delimited parsing
  • Multiple entries
  • Mixed formats
  • Empty input
  • Invalid input handling

All tests passing:

=== RUN   TestMethods/DecodeJSON            --- PASS
=== RUN   TestMethods/DecodeColonDelimited  --- PASS
=== RUN   TestMethods/DecodeEqualsDelimited --- PASS
=== RUN   TestMethods/DecodeMultipleEntries --- PASS
=== RUN   TestMethods/DecodeMixedFormats    --- PASS
=== RUN   TestMethods/DecodeEmptyString     --- PASS
=== RUN   TestMethods/DecodeInvalidFormat   --- PASS

End-to-End Validation

Validated against the real Auth flow using a Postgres-backed test environment:

GOTRUE_SMS_TEST_OTP="12125550124=000000" go test ./internal/api/ -run TestPhone -v

Result:

--- PASS: TestPhone (0.15s)
    --- PASS: TestPhone/TestSendPhoneConfirmationWithTestOTP
        --- PASS: send_confirmation_otp
        --- PASS: send_phone_change_otp
        --- PASS: send_recovery_otp

CI / Quality Checks

  • gofmt
  • go vet
  • go build ./...
  • staticcheck
  • gosec
  • govulncheck

@Reckz69 Reckz69 requested a review from a team as a code owner May 14, 2026 12:13
Comment thread internal/conf/configuration.go Outdated
Co-authored-by: depthfirst-app[bot] <184448029+depthfirst-app[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SMS test OTP not honored with Twilio Verify provider

1 participant