ashok

ashok

I have used Pow for user authentication and successfully created login & logout feature using custom controller (Custom controllers — Pow v1.0.39 ) Now I want to create Forgot Password feature. Pow provides reset password extension “PowResetPassword”. I have install Pow extension by reading the documentation (PowResetPassword — Pow v1.0.39)

I have created a new controller for reset password “WEB_PATH/controllers/reset_password/reset_password_controller.ex”

The controller code is shown below.

def new(conn, _params) do
changeset = Pow.Plug.change_user(conn)

render(conn, "new.html", changeset: changeset)

end

def create(conn, %{“user” => user_params}) do

conn
|> PowResetPassword.Plug.create_reset_token(user_params)
|> case do
     {:ok, conn} ->
     conn
     |> put_flash(:info, 'Check your email to reset password')
     |> redirect(to: Routes.reset_password_path(conn, :new))

     {:error, conn} ->
        conn
        |> put_flash(:info, "Error resetting")
        |> redirect(to: Routes.reset_password_path(conn, :new))

   end

end

def update(conn, %{“user” => user_params}) do

PowResetPassword.Plug.update_user_password(conn, user_params)
# {:ok, conn} = Pow.Plug.clear_authenticated_user(conn)

redirect(conn, to: Routes.login_path(conn, :new))

end

My reset password view is:

<%= form_for @changeset, Routes.reset_password_path(@conn, :create), [class: “form-wrap login-form w-100”], fn f → %>

Reset password

<%= label f, :email, "" %> <%= text_input f, :email, class: "form-control", id: "email", placeholder: "Email" %>
<%= submit "Continue", class: "btn btn-primary w-100" %>

<% end %>

My routes are

signup_path GET / MyAppWeb.RegistrationController :new
signup_path POST / MyAppWeb.RegistrationController :create
login_path GET /login MyAppWeb.SessionController :new
login_path POST /login MyAppWeb.SessionController :create
reset_password_path GET /reset-password/new MyAppWeb.ResetPasswordController :new
reset_password_path POST /reset-password MyAppWeb.ResetPasswordController :create
reset_password_path PATCH /reset-password/:id MyAppWeb.ResetPasswordController :update
PUT /reset-password/:id MyAppWeb.ResetPasswordController :update
reset_password_path GET /reset-password/:id MyAppWeb.ResetPasswordController :edit
logout_path DELETE /logout MyAppWeb.SessionController :delete
game_path GET /game MyAppWeb.PageController :index
websocket WS /socket/websocket MyAppWeb.UserSocket

When I hit submit ‘continue’ button in reset password page with or without entring any email I am getting error as shown below:

