質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Heroku

HerokuはHeroku社が開発と運営を行っているPaaSの名称です。RubyやNode.js、Python、そしてJVMベース(Java、Scala、Clojureなど)の複数のプログラミング言語をサポートしている。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

メール

メールは、コンピュータネットワークを利用し、 情報等を交換する手段のことです。

Q&A

解決済

1回答

1640閲覧

Rails でユーザ認証を実装したい

ts21

総合スコア32

Heroku

HerokuはHeroku社が開発と運営を行っているPaaSの名称です。RubyやNode.js、Python、そしてJVMベース(Java、Scala、Clojureなど)の複数のプログラミング言語をサポートしている。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

メール

メールは、コンピュータネットワークを利用し、 情報等を交換する手段のことです。

0グッド

0クリップ

投稿2019/11/14 07:09

編集2019/11/15 00:17

前提・実現したいこと

Railstutrialを模倣したRailsのWebアプリケーションを開発しています。
HerokuのSendgridアドオンを用いてユーザ登録の際にメール認証機能を実装している過程です。
登録情報をパラメータにしてメールを送信、受け取ることまではできていまいす。

発生している問題・エラーメッセージ

メールが届き、Activateリンクを踏んでも認証されていないという問題が発生して困っています。
リンクの生成が正しく行われていないのかと思います。
ログはこんな感じです。

Started POST "/users" for ::1 at 2019-11-14 12:26:51 +0900 Processing by UsersController#create as */* Parameters: {"user"=>{"user_name"=>"ts", "email"=>"ts@icloud.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}} (1.4ms) BEGIN ↳ app/controllers/users_controller.rb:25 User Exists (1.3ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER($1) LIMIT $2 [["email", "ts@icloud.com"], ["LIMIT", 1]] ↳ app/controllers/users_controller.rb:25 User Create (2.0ms) INSERT INTO "users" ("email", "password_digest", "activation_digest", "user_name", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETU RNING "id" [["email", "ts@icloud.com"], ["password_digest", "$2a$12$tp4dd/HD7L81zvxaVrNnhOyI1JOBt/300zLEQbiV56rJ9JXqxuN/a"], ["activation_digest", "$2a$12$551NN cMiWkr9seluACIDj.xcmyji5DrMPWXIjqZepoVi42KOCXrPO"], ["user_name", "ts"], ["created_at", "2019-11-14 12:26:51.396443"], ["updated_at", "2019-11-14 12:26:51.396443"]] ↳ app/controllers/users_controller.rb:25 (3.0ms) COMMIT ↳ app/controllers/users_controller.rb:25 Rendering user_mailer/account_activation.html.erb within layouts/mailer Rendered user_mailer/account_activation.html.erb within layouts/mailer (4.4ms) Rendering user_mailer/account_activation.text.erb within layouts/mailer Rendered user_mailer/account_activation.text.erb within layouts/mailer (0.8ms) UserMailer#account_activation: processed outbound mail in 18.7ms Sent mail to ts@icloud.com (972.6ms) Date: Thu, 14 Nov 2019 12:26:51 +0900 From: noreply@example.com To: ts@icloud.com Message-ID: <5dccc97b9f939_c5e93ff5410a0d68858@ts21.local.mail> Subject: Account activation Mime-Version: 1.0 Content-Type: multipart/alternative; boundary="--==_mimepart_5dccc97b9e4cc_c5e93ff5410a0d68846d"; charset=UTF-8 Content-Transfer-Encoding: 7bit ----==_mimepart_5dccc97b9e4cc_c5e93ff5410a0d68846d Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit Hi ts, Welcome to the Sample App! Click on the link below to activate your account: https://aqueous-escarpment-97262.herokuapp.com/account_activations/63/edit?email=ts%40icloud.com&token=-u7w-JfyU21-SgpvcQ1FWQ https://account_activations/63/edit?email=ts%40icloud.com&token=-u7w-JfyU21-SgpvcQ1FWQ ----==_mimepart_5dccc97b9e4cc_c5e93ff5410a0d68846d

