Setting emailRedirectTo should set {{ .SiteURL }} in email template when using signInWithOtp
Bug report
Describe the bug
Assuming the Redirect URLs have properly been configured in Supabase configuration settings, when the emailRedirectTo parameter is specified, that URL should be represented in the email template via {{ .SiteURL }}
To Reproduce
Steps to reproduce the behavior, please provide code snippets or a repository:
- Make sure relevant URLs are correctly added to Supabase's
Redirect URLslist - Send a
signInWithOtpwith theemailRedirectToas an option. Example:
supabase.auth.signInWithOtp({
email: email,
options: {
emailRedirectTo: 'http://localhost:5173',
},
});
Expected behavior
The value of {{ .SiteURL }} should match the value passed via emailRedirectTo. Instead, the default Site URL (as defined in the Supabase configuration) is set.
Additional context
- When authenticating via OAUTH, and defining
redirectTo, the{{ .SiteURL }}value is properly overridden. However, thesignInWithOtprequires aemailRedirectTooption and this option does not override{{ .SiteURL }}. - The
{{ .ConfirmationURL }}value is properly updated when settingemailRedirectTo. However,{{ .SiteURL }}should also be set accordingly.
emailRedirectTo should override {{ .SiteURL }} as that is what is expected and is necessary to have properly functioning email templates across different environments.
I made a turn around by create an edge function to do the redirection. It is inspired by MS Defender safe link auth-email-templates#email-prefetching.
Deno.serve(async (req: Request) => {
if (req.method !== 'GET') {
return new Response({}, { status: 405 });
}
try {
const origin = new URL(req.url);
const confirmationUrl = new URL(origin.searchParams.get('confirmation_url'));
const redirectUrl = new URL(confirmationUrl.searchParams.get('redirect_to'));
redirectUrl.searchParams.set('token_hash', confirmationUrl.searchParams.get('token'));
redirectUrl.searchParams.set('type', confirmationUrl.searchParams.get('type'));
return Response.redirect(redirectUrl.toString(), 301);
} catch (err) {
return new Response({ error: err }, { status: 500 });
}
});
After deploying this function you'll get an Endpoint URL and set SiteURL with the Endpoint URL. Also modify email template to pass the {{ .ConfirmationURL }} as query parameters confirmation_url as stated in auth-email-templates#email-prefetching. Here is an example for the email templates:
<h2>Magic Link</h2>
<p>Follow this link to login:</p>
<p><a href="{{ .SiteURL }}?confirmation_url={{ .ConfirmationURL }}">Log In</a></p>
I also ran into a similar issue, but I don't think the fix should be to override {{ .SiteURL }} as a redirect URL is not related to the Site URL.
Instead, the root cause is the fact {{ .RedirectURL }} does not appear to work in the email templates, although the docs state it should be supported for signInWithOtp.
The redirect URLs are configured correctly because I can see the parameter in the {{ .ConfirmationURL }}.
https://supabase.com/docs/guides/auth/auth-email-templates#terminology
Running into the same issue here. Any updates? 🙂
Yes! This is really annoying during development on localhost, when you want to test out the different email confirmations. In the official example, they have removed the usage of ".ConfirmationURL" to ".SiteURL" with ".TokenHash", which makes me believe that ".confirmationURL" will be entirely removed/changed soon.
https://supabase.com/docs/guides/auth/server-side/email-based-auth-with-pkce-flow-for-ssr?framework=nextjs
Im also having this issue, seems impossible to have both localhost and prod logins redirect correctly. My sign up function looks like this:
export async function action({ request, context }: ActionFunctionArgs) {
const cookies = parse(request.headers.get("Cookie") ?? "");
const headers = new Headers();
const formData = await request.formData();
const supabase = createServerClient(
context.env.SUPABASE_PROJECT_URL!,
context.env.SUPABASE_ANON_KEY!,
{
cookies: {
get(key) {
return cookies[key];
},
set(key, value, options) {
headers.append("Set-Cookie", serialize(key, value, options));
},
remove(key, options) {
headers.append("Set-Cookie", serialize(key, "", options));
}
}
}
);
const { data, error } = await supabase.auth.signUp({
email: formData.get("email") as string,
password: formData.get("password") as string,
options: {
emailRedirectTo: context.env.AUTH_REDIRECT_URI // resolves to "http://localhost:8788" in the dev env, is set to prod url on Cloudflare
}
});
if (error) {
return new Response(JSON.stringify(error), {
headers
});
}
return new Response(JSON.stringify(data), {
headers
});
}
I'm having the same issue, is there any updates on this?
I also ran into a similar issue, but I don't think the fix should be to override
{{ .SiteURL }}as a redirect URL is not related to the Site URL.Instead, the root cause is the fact
{{ .RedirectURL }}does not appear to work in the email templates, although the docs state it should be supported forsignInWithOtp.The redirect URLs are configured correctly because I can see the parameter in the
{{ .ConfirmationURL }}.https://supabase.com/docs/guides/auth/auth-email-templates#terminology
Stumbled upon this issue also expecting {{ .SiteURL }} to be overwritten with the redirect URL. I did not know {{ .RedirectURL }} was an option and I tried it out and it's working for me!