CaseClauseError at POST /reset-password
no case clause matching: {:error, #Ecto.Changeset<action: :update, changes: %{}, errors: [password_hash: {“can’t be blank”, [validation: :required]}, password: {“can’t be blank”, [validation: :required]}], data: #MyApp.Users.User<>, valid?: false>, %Plug

I have taken reference from the Pow module PowResetPassword.Phoenix.ResetPasswordController present in my project “deps” folder but not sure which one to use in “create” , “edit” and “update”. please suggest how can I over come this issue.

Showing Posts 1 to 10

danschultzer

danschultzer

Pow Core Team

Your case statement is invalid. PowResetPassword.Plug.create_reset_token/2 returns {:ok, %{token: token, user: user}, conn} or {:error, changeset, conn}.

For security you should also respond with success no matter the result:

def create(conn, %{“user” => user_params}) do
  conn
  |> PowResetPassword.Plug.create_reset_token(user_params)
  |> case do
    {:ok, %{token: token, user: user}, conn} ->
      # Send e-mail

      conn
      |> put_flash(:info, 'Check your email to reset password')
      |> redirect(to: Routes.reset_password_path(conn, :new))

    {:error, conn} ->
      conn
      |> put_flash(:info, 'Check your email to reset password')
      |> redirect(to: Routes.reset_password_path(conn, :new))
  end
end

Take a look at the controller for more.

ashok

ashok OP

Thanks for the solution it works now I am not getting any error but still there is an issue I was assuming that there should be some entry in “user” table for the column “email_confirmation_token”, “email_confirmed_at” or in “unconfirmed_email”.

When run forgot password it works well showing me flash message “Check your email to reset password” and when I looked into the database for the corresponding user there is no update in the database column.

I had followed the documentation — Pow v1.0.39 to “Add extensions support” and install the PowResetPassword and PowEmailConfirmation extensions

Please help how to insert token data into my database?

danschultzer

danschultzer

Pow Core Team

Those columns will only be filled during registration create/update as they are part of the PowEmailConfirmation extension.

PowResetPassword stores the reset token in the cache store.

Muhammad

Muhammad

@danschultzer Thanks for your reply, but I have one more question

> def create(conn, %{“user” => user_params}) do
>   conn
>   |> PowResetPassword.Plug.create_reset_token(user_params)
>   |> case do
>     {:ok, %{token: token, user: user}, conn} ->
>       # How to send email here?
> 
>       conn
>       |> put_flash(:info, 'Check your email to reset password')
>       |> redirect(to: Routes.reset_password_path(conn, :new))
> 
>     {:error, conn} ->
>       conn
>       |> put_flash(:info, 'Check your email to reset password')
>       |> redirect(to: Routes.reset_password_path(conn, :new))
>   end
> end

How can I send email after reset token in the code above?

danschultzer

danschultzer

Pow Core Team

Just for anyone who’s reading, the question was answered on Github: Custom controller for reset password using pow · Issue #354 · pow-auth/pow · GitHub

sveredyuk

sveredyuk

I am using Pow and PowAssent for API-based app and always getting the result like:

{:error, changeset, _conn} = PowResetPassword.Plug.create_reset_token(conn, %{"email" => "user@example.com"})

changeset # => #Ecto.Changeset<action: nil,changes: %{},errors: [password: {"can't be blank", [validation: :required]}],data: #Handshake.Accounts.User<>,valid?: false

why it requires a password?

danschultzer

danschultzer

Pow Core Team

It’s because the same changeset is used as when the password gets changed. That’s a bug and it should just return a blank changeset. I’ve opened an issue on Github and will fix it promptly: Confusing changeset error when email can't be found in PowResetPassword · Issue #482 · pow-auth/pow · GitHub

sveredyuk

sveredyuk

@danschultzer I see. Thank you a lot for your amazing work.

Hossman333

Hossman333

Hi there! This is great. Thanks for this forum. I have everything working, except it’s giving me a false positive when I call “update_user_password”. It appears it never actually hashes the password in that function for me. I could hash the password and then pass it to that method, but for me to hash it I need to know the “secret”. “Pow.Ecto.Schema.Password.pbkdf2_hash()” Would the secret be something like the “SECRET_KEY_BASE” environment variable? Or how exactly does calling “PowResetPassword.Plug.update_user_password” supposed to work?

Basically I call “PowResetPassword.Plug.load_user_by_token” before and then pass the conn to “PowResetPassword.Plug.update_user_password”. Everything is great other than it not actually updating it in the DB field / hashing it.

Let me know. Thank you friends

Hossman333

Hossman333

Ahhhhhh. I figured it out. Haha. Whoops. I was using my own changeset instead of what I should have been doing. Inside the changeset is where the magic happens.

I now call these methods inside my changeset:

      |> Pow.Ecto.Schema.Changeset.confirm_password_changeset(attrs, @pow_config)
      |> Pow.Ecto.Schema.Changeset.new_password_changeset(attrs, @pow_config)

Thanks!

— All posts loaded —

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
Blokh
Hey guys, I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly Do you guys have any suggestions what is the best prac...
New
roeland
Kia ora, We have been using elixir-google-api to connect to Google Drive. However, with the updates to Tesla due to CVEs this is now bro...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
Onor.io
I have what I’ve heard referred to as a “lookup table” in my database. This is a way of assigning codes to common values. One common lo...
New
jaybe78
Hello, I’m developing a online persistent chat system (what’s app) like using elixir/dynamodb/aws for a mobile app(flutter). The diffic...
New
Trolleger
What approach to take when sending live updates to “random” users Hi! I have a question, I have a little chat app, and when I create a DM...
New

Other Trending Topics Top

garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
wintermeyer
There are three potential reasons for members of this forum to have a look at https://vutuv.de You are tired or annoyed of LinkedIn. Yo...
New
aseigo
ICal is a library for interacting with iCalendar data. It parses iCalendars into typed Elixir structs via ICal.from_ics, and can prepare ...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews