Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Broken Invitation Links - http://kong is the domain #1228

Closed
2 tasks done
iarata opened this issue Aug 7, 2023 · 39 comments · Fixed by #1808 or #1809 · May be fixed by #1571
Closed
2 tasks done

Broken Invitation Links - http://kong is the domain #1228

iarata opened this issue Aug 7, 2023 · 39 comments · Fixed by #1808 or #1809 · May be fixed by #1571
Labels
auth bug Something isn't working

Comments

@iarata
Copy link

iarata commented Aug 7, 2023

Bug report

  • I confirm this is a bug with Supabase, not with my own application.
  • I confirm I have searched the Docs, GitHub Discussions, and Discord.

Describe the bug

Currently, when sending an invitation to a user, the invitation link in the email is http://kong/auth/v1/verify?token=xxx rather than the proper domain.

To Reproduce

Steps to reproduce the behaviour, please provide code snippets or a repository:

  1. Setup docker Supabase
  2. Go to the authentication
  3. Click "Add user"
  4. Select "Send Invitation"
  5. Check the invitation link in the email

Expected behaviour

It was expected that the invitation URL to contain the configured URLs in the .env file rather than http://kong as the domain.

@iarata iarata added the bug Something isn't working label Aug 7, 2023
@iarata iarata changed the title Broken Invitation Links - http://kong is the hostname Broken Invitation Links - http://kong is the domain Aug 7, 2023
@saltcod saltcod added the auth label Aug 7, 2023
@J0 J0 transferred this issue from supabase/supabase Aug 21, 2023
@rmvh
Copy link

rmvh commented Sep 22, 2023

I think this was introduced in PR #999, where a bit of magic is used to determine the hostname regardless of the configured API_EXTERNAL_URL in the function isValidExternalHost here, although I'm not sure I understand it completely.

In my case the host in the confirmation mails is set to supabase-kong, which of course doesn't resolve outside of the docker network. It used to just use the API_EXTERNAL_URL correctly. This makes it difficult to test the sign-up flow during development.

@tomekit
Copy link

tomekit commented Oct 1, 2023

There is some breaking change in a minor release: v2.67.1 (v2.67.0...v2.67.1).

In our case, after upgrading Docker image to anything above v2.67.1 (including current latest) turns the account confirmation URL from https to https, there are also some other minor changes.

v2.67.0 (correct)

https://auth.domain.app/auth/v1/verify?token=token&type=signup&redirect_to=https://web.domain.app/login

v2.67.1 (broken)

http://auth.domain.app/auth/v1/verify?redirect_to=https%3A%2F%2Fweb.domain.app%2Flogin&token=token&type=signup

I've tried to reproduce this outside of the docker environment, kong etc. by injecting our configuration through .env, so I can run the debugger on main.go. I've set up breakpoints on: ConfirmationMail and isValidExternalHost and problem doesn't exist for some reason.

Unfortunately I don't have much time currently to add some additional logging to the code, compile the binary and debug/run it from the Docker context, to understand at which stage the URL does get broken.

@tomekit
Copy link

tomekit commented Oct 1, 2023

I suspect that it's part of the: isValidExternalHost function which unintentionally modifies the URL, specifically:

baseUrl := config.API.ExternalURL
	xForwardedHost := req.Header.Get("X-Forwarded-Host")
	xForwardedProto := req.Header.Get("X-Forwarded-Proto")
	if xForwardedHost != "" && xForwardedProto != "" {
		baseUrl = fmt.Sprintf("%s://%s", xForwardedProto, xForwardedHost)
	} else if req.URL.Scheme != "" && req.URL.Hostname() != "" {
		baseUrl = fmt.Sprintf("%s://%s", req.URL.Scheme, req.URL.Hostname())
	}

Sorry for mentioning you directly: @kangmingtay, but perhaps you could help us to understand the intention behind these two if/else cases where baseUrl (initially set from env) is overriden by the headers or request data.