Postmanで確認してみるとこんな感じになります

json

1{ 2 "status": "success", 3 "data": { 4 "id": 63, 5 "email": "ts@icloud.com", 6 "password_digest": "$2a$12$tp4dd/HD7L81zvxaVrNnhOyI1JOBt/300zLEQbiV56rJ9JXqxuN/a", 7 "remember_digest": null, 8 "admin": null, 9 "activation_digest": "$2a$12$551NNcMiWkr9seluACIDj.xcmyji5DrMPWXIjqZepoVi42KOCXrPO", 10 "activated_at": null, 11 "reset_digest": null, 12 "reset_sent_at": null, 13 "user_name": "ts", 14 "display_name": null, 15 "address": null, 16 "avatar_uri": null, 17 "created_at": "2019-11-14T12:26:51.396+09:00", 18 "updated_at": "2019-11-14T12:26:51.396+09:00", 19 "activated": false, 20 } 21}

該当のソースコード

user_controller.rb

ruby

1class UsersController < ApplicationController 2 before_action :set_user, only: [:update, :destroy] 3 4 # before_action :logged_in_user, only: [:index, :edit, :update, :destroy, 5 # :following, :followers] 6 # before_action :correct_user, only: [:edit, :update] 7 # before_action :admin_user, only: :destroy 8 9 def create 10 @user = User.new(user_params) 11 if @user.save 12 @user.send_activation_email 13 render json: { status: "Please check your email to activate your account." } 14 else 15 render json: { status: 'error!', data: @user.errors } 16 end 17 end 18 19 def edit 20 @user = User.find(params[:id]) 21end 22 23 def update 24 # @user = User.find(params[:id]) 25 if @user.update(user_params) 26 render json: { status: 'success', data: @user } 27 else 28 render json: { status: 'error', data: @user.errors } 29 end 30 end 31 32 def destroy 33 # User.find(params[:id]).destroy 34 # flash[:success] = "User deleted" 35 # redirect_to users_url 36 @user.destroy 37 render json: { status: 'success', data: @user } 38 end 39 40 private 41 42 def user_params 43 params.require(:user).permit(:user_name,:email,:password,:password_confirmation) 44 # @users = params[:user].permit(:email, :password, :password_confirmation) 45 end 46 47 def set_user 48 @user = User.find(params[:id]) 49 end 50end 51

account_activation_controller.rb

ruby

1class AccountActivationsController < ApplicationController 2 3 def edit 4 user = User.find_by(email: params[:email]) 5 token = params[:token] 6 if user && !user.activated? && user.authenticated?(:activation, :token) 7 user.activate 8 log_in user 9 render json:{status:"Account activated!"} 10 else 11 render json:{status:"Invalid activation link"} 12 end 13 end 14end

account_activation.text.erb

erb

1Hi <%= @user.user_name %>, 2 3Welcome to the Sample App! Click on the link below to activate your account: 4 5<%= edit_account_activation_url(@user, 6 token: @user.activation_token, 7 email: @user.email) %> 8

account_activation.html.erb

erb

1<h1>Sample App</h1> 2 3<p>Hi <%= @user.user_name %>,</p> 4 5<p> 6Welcome to the Sample App! Click on the link below to activate your account: 7</p> 8 9<%= link_to "Activate", edit_account_activation_url(@user, 10 token: @user.activation_token, 11 email: @user.email) %> 12

user.rb

ruby

