3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Rails8でLINEログイン実装時に遭遇した2つのエラーと解決方法

Last updated at Posted at 2025-10-23

1. はじめに

Rails8でLINEログイン機能を実装する際に遭遇したエラーと解決方法を記録します。
うまく動かない...という方の参考になれば幸いです。

経緯

既存のomniauth-line gemを調べてみたところ、長期間更新されておらず Rails8での動作に不安があったため、今回は独自のOmniAuth strategyを作成してLINEログインを実装する方法を選択しました。
実装については下記の記事を元に実装しました。

開発環境
・Ruby 3.3.6
・Rails 8.0.2.1
・ 認証: Devise
・Docker(開発環境)
・DB: PostgreSQL
・画像管理: Cloudinary
・デプロイ: Render / Neon

実際の実装内容

Gemfile
# LINEログイン
gem 'omniauth'
gem 'omniauth-oauth2'
gem 'omniauth-rails_csrf_protection'
lib/omni_auth/strategies/line.rb(クリックで展開)
lib/omni_auth/strategies/line.rb
require 'omniauth-oauth2'

module OmniAuth
  module Strategies
    class Line < OmniAuth::Strategies::OAuth2
      # プロバイダー名
      option :name, 'line'

      # IDトークン, プロフィール情報, メールアドレスの取得権限を含める
      option :scope, 'openid profile email'

      # LINEのAPIエンドポイント設定
      option :client_options, {
        site: 'https://api.line.me',
        authorize_url: 'https://access.line.me/oauth2/v2.1/authorize',
        token_url: 'https://api.line.me/oauth2/v2.1/token'
      }

      # LINEユーザーIDをuidとして設定
      uid { raw_info['sub'] }

      # ユーザー情報を設定
      info do
        {
          name: raw_info['name'],
          email: raw_info['email']
        }
      end

      # 追加情報(デバッグ用)
      extra do
        {
          raw_info: raw_info
        }
      end

      def raw_info
        @raw_info ||= verify_id_token
      end

      private

      # ID Tokenに必須のnonceをパラメータに追加
      def authorize_params
        super.tap do |params|
          params[:nonce] = SecureRandom.uuid
          session['omniauth.nonce'] = params[:nonce]
        end
      end

      # callback_urlのクエリパラメータを除去
      def callback_url
        full_host + callback_path
      end

      # ID token検証 & ユーザ情報取得
      def verify_id_token
        @id_token_payload ||= begin
          # HTTPクライアントを使用してID Token検証
          response = client.request(:post, 'https://api.line.me/oauth2/v2.1/verify', {
            body: {
              id_token: access_token['id_token'],
              client_id: options.client_id,
              nonce: session.delete('omniauth.nonce')
            }
          })
          
          response.parsed
        rescue => e
          Rails.logger.error "[LINE Login] ID token verification failed: #{e.message}"
          Rails.error.report(e, context: {
            action: '[LINE login] ID token verification & get user info',
            client_id: options.client_id,
            has_id_token: access_token['id_token'].present?
          }) if defined?(Rails.error)
          raise
        end
      end
    end
  end
end
app/models/user.rb 追加(クリックで展開)
app/models/user.rb
 def self.from_omniauth(auth, current_user = nil)
    # ログイン済みユーザーがLINE連携を追加する場合
    return link_line_account(auth, current_user) if current_user && !current_user.line_connected?

    # 既存のLINEユーザーでログインまたは新規ユーザー作成
    sign_in_or_create_user_from_line(auth)
  end

  # 既存ユーザーにLINE連携を追加
  def self.link_line_account(auth, current_user)
    # 他のユーザーが既にこのLINEアカウントを使用していないかチェック
    return nil if exists?(provider: auth.provider, uid: auth.uid)

    success = current_user.update(
      provider: auth.provider,
      uid: auth.uid,
      line_notify: true
    )

    success ? current_user : nil
  end

  # LINEログインまたは新規ユーザー作成
  def self.sign_in_or_create_user_from_line(auth)
    find_or_create_by(
      provider: auth.provider,
      uid: auth.uid
    ) do |user|
      user.email = auth.info.email || "#{auth.uid}@line.example.com"
      user.name = auth.info.name || "LINE User"
      user.password = Devise.friendly_token[0, 20]
      user.line_notify = true
    end
  end
