Railsでマジックリンクの機能を実装
多くのサービスでは、メールアドレスとパスワードを入力してログインするという方法を採用しています。
この方法はシンプルでわかりやすいので、広く普及してきました。ただ問題になったのはパスワードを考える・管理するという方法です。
現在は色々なログイン情報を管理するためのツールがあります。ですが、それらのツールを皆が使っているかと言うとそうでもありません。
ユーザーの中には自分が覚えやすい簡単なパスワードにしたり、他のサービスで使っているパスワードを流用したりしていたりします。
そこで登場したのが、マジックリンクによるログインシステムです。
パスワード認証やマジックリンクについての説明は以下の記事に譲るとして、マジックリンクというのは要は1回限りの認証用のリンクを使ってログインする方法です。
パスワード認証ってもう古くないですか? | 東京上野のWeb制作会社LIG
前置きはこのくらいにして、さっそく Rails アプリで実装してみたいと思います。
今回は passwordless という gem を利用します。
まずは Rails アプリを作成し、 Gemfile に passwordless を追加して bundle install するところまで。
$ rails new magicklink
$ cd magicklink
$ vim Gemfile # gem 'passwordless' を追加
$ bundle install
gem のインストールが完了したら、今度は passwordless のマイグレーションファイルを生成するコマンドを実行し、マイグレーションします。(database.yml の設定は適宜お願いします。)
$ ./bin/rails passwordless:install:migrations
$ ./bin/rails db:create db:migrate
それからログインユーザーとして User モデルを用意します。
$ ./bin/rails generate model User email
$ ./bin/rails db:migrate
それでは passwordless の設定を追加して試してみたいと思います。
user.rb に passwordless_with :email
を追加します。
# user.rb
class User < ApplicationRecord
passwordless_with :email # 追加
end
routes.rb には passwordless_for :users
を追加します。
# routes.rb
Rails.application.routes.draw do
passwordless_for :users
end
そして /users/sign_in
にアクセスするとマジックリンクを送るためのメールアドレス入力欄が表示されます。
では console からユーザーを登録して、マジックリンクを送ってみましょう。
irb(main):001:0> User.create(email: "miyake@ruffnote.com")
(1.8ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
(1.2ms) BEGIN
User Create (1.9ms) INSERT INTO `users` (`email`, `created_at`, `updated_at`) VALUES ('miyake@ruffnote.com', '2019-03-15 01:41:36', '2019-03-15 01:41:36')
(4.5ms) COMMIT
=> #<User id: 1, email: "miyake@ruffnote.com", created_at: "2019-03-15 01:41:36", updated_at: "2019-03-15 01:41:36">
上記のマジックリンク送信画面に登録したメールアドレスを入力して Send magick link をクリックすると以下のようにマジックリンクが記載されたメールが送信されます。
事前に default_url_options
の設定を忘れずに。
Sent mail to miyake@ruffnote.com (56.6ms)
Date: Fri, 15 Mar 2019 10:44:27 +0900
From: CHANGE_ME@example.com
To: miyake@ruffnote.com
Message-ID: <5c8b037b1b94b_9d383ff66b5cd1bc9826@kotamiyake-pro.local.mail>
Subject: =?UTF-8?Q?Your_magic_link_=E2=9C=A8'?=
Mime-Version: 1.0
Content-Type: text/plain;
charset=UTF-8
Content-Transfer-Encoding: 7bitHere's your link: http://localhost:3001/users/sign_in/FwnvkH89BT2Tuh-NGPz7cyCH5ZW3tK3b4UL-snIGD-c
こちらのリンクを URL アドレスバーに入力すると正常に処理されれば root へリダイレクトします。( root 用の controller と view は home など適宜用意してください)
実際にログインできているか current_user
メソッドを追加して確認してみたいと思います。
# application_controller.rb
class ApplicationController < ActionController::Base
include Passwordless::ControllerHelpershelper_method :current_userdef current_user
@current_user ||= authenticate_by_cookie(User)
end
end# home/index.html.erb
<% if current_user.present? %>
<%= current_user.email %>
<%= link_to 'ログアウト', '/users/sign_out', method: :delete %>
<% else %>
ログインしていません。
<% end %>
これでメールアドレスが表示されればログイン成功です。
ログアウトも機能しているか確認します。
あとは current_user
を使って参照権限などを設定いけば良いかと思います。
ここまで passwordless を使った簡単なマジックリンクを使った認証機能の実装を紹介しました。
パスワードを使わないログインで安全では…と思いきや、結局メールを利用しているので、メールアカウントの認証情報を破られれば筒抜けです。
またメールを受信して、リンクをクリックするというステップは使う側からすると、ちょっと面倒な気もします。
とは言え、複数のサービスで同じパスワードを流用するような問題は解決することはできます。
が、それもメールアカウントの管理が適当になってしまうと意味がありません。
最終的には使う側が上手に、そして簡単に管理できるようなメールアドレスとパスワードに変わる認証方法が生まれるのを待つ必要がありそうです。
皆さんもパスワード管理には最新の注意を払いましょう。