1class User < ApplicationRecord 2 attr_accessor :remember_token, :activation_token 3before_save :downcase_email 4before_create :create_activation_digest 5 6validates :user_name, presence: true, length: { maximum: 50 } 7VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+.[a-z]+\z/i 8validates :email, presence: true, length: { maximum: 255 }, 9 format: { with: VALID_EMAIL_REGEX }, 10 uniqueness: { case_sensitive: false } 11has_secure_password 12validates :password, presence: true, length: { minimum: 6 }, allow_nil: true 13 14 def User.digest(string) 15 cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : 16 BCrypt::Engine.cost 17 BCrypt::Password.create(string, cost: cost) 18 end 19 20 21 # Returns the hash digest of the given string. 22 def User.digest(string) 23 cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : 24 BCrypt::Engine.cost 25 BCrypt::Password.create(string, cost: cost) 26 end 27 28 # Returns a random token. 29 def self.new_token 30 SecureRandom.urlsafe_base64 31 end 32 33 # Remembers a user in the database for use in persistent sessions. 34 def remember 35 self.remember_token = User.new_token 36 update_attribute(:remember_digest, User.digest(remember_token)) 37 end 38 39 # Returns true if the given token matches the digest. 40 def authenticated?(attribute, token) 41 digest = send("#{attribute}_digest") 42 return false if digest.nil? 43 BCrypt::Password.new(digest).is_password?(token) 44 end 45 46 # Forgets a user. 47 def forget 48 update_attribute(:remember_digest, nil) 49 end 50 51 # Activates an account. 52 def activate 53 update_attribute(:activated, true) 54 update_attribute(:activated_at, Time.zone.now) 55 end 56 57 # Sends activation email. 58 def send_activation_email 59 UserMailer.account_activation(self).deliver_now 60 end 61 62 # Sets the password reset attributes. 63 def create_reset_digest 64 self.reset_token = User.new_token 65 update_attribute(:reset_digest, User.digest(reset_token)) 66 update_attribute(:reset_sent_at, Time.zone.now) 67 end 68 69 # Sends password reset email. 70 def send_password_reset_email 71 UserMailer.password_reset(self).deliver_now 72 end 73 74 # Returns true if a password reset has expired. 75 def password_reset_expired? 76 reset_sent_at < 2.hours.ago 77 end 78 79 # Returns a user's status feed. 80 def feed 81 following_ids = "SELECT followed_id FROM relationships 82 WHERE follower_id = :user_id" 83 Micropost.where("user_id IN (#{following_ids}) 84 OR user_id = :user_id", user_id: id) 85 end 86 87 # Follows a user. 88 def follow(other_user) 89 following << other_user 90 end 91 92 # Unfollows a user. 93 def unfollow(other_user) 94 following.delete(other_user) 95 end 96 97 # Returns true if the current user is following the other user. 98 def following?(other_user) 99 following.include?(other_user) 100 end 101 102 private 103 104 # Converts email to all lower-case. 105 def downcase_email 106 self.email = email.downcase 107 end 108 109 # Creates and assigns the activation token and digest. 110 def create_activation_digest 111 self.activation_token = User.new_token 112 self.activation_digest = User.digest(activation_token) 113 end 114 end 115

Invalid activation linkが表示されます。
account_activation_controller.rbのif文の中身がおかしいのかと思っています
何かお気づきになりましたら教えていただきたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

if user && !user.activated? && user.authenticated?(:activation, :token)
と (:activation, :token) で authenticated? を 呼んでますが
def authenticated?(attribute, token) で受けた方は
.is_password?(token) にて params[:token]の値を欲しがってます。

digest = send("#{attribute}_digest") これが謎です。
digest = send("attribute_digest") ってことをやってます。
digest = self.attribute_digest ってことです。

digestは activation_digest に置いてあるのでしょう?
digest = self.attribute_digest
でよいのでは?

ということで多分 user.authenticated?(:activation, token)
引数が一つ不要に思えますが

投稿2019/11/14 22:07

winterboum

総合スコア23329

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ts21

2019/11/15 08:44

回答ありがとうございます。 シンボルを消してみましたがうまくできませんでした。
winterboum

2019/11/15 09:48

エラーメッセージは?
winterboum

2019/11/15 11:51

値が def authenticated?(attribute, token) digest = send("#{attribute}_digest") logger.debug("digest=#{digest}, token=#{token}") #<=== return false if digest.nil? BCrypt::Password.new(digest).is_password?(token) end とでもして、期待通りの値が渡っているかみてみたらどうでしょう
ts21

2019/11/16 02:20

ローカルから立ててたサーバにスマホからメールの認証をしようとしていたことが大きな間違えでした。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問