S
Supabase•3y ago
xzilja

Issues setting up OTP code signin and signup flows

I'm trying to create a user flow where an OTP code is sent to users email and then verified to sign them in. Following supabases documentation I am doing following 1. I changed from using link in "Magic Link" email template to {{ .Token }} 2. I tried using both type: 'magiclink' and type: 'signup' in code below 3. My email provider settings are set to 60000 for expiry seconds and 6 for password length. Email confirmation is set to be enabled. Implementation is as follows
const { data, error } = await supabaseClient.auth.signInWithOtp({ email })
// {"data": {"session": null, "user": null}, "error": null}

const { data, error } = await supabaseClient.auth.verifyOtp({ email, token, type: 'signup' })
// {"data": {"session": null, "user": null}, "error": [AuthApiError: Token has expired or is invalid]}
const { data, error } = await supabaseClient.auth.signInWithOtp({ email })
// {"data": {"session": null, "user": null}, "error": null}

const { data, error } = await supabaseClient.auth.verifyOtp({ email, token, type: 'signup' })
// {"data": {"session": null, "user": null}, "error": [AuthApiError: Token has expired or is invalid]}
I double verified that token I am sending is exact one as I got in email, yet I keep getting that auth error.
23 Replies
garyaustin
garyaustin•3y ago
You probaly want to use 'magiclink' for signInWithOtp(), not 'signup' which is for signUp()
xzilja
xziljaOP•3y ago
Yeh, I mentioned that above, both types are returning this error right now
garyaustin
garyaustin•3y ago
Sorry, missed the magiclink comment. But it for sure is not signup. hmmm
xzilja
xziljaOP•3y ago
I'm working on a small example to re-create this
garyaustin
garyaustin•3y ago
Are you passing the code as a string or a number? My working code...
const {data, error} = await supabase.auth.verifyOtp({
email: email,
token: confirmValue.trim(),
type: 'magiclink'
})
....
const { data, error } = await supabase.auth.signInWithOtp({
email:email
}
)
const {data, error} = await supabase.auth.verifyOtp({
email: email,
token: confirmValue.trim(),
type: 'magiclink'
})
....
const { data, error } = await supabase.auth.signInWithOtp({
email:email
}
)
xzilja
xziljaOP•3y ago
I just got this working in codesandbox https://codesandbox.io/s/supabase-otp-example-kx3ru2 So I assume there is an issue in react-native (where I originally saw this error). It's exact same code with only difference being how supabase client is created
import AsyncStorage from '@react-native-async-storage/async-storage'
import { createClient } from '@supabase/supabase-js'
import { setupURLPolyfill } from 'react-native-url-polyfill'
import { ConstantsUtil } from './ConstantsUtil'

setupURLPolyfill()

export const SupabaseUtil = createClient(
ConstantsUtil.SUPABASE_URL,
ConstantsUtil.SUPABASE_API_KEY,
{
auth: {
autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: false,
storage: AsyncStorage
}
}
)
import AsyncStorage from '@react-native-async-storage/async-storage'
import { createClient } from '@supabase/supabase-js'
import { setupURLPolyfill } from 'react-native-url-polyfill'
import { ConstantsUtil } from './ConstantsUtil'

setupURLPolyfill()

export const SupabaseUtil = createClient(
ConstantsUtil.SUPABASE_URL,
ConstantsUtil.SUPABASE_API_KEY,
{
auth: {
autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: false,
storage: AsyncStorage
}
}
)
I guess this could be a bug in latest rc?
garyaustin
garyaustin•3y ago
I'm on latest RC. (or at least as of a week ago), but not RN.
xzilja
xziljaOP•3y ago
As for
Are you passing the code as a string or a number?
yeh, passing it in the same way as string
garyaustin
garyaustin•3y ago
RC10 is fine.
xzilja
xziljaOP•3y ago
Yeh, thats the one I'm on. It looks like verifyOtp fails even before making a network request. Need to dig in there and see what could be causing this rn specific error Any chance you know where to look for this big in supabases github?
garyaustin
garyaustin•3y ago
GitHub
gotrue-js/GoTrueClient.ts at a15296288d15919d2ec8a64654a545a375fb3a...
An isomorphic Javascript library for GoTrue. Contribute to supabase/gotrue-js development by creating an account on GitHub.
xzilja
xziljaOP•3y ago
I think the only diff / request param that could be causing the error is that xform: _sessionResponse,
garyaustin
garyaustin•3y ago
I assume you are generating a new confirmation email every once in awhile in this testing process.
garyaustin
garyaustin•3y ago
The error comes from here: https://github.com/supabase/gotrue/blob/master/api/verify.go#L541 And should be for bad code or expired. I sort of thought they might also invalidate the code if used "badly" but at quick glance don't see it.
GitHub
gotrue/verify.go at master · supabase/gotrue
A JWT based API for managing users and issuing JWT tokens - gotrue/verify.go at master · supabase/gotrue
Thomas
Thomas•3y ago
Not sure if I'm having the same issue as this, but I'm always getting Invalid login credentials when trying to log in with OTP sent to email. Could it be related? Also on RC. I had it working with magic links prior, and it also works with password
const { data, error } = await supabase.auth.verifyOtp({ email, token, type: "magiclink", });
const { data, error } = await supabase.auth.verifyOtp({ email, token, type: "magiclink", });
garyaustin
garyaustin•3y ago
You have to make sure you use right type for each code/token. https://supabase.com/docs/reference/javascript/next/auth-verifyotp
verifyOtp() | Supabase
Log in a user given a User supplied OTP received via mobile.
Thomas
Thomas•3y ago
I've tried all the types As this is a sign in via email I believe magiclink is the right one anyway, no? I'm triggering the OTP email with const { error } = await supabase.auth.signInWithOtp({ email });
garyaustin
garyaustin•3y ago
Yes magiclink for that.
Thomas
Thomas•3y ago
Actually, the network request goes to /auth/v1/token?grant_type=password
garyaustin
garyaustin•3y ago
hmmmm
Thomas
Thomas•3y ago
Is that expected? Maybe I have some error in my app logic So it's actually trying to log in with signInWithPassword instead Doh, that was it. Thanks for your help!
garyaustin
garyaustin•3y ago
async signInWithOtp(credentials: SignInWithPasswordlessCredentials): Promise<AuthResponse> {
try {
await this._removeSession()

if ('email' in credentials) {
const { email, options } = credentials
const { error } = await _request(this.fetch, 'POST', `${this.url}/otp`, {
async signInWithOtp(credentials: SignInWithPasswordlessCredentials): Promise<AuthResponse> {
try {
await this._removeSession()

if ('email' in credentials) {
const { email, options } = credentials
const { error } = await _request(this.fetch, 'POST', `${this.url}/otp`, {
from gotrue-js v2 /otp should be the url.
Thomas
Thomas•3y ago
Got it working now, just had an issue with an if statement (I have an optional password field in the sign-in form) that got triggered despite the password state being empty. I'm very new to Next/React as you might tell 😅 Sorry for hijacking your thread Aztec

Did you find this page helpful?