app/controllers/users/omniauth_callbacks_controller.rb(クリックで展開)
app/controllers/users/omniauth_callbacks_controller.rb
 module Users
  class OmniauthCallbacksController < Devise::OmniauthCallbacksController
    skip_before_action :verify_authenticity_token, only: :line

    def line
      @user = User.from_omniauth(request.env['omniauth.auth'], current_user)


      notify_line_already_linked and return if current_user && @user.nil?

      if @user.persisted?
        complete_line_login
      else
        fail_line_login
      end
    end

    private

    def notify_line_already_linked
      redirect_to user_setting_path
      set_flash_message(:alert, :failure, kind: 'LINE', reason: '他アカウントでLINE連携済みです')
    end

    def complete_line_login
      sign_in_and_redirect @user, event: :authentication
      set_flash_message(:notice, :success, kind: 'LINE')
    end

    def fail_line_login
      session['devise.line_data'] = request.env['omniauth.auth'].except(:extra)
      redirect_to new_user_registration_url
      set_flash_message(:alert, :failure, kind: 'LINE', reason: 'LINE連携に失敗しました')
    end
  end
end
.env
LINE_CHANNEL_ID=チャネルID
LINE_CHANNEL_SECRET=チャネルシークレット
migrate
class AddOmniauthToUsers < ActiveRecord::Migration[8.0]
  def change
    add_column :users, :provider, :string
    add_column :users, :uid, :string

    # 重複しないように
    add_index :users, [:provider, :uid], unique: true
  end
end
config/initializers/devise.rb
# 下記の内容を追加
require Rails.root.join('lib/omni_auth/strategies/line')
...
config.omniauth :line, ENV['LINE_CHANNEL_ID'], ENV['LINE_CHANNEL_SECRET']

【エラー1】 本番環境でのZeitwerkエラー

エラー内容

ローカル環境では正常に動作するが、Renderへのデプロイ時に以下のエラーが発生:

/opt/render/project/.gems/ruby/3.3.0/gems/zeitwerk-2.7.3/lib/zeitwerk/cref.rb:62:in `const_get': uninitialized constant Omniauth::Strategies::Line (NameError)

原因

Rails8の「Zeitwerk」が、自作したlib/omniauth/strategies/line.rb を正しく読み込めていなかった。

Zeitwerkの命名規則:
・OmniAuth → omni_auth (スネークケース)
・omniauth だと Omniauth クラスを期待してしまう
・Rails8ではこの規則がより厳格に適用される

解決方法

- lib/omniauth/strategies/line.rb
+ lib/omni_auth/strategies/line.rb

これによりRails8 の Zeitwerk がモジュール名 OmniAuthを探せてエラーが解消

【エラー2】 コールバック時の404エラー

エラー内容

LINEログイン後のコールバック処理で以下のエラーが発生:

[77d87eba-2df9-4c5f-8e76-1659254d9613] Processing by Users::OmniauthCallbacksController#passthru as HTML
[77d87eba-2df9-4c5f-8e76-1659254d9613] Completed 404 Not Found in 1ms

スクリーンショット 2025-10-22 10.46.19.png

エラーの症状

  1. LINEログインボタンをクリック → 404エラー
  2. ログを見ると #passthru アクションが呼ばれている

エラーの原因分析

#passthru が呼ばれるということは、
OmniAuth がコールバックリクエストを受け付けていない ということ。

OmniAuth 2.x で導入された allowed_request_methods の制限

  • デフォルトで POST のみ許可
  • LINE のコールバックは GET を利用するため 404 になる

参考リンク
https://stackoverflow.com/questions/65995219/omniauth-isnt-catching-the-initial-get-auth-provider-request?utm_source=chatgpt.com

4. 解決方法

config/initializers/omniauth.rb
# 追加 ファイルがない場合作成要
Rails.application.config.middleware.use OmniAuth::Builder do
  OmniAuth.config.allowed_request_methods = [:post, :get]
end

これにより、Rails のミドルウェアに OmniAuth を追加して、明示的にgetリクエストを許可し、エラー解消

まとめ

Rails8 でOmniAuth strategyを作成してLINEログインを実装する方法についての参考記事が少ないので、今回振り返りも含めて記事にしました

3
3
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
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?