【Rails7, Sorcery】LINEログインの実装
自己紹介
もなかと申します。
プログラミング学習2年目の初心者です。
Ruby on Railsをメインに勉強しています。
実務は未経験です。
内容につきまして、間違いや不備がありましたらコメントで教えてください。
参考文献
LINEログインの導入
今回、LINE Developerの開発者登録については省略させていただきます。無料で使えます。
環境
Ruby 3.2.2
Rails 7.0.8
gem 'sorcery'
gemのインストール
gem 'omniauth-auth0'
gem 'omniauth-line'
gem 'omniauth-rails_csrf_protection'
bundle install
Externalのインストール
sorceryで外部認証が行えるようにExternalのインストールを行います。
rails g sorcery:install external --only-submodules
以下が生成されます。
class SorceryExternal < ActiveRecord::Migration[7.0]
def change
create_table :authentications do |t|
t.integer :user_id, null: false
t.string :provider, :uid, null: false
t.timestamps null: false
end
add_index :authentications, [:provider, :uid]
end
end
rails db:migrate
モデルを生成します。
外部認証機能を追加する場合、通常は外部認証プロバイダーとの連携に使用する情報を格納するためのマイグレーションファイルは必要ありません。
rails g model Authentication --migration=false
サブモジュールの機能を追加します。
Rails.application.config.sorcery.submodules = [:external]
#Here you can configure each submodule's features.
Rails.application.config.sorcery.configure do |config|
(中略)
# -- external -- 78行目辺り
# What providers are supported by this app
# i.e. [:twitter, :facebook, :github, :linkedin, :xing, :google, :liveid, :salesforce, :slack, :line].
# Default: `[]`
config.external_providers = %i[line]
(中略) # 223行目辺り
config.line.key = Rails.application.credentials.dig(:line, :channel_id)
config.line.secret = Rails.application.credentials.dig(:line, :channel_secret)
config.line.callback_url = 'http://localhost:3000/oauth/callback?provider=line'
config.line.scope = 'profile'
# config.line.bot_prompt = "normal"
config.line.user_info_mapping = {name: 'displayName', email: 'userId'}
(以下略)
# -- external --
user.authentications_class = Authentication
end
end
config.line.user_info_mapping
…名前通り、line認証を通して取得する情報(user_info)を、アプリ側でどのパラメータとして扱うか(mapping)の設定。
callback_urlの設定
config.line.callback_url
…コールバックURLを設定。
開発・本番環境で違う設定が必要です。
GoogleやTwitterの認証と違い、LINEのチャネルにはコールバックURLを一つしか登録できないため、
確認したい環境に合わせて都度変更する必要があります。
# 開発環境
+ config.line.callback_url = 'http://localhost:3000/oauth/callback?provider=line'
# 本番環境
+ config.line.callback_url = 'https://本番環境のドメイン/oauth/callback?provider=line'
参考にした記事の通りにできなかったので、sorcery.rbに直接書き込む形にしました。
キーの設定
config.line.key…作成したプロバイダー(チャネル)のチャネルIDを設定
config.line.secret…作成したプロバイダー(チャネル)のチャネルシークレットを設定
line:
channel_id: チャネルidの値
channel_secret: チャネルシークレットの値
LINE DevelopersのコールバックURLの設定
下記を記載。
# 開発環境
http://localhost:3000/oauth/callback
# 本番環境
http://本番環境のドメイン/oauth/callback
ユーザー認証との紐付け
class User < ActiveRecord::Base
+ has_many :authentications, :dependent => :destroy
+ accepts_nested_attributes_for :authentications
end
class Authentication < ActiveRecord::Base
belongs_to :user
end
OauthsControllerの作成
認証を処理するためのコントローラーを作成します。
class OauthsController < ApplicationController
skip_before_action :require_login, raise: false
# sends the user on a trip to the provider,
# and after authorizing there back to the callback url.
def oauth
login_at(params[:provider])
end
def callback
provider = params[:provider]
if @user = login_from(provider)
redirect_to root_path, :notice => "Logged in from #{provider.titleize}!"
else
begin
@user = create_from(provider)
# NOTE: this is the place to add '@user.activate!' if you are using user_activation submodule
reset_session # protect from session fixation attack
auto_login(@user)
redirect_to root_path, :notice => "Logged in from #{provider.titleize}!"
rescue
redirect_to root_path, :alert => "Failed to login from #{provider.titleize}!"
end
end
end
#example for Rails 4: add private method below and use "auth_params[:provider]" in place of
#"params[:provider] above.
# private
# def auth_params
# params.permit(:code, :provider)
# end
end
viewへの表示
自身のルーティングを確認して記載してください。
<%= link_to 'Login with Line', oauths_oauth_path(:provider => :line) %>
ngrokを使ってローカル環境をhttpsで公開する
コールバックURLにhttp://localhost:3000
などのURLは使えません。
そのため、ngrokを使ってローカルで立ち上げたウェブアプリケーションを外部に公開します。
ファイルをダウンロード
ngrokのサイトでユーザー登録を行い、バイナリファイルをダウンロードします。
今回は手動でngrokをダウンロードして解凍する方法で行うので、brew install ngrok/ngrok/ngrok
は必要ありません。
# intel macの方
unzip ~/Downloads/ngrok-v3-stable-darwin-amd64.zip
# apple siliconの方
unzip ~/Downloads/ngrok-v3-stable-darwin.zip
次のコマンドを実行して、認証トークンを追加します。
./ngrok config add-authtoken xxxxxxxxxxxxxxxxxxxxxxxx(あなたのauthtoken)
アプリをオンラインで開く
config/environments/development.rb に下記を記載し、hostを追加すれば動作できます。
許可したいホスト名には xxxxxxxx.ngrok.io の部分を追加してください。(httpsなどの部分は不要です。)
Rails.application.configure do
+ config.hosts << "許可したいホスト名"
end
うまくいかない場合や許可したいホスト名を何度も書きかえるのが面倒な人は下記のやり方を行ってみてください。
Rails.application.configure do
+ config.hosts.clear
end
アプリを一時ドメインでオンラインにするためにサービスに転送します。
./ngrok http 3000
下記のように表示されます。
ngrok
K8s Gateway API support available now: https://ngrok.com/r/k8sgb
Session Status online
Account (名前)
Version 3.8.0
Region Japan (jp)
Latency 32ms
Web Interface http://XXXX:XXXX
Forwarding https://XXXXXXXXXXXXXX.ngrok-free.app -> http://localhost:3000
Connections ttl opn rt1 rt5 p50 p90
0 0 0.00 0.00 0.00 0.00
うまくいかないとき
400 Bad Request と表示される。
LINEでログインのボタンを押した後にエラー。
./ngrok http 3000
の画面上で
HTTP Requests
-------------
GET / 403 Forbidden
403(Forbidden)エラー。
LINEの名前が反映されなかった。
私はLINEログイン機能を実装してから、名前(displayName)が反映されるように行いました。
しかし、名前は変更されませんでした。
解決策として、そのuser_idを一度削除してから再度ログインを行うと正しく反映させることができました。
最後に
最後まで読んでいただいてありがとうございました。
不備等ありましたらコメント等お願いいたします。
Discussion