devise-passwordless icon indicating copy to clipboard operation
devise-passwordless copied to clipboard

Proper way for magic link to confirm using Devise `confirmable`

Open wilg opened this issue 1 year ago • 6 comments

I have both magic_link_authenticatable and confirmable. However, I want to handle the case where the user never confirms their email, but does click the magic link. This should just mark the user as confirmed, since of course they just received the email. It doesn't appear to work this way by default, and I'm not sure where to hook in. It seems like maybe its getting caught by confirmable first.

wilg avatar Apr 19 '24 23:04 wilg

I could not figure out how to do it the way I originally described, but I overrode the controller so that attempting to send a magic link to an unconfirmed user just sends them the confirmation email instead.

class Users::Passwordless::SessionsController < Devise::Passwordless::SessionsController
  def create
    user = resource_class.find_by(email: create_params[:email])
    if !user || user.confirmed?
      super
    else
      user.send_confirmation_instructions
      set_flash_message!(:notice, :magic_link_sent)
      redirect_to(after_magic_link_sent_path_for(resource), status: devise_redirect_status)
    end
  end
end

wilg avatar Apr 20 '24 00:04 wilg

I'd try something like this instead, which avoids duplicating the code in the passwordless controllers

class Users::MagicLinksController < Devise::MagicLinksController
  def show
    super do |resource|
      resource.confirm unless resource.confirmed?
    end
  end
end

iainbeeston avatar Apr 29 '24 08:04 iainbeeston

@iainbeeston Unfortunately, that does not work for me. Devise catches it before it gets to the controller code and flashes "You have to confirm your email address before continuing." Digging around in the internals it seems quite difficult to change this behavior.

wilg avatar Apr 29 '24 14:04 wilg

not at my dev machine to test this but try something like this

class User
  def after_magic_link_authentication
    unless confirmed?
      skip_confirmation!
      save!
    end
  end
end

abevoelker avatar Apr 30 '24 04:04 abevoelker

(Copying and pasting this to all open issues/PRs:)

Hey all, per #64 I unfortunately won't have much time for the foreseeable future to maintain devise-passwordless to fix the open bugs and work on new features. I'm not abandoning this project, but due to some life issues it's just at the bottom of my priority list for now.

Anyone who wants to step up and be a maintainer to shepherd the project forward would be welcomed! I just ask that you've opened a PR, or written an issue, or can otherwise demonstrate some familiarity/competence with the project. You can reply to #64 or message me privately (through email or socials since GitHub doesn't have DMs) if interested. Thank you :v:

abevoelker avatar Jun 01 '24 19:06 abevoelker

This worked for me:

  # User authed with magic link. Confirm them if they are not already confirmed.
  def after_magic_link_authentication
    unless self.confirmed?
      skip_confirmation!
      self.confirmed_at = Time.now.utc
      save!
    end
  end

(based on @abevoelker 's comment above)

jasonshah avatar May 05 '25 01:05 jasonshah