pow-auth / pow

Robust, modular, and extendable user authentication system
https://powauth.com
MIT License
1.61k stars 160 forks source link

Email Confirmation URL in is incorrect #556

Open That-David-Guy opened 4 years ago

That-David-Guy commented 4 years ago

I have set the default confirmation email behaviour so when a user registers it will send an email and they have to click a link.

On local the link looks as expected

http://localhost:4000/confirm-email/SFMyNTY.NDkwYWRlMzMtNjc4Ny00ZjczLTkxODgtYzVjMDVhOGRkYzU2.kJnIc2fwPv578DXr_S7CUthkcsu7pqTE916FZ3q7K8g

However in prod its does not:

http://[http://makeawesomeworkshop.com]:5000/confirm-email/SFMyNTY.NGMzNzZiMTYtNWUyZi00YjUxLTgzNzctNmI4ZDU1YWYxNzM2.eMK80f11-EntQGlMv-8tKsqMdyKEnSjwvXwh66WjWoc

Note this part of it http://[http://makeawesomeworkshop.com]:5000/confirm-email/

I expected it to look like:

http://www.makeawesomeworkshop.com/confirm-email/

I can't find the config to change this? I'm assuming it's getting it dynamically somehow?

I do have my phoenix running in a docker container setup as so:

Phoenix container <-> Nginx container <-> Internet

I feel that is important to mention because the 5000 port is the port that nginx container talks to the phoenix container on. It is not the Internet address.

How can I solve my issue?

That-David-Guy commented 4 years ago

In the meantime, I've switched out the template for my own in Mailer module's cast method based on the subject I grab the token from the template, then make a new one with the corrected urls. It makes me cry a bit but it's unblocked me for now.

This is. my new mailer module

defmodule MawWeb.Pow.Mailer do
  use Pow.Phoenix.Mailer
  use Bamboo.Mailer, otp_app: :maw

  import Bamboo.Email

  @impl true
  def cast(%{user: user, subject: subject, text: text, html: html}) do
    Maw.Logger.divider("cast")
    [subject_, text_, html_] =
      if Application.get_env(:maw, :env) == :prod do
        # The links are incorrect in prod due to docker containers THIS IS THE NEW BIT
        update_template_for_prod(subject, text, html)
      else
        [subject, text, html]
      end

    new_email(
      to: user.email,
      from: "welcome@mail.makeawesomeworkshop.com",
      subject: subject_,
      html_body: html_,
      text_body: text_
    )
    |> Maw.Logger.log("new_email")
  end

  defp update_template_for_prod(subject, text, html) do
    case subject do
      "Confirm your email address" ->
        token = get_token_from_confirm_email(text)

        [
          "[MAW] Confirm your email address",
          "Welcome to make*awesome*workshop.\nClick to confirm your email: http://www.makeawesomeworkshop.com/confirm-email/#{token}\n",
          "<h1>Welcome to make<strong>awesome</strong>workshop</h1><p>Click to confirm your email: <a href='http://www.makeawesomeworkshop.com/confirm-email/#{token}'>http://www.makeawesomeworkshop.com/confirm-email/#{token}</a></p>"
        ]

      "Reset password link" ->
        token = get_token_from_reset_email(text)
        [
          "[MAW] Reset password link",
          "Hi,\n\nPlease use the following link to reset your password:\n\nhttp://www.makeawesomeworkshop.com/reset-password/#{token}\n\nYou can disregard this email if you didn't request a password reset.\n",
          "<h3>Hi,</h3><p>Please use the following link to reset your password:</p><p><a href=\"http://www.makeawesomeworkshop.com/reset-password/#{token}\">http://www.makeawesomeworkshop.com/reset-password/#{token}</a></p><p>You can disregard this email if you didn&#39;t request a password reset.</p>"
        ]
      _ ->
        [ subject, text, html]
    end
  end

  defp get_token_from_confirm_email(text) do
    text
    |> String.split("confirm-email/")
    |> (fn [_, x] -> x end).()
    |> String.split("\n")
    |> (fn [x, _] -> x end).()
  end

  defp get_token_from_reset_email(text) do
    text
    |> String.split("/reset-password/")
    |> (fn [_, x] -> x end).()
    |> String.split("\n\nYou")
    |> (fn [x, _] -> x end).()

  end

  @impl true
  def process(email) do
    # An asynchronous process should be used here to prevent enumeration
    # attacks. Synchronous e-mail delivery can reveal whether a user already
    # exists in the system or not.
    Maw.Logger.divider("process")

    deliver_later(email)
  end
end
That-David-Guy commented 4 years ago

I also had to add this line to my config file to get the above to work config :maw, env: Mix.env()

Schultzer commented 4 years ago

The urls are generated by Phoenix. You might have to tweak your endpoint settings for production.

danschultzer commented 4 years ago

As @Schultzer wrote, you should update the endpoint config. The Phoenix URL generator is creating the URL's: https://github.com/danschultzer/pow/issues/553#issuecomment-680038814

config :my_app, MyAppWeb.Endpoint,
  # ...,
  url: [scheme: "https", host: "example.com", port: 443]
That-David-Guy commented 4 years ago

Thanks for the replies. I believe that setting is important for my docker setup and changing it will cause some issues. So it will be a few weeks before I'll have the time to make such a change.

danschultzer commented 4 years ago

It would only affect URL generation, so anywhere where you use _url calls in Phoenix.