In our case we run Kong in the HTTP context, as we terminate SSL at the upper layer. I suspect that because of Kong running in http context, it sets the: X-Forwarded-Proto (Kong/kong#2202) header to HTTP and: isValidExternalHost function overrides the value specified in the API_EXTERNAL_URL header. I need to confirm that claim, but at this stage sounds plausible.

@tomekit
Copy link

tomekit commented Oct 1, 2023

Our infamous fix is here: v2.151.0...tomekit:auth:v2.151.0_tr it's likely not something that should be merged to supabase/gotrue, but it gives an idea where the problem is.

@kangmingtay
Copy link
Member

kangmingtay commented Oct 2, 2023

@tomekit we use those headers to determine the hostname to use for email links and the baseUrl defaults to use the API_EXTERNAL_URL env var if those headers are missing.

In the supabase context, the API_EXTERNAL_URL is set to https://project_ref.supabase.co/auth/v1. With custom domains or vanity subdomains, the baseUrl can be either the custom domain, the vanity subdomain or the default domain assigned and it should be based on the hostname used in the request.

In our case we run Kong in the HTTP context, as we terminate SSL at the upper layer. I suspect that because of Kong running in http context, it sets the: X-Forwarded-Proto (Kong/kong#2202) header to HTTP and: isValidExternalHost function overrides the value specified in the API_EXTERNAL_URL header. I need to confirm that claim, but at this stage sounds plausible.

does kong forward the original request url in a header?

@timkister
Copy link

I'm facing the same problem.
My temporary fix is to switch to "supabase/gotrue:v2.67.0" in my docker-compose.yml

@tomekit
Copy link

tomekit commented Oct 6, 2023

does kong forward the original request url in a header?

I am not sure, I am using default kong setup from: https://supabase.com/docs/guides/self-hosting/docker
What header are we talking about? Would that be X-Forwarded-Path?

@donalffons
Copy link

I'm also having this issue (as reported in the original issue, with http://kong in the confirmation email) with a mostly default self-hosting docker-compose.yml + .env.

The issue is present with supabase/gotrue:v2.67.1 but goes away with supabase/gotrue:v2.67.0.

@EasternIndustries-IT
Copy link

I'm not sure if anyone has realized but in the docker-compose.yml it states SUPABASE_URL: http://kong/ changing this to use the API_EXTERNAL_URL variable should solve your issue. Or so one would think I have changed it to the local ip and i am getting it in the email link but I don't get the port. Which in my case is 8000 the api is supposed to be directed too.

@marcio-andrade
Copy link

I'm also having this issue (as reported in the original issue, with http://kong in the confirmation email) with a mostly default self-hosting docker-compose.yml + .env.

The issue is present with supabase/gotrue:v2.67.1 but goes away with supabase/gotrue:v2.67.0.

i verify and ok in 2.67.0 but using 2.99.00 not work correct

@marcio-andrade
Copy link

Is present bug in v2.67.1 and next. In v2.67.0 is correct use of SUPABASE_URL in sended e-mal link.

@philmas
Copy link

philmas commented Dec 12, 2023

Issue is indeed still there. Would be nice to somehow be able to specify this.

@Obeyed
Copy link

Obeyed commented Dec 19, 2023

How come this issue is not prioritized? If I'm not mistaken then all affected by this issue are vulnerable to man-in-the-middle attacks because of the unencrypted traffic. 🤔

I'm self-hosting with docker and it seems that all email links are currently with http. It seems to be the case regardless of API_EXTERNAL_URL environment and any X-Forwarded-Proto headers.

Is there a workaround to force https for links in emails? What's the right way to get this up and running correctly?

Sorry for the direct mentions, but it seems that you guys could have some more info on this. @tomekit @kangmingtay
Any help is appreciated, thanks!

@hf
Copy link
Contributor

hf commented Dec 19, 2023

@Obeyed How are you self-hosting? What are the environment variables added to the GoTrue/Auth container?

@Obeyed
Copy link

Obeyed commented Dec 19, 2023

With docker swarm behind nginx proxy. Have https context until my load balancer servers, from which the TLS is terminated and only http is used on the private network where kong, gotrue, and the remaining swarm runs.

Using image supabase/gotrue:v2.127.2

I assume these two environment variables are the relevant ones (not the real domains, but you get the idea):

API_EXTERNAL_URL: https://sub.domain1.com
GOTRUE_SITE_URL: https://sub.domain2.com

This is the example link from an invitation email that would be sent out:

http://sub.domain1.com/auth/v1/verify?token=some-token&type=invite&redirect_to=https://sub.domain2.com

Notice, the GOTRUE_SITE_URL (domain2) has the correct protocol, but the API_EXTERNAL_URL (domain1) uses the http protocol. I would assume that the entire API_EXTERNAL_URL including the protocol would be used. Is that not expected in some cases?

Any other info that can help?

@tomekit
Copy link

tomekit commented Dec 19, 2023

Hi @Obeyed,
I am not sure if I can help here.
In our case we're running fork with a couple amendments. Most importantly this line needs changing: c1f0ec8#diff-97dfc3310e5139b4d9c7a160bd077aeb81ca1e7b8d7cfa837a402f54b4c03a3dR213

Given that Supabase team is likely busy with other items your best bet is either to wait or apply it yourself and build a Docker image, alternatively use our build: s3drive/gotrue:v2.129.1 (https://hub.docker.com/layers/s3drive/gotrue/v2.129.1/images/sha256-a8176564a48f34b20598884848f284ed78cb8db0b5d44fea20d2ed8d37a4eab9?context=explore) which is the most recent Supabase version with these two fixes applied: master...tomekit:gotrue:master however please be aware that you shouldn't really use unofficial images for your organization... after all it's auth.

Good luck !

@Obeyed
Copy link

Obeyed commented Dec 21, 2023

@hf do you need any more info? It would be great to get some insight into how this can be set up such that it works as expected. Right now I'm unsure of which HTTP Headers / Environment Variables to set to get the desired output with https. I have tried to set the HTTP Headers X-Forwarded-Host and X-Forwarded-Proto to force https via nginx through kong, but that didn't seem to affect the output. I'm assuming that kong forwards these headers. Haven't had time to dig deeper into this.

@hf
Copy link
Contributor

hf commented Dec 21, 2023

Yes you probably need to set those headers deep in your stack, both in Kong and/or Nginx. GoTrue uses these headers to allow you to host the Auth server on multiple domains.

Unfortunately I'm not an expert in Kong so can't help you out there.

@hf
Copy link
Contributor

hf commented Dec 21, 2023

If you want you can open a PR that adds a new config variable to ignore those headers in GoTrue.

@rmvh
Copy link

rmvh commented Dec 21, 2023

Up till version 2.67.0, this worked properly as expected. Though it's cool to be able to specify multiple custom domains (the feature in 2.67.1 which if I understand correctly introduced the breaking change), this leaves many of us self-hosters without the option to properly specify even a single domain. It seems weird to have an API_EXTERNAL_URL if it is going to be partially ignored, where the expectation is that that variable can be used to set - with absolute certainty and overriding all other values - the external URL for the API to be used anywhere, e.g. email templates.

If it is too much to ask for the original functionality to be brought back, perhaps the variable API_EXTERNAL_URL can be renamed to API_EXTERNAL_DOMAIN so that it is no longer misleading?

In the meantime, I thought I'd mention our solution which might be a bit obvious but could be useful to some: we've implemented custom endpoints for those actions that need to send emails (e.g. magic link, reset password), calling supabase.auth.admin.generateLink manually and then using javascript's URL to change the protocol and domain back to what it should be, and finally manually sending the mail. Doing it this way does require clients to call those endpoints instead of using the built-in Supabase methods, but it gives you full control over every aspect. See also this blog post about sending i18n-ready mails by Supabase's @mansueli

@dsyrstad
Copy link

This affects /recover as well. I self-host. You will never be to reliably determine the API URL from request headers. For example, I have my app and api fronted by AWS Cloudfront. Cloudfront terminates SSL and relays https://myapp.com/api/... requests to my kong instance, which then forwards to gotrue. You won't see "https://myapp.com" in any of the headers - ever. I also have API_EXTERNAL_URL set to https://myapp.com, but it has no effect with 2.132.0.

@lichong-a
Copy link

I also think that this problem is quite serious, and I hope it can be properly resolved, otherwise privatized deployment will be affected. If I have the ability I will also try to submit a PR.

@armandusbasson
Copy link

armandusbasson commented Apr 4, 2024

In the docker-compose.yml file there is a line SUPABASE_URL: http://kong
Replace that with your project's URL, then stop and create the containers again:

// Stop and remove the containers
docker compose down

//Recreate and start the containers
docker compose up -d

This worked for me and the Invite emails are now giving the correct link.

@Chipsnet
Copy link

However, this means that STUDIO will attempt to access kong from the outside

For security reasons, it is recommended that studio access kong from within the docker container

While helpful in the short term, this problem needs to be fixed in the long term.

@Vokturz
Copy link

Vokturz commented Apr 17, 2024

In my case it also happens when trying to reset my password :(

Any progress on this? I see this problem has been here for a while.

@nickmitchko
Copy link

nickmitchko commented May 5, 2024

This was bugging me hard. So I added a force no-change environment variable and submitted a PR.

With the changes:

  1. Set API_EXTERNAL_URL environment variable as you normally would.
  2. Add a new environment variable API_FORCE_EXTERNAL_URL to equal true.

.env:

API_EXTERNAL_URL=https://sb.mydomain.com/auth/v1
API_FORCE_EXTERNAL_URL=true

Kubernetes:

  environment:
    API_EXTERNAL_URL: https://sb.mydomain.com/auth/v1
    API_FORCE_EXTERNAL_URL: "true"

Fix repo: nickmitchko/auth
Fix container (latest): nickmitchko/gotrue:latest
Fix PR: #1571

@Vokturz, @Chipsnet, @hf

@Paillat-dev
Copy link

@nickmitchko Thanks much, because this was getting really boring...

@dshongphuc
Copy link

We can temporarily fix this by changing the MAILER_ variables in the .env. #1571 (comment)

@tsifei888
Copy link

We have the same issue.
Please fix it guys

@Paillat-dev
Copy link

I find it really unbelievable this issue is still open.

@nickmitchko
Copy link

I find it really unbelievable this issue is still open.

If I find time I'll update my repo with the latest changes again.

@blbergo
Copy link

blbergo commented Oct 3, 2024

I am experiencing a similar issue with the storage API, createSignedUrl in the js SDK is returning a URL with kong:8000 as the domain.

@arkodeep3404
Copy link

still facing the same issue

@arkodeep3404
Copy link

MAILER_URLPATHS_CONFIRMATION="${API_EXTERNAL_URL}/auth/v1/verify"
MAILER_URLPATHS_INVITE="${API_EXTERNAL_URL}/auth/v1/verify"
MAILER_URLPATHS_RECOVERY="${API_EXTERNAL_URL}/auth/v1/verify"
MAILER_URLPATHS_EMAIL_CHANGE="${API_EXTERNAL_URL}/auth/v1/verify"

this works

@hf hf closed this as completed in #1808 Oct 22, 2024
hf added a commit that referenced this issue Oct 22, 2024
Adds a new config option `GOTRUE_MAILER_EXTERNAL_HOSTS` that serves as
an allowlist to all the acceptable hosts provided to the APIs.

Fixes #1228
hf pushed a commit that referenced this issue Oct 22, 2024
🤖 I have created a release *beep* *boop*
---


##
[2.163.1](v2.163.0...v2.163.1)
(2024-10-22)


### Bug Fixes

* external host validation
([#1808](#1808))
([4f6a461](4f6a461)),
closes [#1228](#1228)

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@kangmingtay
Copy link
Member

hi everyone, we fixed this issue recently by specifying a new config param - GOTRUE_MAILER_EXTERNAL_HOSTS which specifies the list of hosts that can be used. If this is empty, it will just default to use the API_EXTERNAL_URL

this is somewhat similar to the suggestion @nickmitchko proposed but we're solving it with an allow list rather than a flag to disable it

@ohhsj
Copy link

ohhsj commented Nov 22, 2024

Hi @kangmingtay I setup a self-host Supabase and ran into an error that suggests GOTRUE_MAILER_EXTERNAL_HOSTS needs to be configured also for paths like http://localhost:8000/auth/v1/sso.

I have been wondering why, so if you or someone can advise, that will be great.

I was following Calvin's excellent tutorial on turning on SAML SSO. https://calvincchan.com/blog/self-hosted-supabase-enable-sso

@gavinc
Copy link

gavinc commented Dec 19, 2024

hi everyone, we fixed this issue recently by specifying a new config param - GOTRUE_MAILER_EXTERNAL_HOSTS which specifies the list of hosts that can be used. If this is empty, it will just default to use the API_EXTERNAL_URL

this is somewhat similar to the suggestion @nickmitchko proposed but we're solving it with an allow list rather than a flag to disable it

excellent- now, the crucial bit that seems to elude the internet, where can I set this value? (using supabase-cli for local docker env)

  1. setting it in .env.local for my project didn't work.
  2. It doesn't go in config.toml - I cannot locate the docker-compose.yaml that presumably supabase-cli creates somewhere.

What is the officially blessed location?

@cstockton
Copy link
Contributor

@gavinc I wasn't sure myself, so I just did some greps through Supabase CLI and it seems to maintain a mapping of toml config -> auth env values. Unfortunately I don't see this config value mapped so a pull request would need to be made on the CLI to set them from the toml file.

A quick hack for you might be to add your own .env file directly into the container, as auth will load a .env file if present. Given the CWD of auth is /, the below should work:

# See the current setting for env var: GOTRUE_EXTERNAL_ANONYMOUS_USERS_ENABLED
curl -s http://127.0.0.1:54321/auth/v1/settings | jq -r '.external.anonymous_users'

docker exec -u root -it 2f883354b5a0 \
  /bin/sh -c \
    'echo "GOTRUE_EXTERNAL_ANONYMOUS_USERS_ENABLED=true" > .env'

# Append any other settings you want, or just cp a file into the container.
docker exec -u root -it 2f883354b5a0 \
  /bin/sh -c \
    'echo "GOTRUE_MAILER_EXTERNAL_HOSTS=http://myexternalhost.local" >> .env'

# Restart container
docker restart 2f883354b5a0

# Both env vars should now be updated, we make sure the file was read by
# checking the settings endpoint.
curl -s http://127.0.0.1:54321/auth/v1/settings | jq -r '.external.anonymous_users'

@gavinc
Copy link

gavinc commented Dec 19, 2024

Really appreciate the hack @cstockton - I did manage to apply it (to the Auth container) and did indeed see that the reload applied the externa_anon change - saw the GO_TRUE in the .env file... and yet inthe auth logs still getting:
{"level":"info","msg":"Request received external host in X-Forwarded-Host or Host headers, but the values have not been added to GOTRUE_MAILER_EXTERNAL_HOSTS and will not be used. To suppress this message add the host, or sanitize the headers before the request reaches Auth.","time":"2024-12-19T20:49:05Z","x_forwarded_host":"localhost","x_forwarded_proto":"http"}

as if I hadn't put in http://localhost:3000/ :(

This is all in an attempt to stop supabase from apparently eating the invite params when forwarding to the auth callback. My hunt continues :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auth bug Something isn't working
Projects
None yet