0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RailsでDiscord認証を実装してみよう

0
Posted at

自己紹介

みなさん、こんにちは!
FBC生のzecky(ぜっきー)と申します。
現在、自作サービス開発中しておりその中でDiscordのログイン認証について自分が実装したコードをまとめてみたいと思い、ここに記します。
(これまでブログを書こう書こうと思い、3年も経ってしまいました😰)

はじめに

この記事ではDiscordとRailsでOAuthを利用して認証を実施したときの記録です。

バージョン

  • Ruby 4.0.1
  • Rails 8.1.3
  • omniauth 2.1.4
  • omniauth-discord 1.2.0
  • omniauth-rails-csrf_protection 2.0.1
  • discordrb 3.7.2

Gemのインストール

gem 'omniauth'
gem 'omniauth-discord'
gem 'omniauth-rails_csrf_protection'
gem 'discordrb'

ルーティングの設定

Rails.application.routes.draw do
  root "home#index"
  get 'auth/:provider/callback', to: 'sessions#create'
  get 'auth/failure', to: redirect('/')
  get 'logout', to: 'sessions#destroy', as: 'logout'

  resources :sessions, only: %i[create destroy]
  resources :users, only: %i[index show]
end

Discord Developper Portalで設定を行う

  1. こちらのURLにてアクセスします
  2. 次にアプリケーションの「新しいアプリケーション」をクリックし名前を決めて作ります!!
  3. 「OAuth2」という画面で「クライアントID」「クライアントシークレット」を取得できますスクリーンショット 2026-10-19 21.06.31.png
  4. $EDITOR=vim bin/rails credentials:edit -e developmentで開きます
discord:
  client_id: クライアントID
  client_secret: クライアントシークレット

5.リダイレクトの設定を行いますスクリーンショット 2026-10-19 21.22.04.png
http://127.0.0.1:3000/auth/discord/callbackで設定します。

設定ファイル

今回登録しているのはDisocrdのuidなのでscope: 'identify'と記述します。

provider :discord,
  Rails.application.credentials.discord[:client_id],
  Rails.application.credentials.discord[:client_secret],
  scope: 'identify'

その下に下記を記載しました。

...
OmniAuth.config.on_failure = proc { |_env| [ 302, { 'Location' => '/auth/failure', 'Content-Type' => 'text/html' }, [] ] }

OmniAuthの認証処理が失敗したときに実行される設定です.
簡単に言うと、「OmniAuthの認証に失敗したら、/auth/failureというURLにリダイレクトする」という意味になります。

Model編

rails g model Userで生成します。

def self.find_or_create_from_discord_auth(discord_auth)
  find_or_create_by(uid: discord_auth.uid) do |user|
    user.update(
      name: discord_auth.info.name,
      nickname: discord_auth.extra.raw_info.global_name,
      avatar_url: discord_auth.info.image || default_avatar(discord_auth.uid),
      uid: discord_auth.uid,
      provider: discord_auth.provider
    )
  end
end

def self.default_avatar(uid)
  index = (uid.to_i >> 22) % 6
  "#{Discordrb::API.cdn_url}/embed/avatars/#{index}.png"
end

find_or_create_byメソッドはもしユーザーがいなければ作って、ユーザーが存在していればfindするという便利なメソッドですね〜🤗
default_avatarはDiscordのアイコンが設定せずデフォルトだった場合表示させるメソッドです。

Controller編

rails g controller Userで生成します。

class UsersController < ApplicationController
  def show
    @user = User.find(params[:id])
  end
end

rails g controller Sessionで生成します。

class SessionsController < ApplicationController
  skip_before_action :check_logged_in, only: :create

  def create
    if (user = User.find_or_create_from_discord_auth(discord_auth))
      reset_session
      login user
    end
    redirect_to root_path, notice: 'ログインしました'
  end

  def destroy
    logout
    redirect_to root_path, notice: 'ログアウトしました'
  end

  private

  def discord_auth
    request.env['omniauth.auth']
  end
end

Views編

<!DOCTYPE html>
<html>
...省略
  <body>
  <% if flash[:notice] %>
    <%= notice %>
  <% end %>
  <header>
    <%= link_to "トップページ", root_path %>
    <% if current_user %>
      <%= image_tag current_user.avatar_url %>
      <%= link_to "#{user_name(current_user)}", user_path(current_user) %> |
      <%= link_to "ログアウト", logout_path %>
    <% else %>
      ゲストさん
      <%= button_to "discordでログイン", "/auth/discord", method: :post, data: { turbo: false } %>
    <% end %>
  </header>
    <%= yield %>
  </body>
</html>

ログインが成功するとDiscordで設定した名前やニックネーム、アバター画像が表示される。
スクリーンショット 2026-10-19 22.05.10.png

おまけ

実装後、数日経ったのちローカルホストを立ち上げ、ログインしてみると
スクリーンショット 2026-10-18 21.42.48.png

OAuth2 redirect_uriが無効ですと出ました💦
多分こういう事象に遭われた方がいらっしゃると思います。

実はこれDiscordのDevelopper Portalで設定したOAuth2のリダイレクトに記載されているドメインでなければいけないのです。
スクリーンショット 2026-10-18 21.48.41.png

エラー画面が出たURLのドメインはhttp://localhost:3000でした。
登録したのは127.0.0.1:3000なのでこれでアクセスしなければなりませんでした。😳

参考サイト

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?