2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

deviseを利用してRailsアプリにLINE連携ログインを導入する

Posted at

初めに

初学者です。

個人開発でRailsアプリにLINE連携ログインを導入した際の記録です。

アプリでLINEBOTと合わせてLINE連携ログインを利用したかったので導入しました。
deviseを使用して実装しています。

この記事で行なっている作業はこちらの記事で構築した環境で実施しています。
https://qiita.com/tkhero555/items/a1811369c59021077d62

アプリ「Puri.log」はこちら(2024/5/3時点でMVPリリース状態)
https://purilog-2a85943c9f18.herokuapp.com/

技術構成とバージョン

カテゴリ 技術
フロントエンド javascript/Hotwire/bootstrap 
バックエンド ruby3.3.0/rails7.1.3.2
データベース PostgreSQL16.2
認証 devise
環境構築 Docker / docker-compose
CI/CD Github Actions
インフラ  heroku

deviseの導入と初期設定

gem 'devise'を導入する。

gem 'devise'

バンドルインストールした後、deviseを実行して必要なファイルを作る。

docker compose run web bundle install
docker compose run web rails g devise:install
docker compose run web rails g devise User

生成されるマイグレーションファイルを確認してnameカラムを追加する。

# frozen_string_literal: true

class DeviseCreateUsers < ActiveRecord::Migration[7.1]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :name
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      # t.integer  :sign_in_count, default: 0, null: false
      # t.datetime :current_sign_in_at
      # t.datetime :last_sign_in_at
      # t.string   :current_sign_in_ip
      # t.string   :last_sign_in_ip

      ## Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at


      t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end
end

db:migrateする。

LINEとdeviseを連携する

LINE developersでLINEログインの新しいチャネルを作成しておく。

gem 'omniauth-line'を導入する。

gem 'omniauth-line'
gem 'omniauth-rails_csrf_protection'

バンドルインストールとビルドする。

.envファイルにLINEログイン用の環境変数を追加する。

.env
# LineBotで使用したチャンネルシークレットとトークン
LINE_CHANNEL_SECRET="LINEBOT用のチャネルのsecret"
LINE_CHANNEL_TOKEN="LINEBOT用のチャネルのトークン"

# 今回設定するチャンネルIDとシークレット
LINE_LOGIN_KEY='LINEログイン用チャネルのChannel ID'
LINE_LOGIN_SECRET='LINEログイン用チャネルのChannel Secret'

config/initializers/devise.rbで接続するLINEチャネルのIDとシークレットをENVを利用して設定する。

config/initializers/devise.rb
config.omniauth :line, ENV['LINE_LOGIN_KEY'], ENV['LINE_LOGIN_SECRET']

User.rbにomniauthの記述を追加する。

user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :omniauthable, omniauth_providers: %i[line] # この1行を追加
end

omniauth_collbacks_controllerを作成する。

docker compose run web rails g controller omniauth_callbacks
omniauth_callbacks_controller.rb
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
  
  def line
    basic_action
  end

  private
  
  def basic_action
	  # 認証情報を取得
    @omniauth = request.env["omniauth.auth"]
    # 認証情報が存在している場合
    if @omniauth.present?
	    # 認証情報のproviderとuidを元に、ユーザーを発見もしくは初期化する。
      @profile = User.find_or_initialize_by(provider: @omniauth["provider"], uid: @omniauth["uid"])
      # 保存したユーザー情報のemailが空白なら
      if @profile.email.blank?
	      # 三項演算子 認証情報の[info][email]が存在する場合その値を代入 そうでない場合認証情報の中身を使って、一意のダミーemailアドレスを作っている
        email = @omniauth["info"]["email"] ? @omniauth["info"]["email"] : "#{@omniauth["uid"]}-#{@omniauth["provider"]}@example.com"
        # current_userが存在するならそのまま代入、しないならその場で認証情報から新しいユーザーを作成している。
        @profile = current_user || User.create!(provider: @omniauth["provider"], uid: @omniauth["uid"], email: email, name: @omniauth["info"]["name"], password: Devise.friendly_token[0, 20])
      end
      # set_values(@omniauth)はuserモデルで定義されたメソッド
      @profile.set_values(@omniauth)
      # ログイン動作を実施する
      sign_in(:user, @profile)
    end
    #ログイン後のflash messageとリダイレクト先を設定
    flash[:notice] = "ログインしました"
    # ここのリダイレクト先は後で自分のルーティングに応じて変更する
    redirect_to expendable_items_path
  end

	# ダミーのemailアドレスを作成するメソッド
  def fake_email(uid, provider)
    "#{auth.uid}-#{auth.provider}@example.com"
  end
end

ルーティングを設定する

devise_for :users, controllers: {
  omniauth_callbacks: "omniauth_callbacks"
}

UserモデルにLINEログイン用のカラムを追加する。

docker compose run web rails g migration add_column_to_users
class ChangeColumnToUser < ActiveRecord::Migration[6.0]
  def change
    add_column :users, :provider, :string
    add_column :users, :uid, :string
  end
end

Userモデルにメソッドを追加する。

user.rb
# social_profilesの中身を順番に取り出して、指定したproviderと一致する最初のsocial_profileを返す
	def social_profile(provider)
    social_profiles.select { |sp| sp.provider == provider.to_s }.first
  end
	
	# omniauthから受け取った情報で、インスタンスの属性を設定する。
  def set_values(omniauth)
	  # omniauthのproviderとuidのどちらかが既存の値と異なる場合、この時点でreturnしてメソッドを終了する。
    return if provider.to_s != omniauth["provider"].to_s || uid != omniauth["uid"]
    # omniauthのcredentialsを取り出す
    credentials = omniauth["credentials"]
    # omniauthのinfoを取り出す
    info = omniauth["info"]
		
		# さっき取り出したcredentialsからrefresh_tokenを取り出す
    access_token = credentials["refresh_token"]
    # さっき取り出したcredentialsからsecretを取り出す
    access_secret = credentials["secret"]
    # 最後にcredentialsをjson化しておく
    credentials = credentials.to_json
    # さっき取り出したinfoからnameを取り出す
    name = info["name"]
  end
	
	# 引数で受け取ったraw_infoをjson化してインスタンスのraw_infoに格納する
  def set_values_by_raw_info(raw_info)
    self.raw_info = raw_info.to_json
    self.save!
  end

LINE developersでコールバックのurlを設定する

ngrokを起動して外部からローカルサーバーにアクセスできるURLを確保

ngrokの導入と設定はこちらの記事で実施済み
https://qiita.com/tkhero555/items/4af4c7cd48a757974685

ngrok http 3000

ルーティングを確認して、ngrokのurl + omniauth_callbacks_controllerのlineアクションのルーティングをLINEログインのwebhookに設定する。

上手く行っていればdeviseのloginページにSign in with Lineのボタンができており、クリックするとLINE連携ログイン画面へ遷移するようになっている。
スクリーンショット 2024-04-08 20.56.40.png

参考記事等

https://qiita.com/prg_mt/items/b3238ebfae1a3df67cab
https://zenn.dev/yoiyoicho/articles/974c73ac75c100

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?