自己紹介
みなさん、こんにちは!
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で設定を行う
- こちらのURLにてアクセスします
- 次にアプリケーションの「新しいアプリケーション」をクリックし名前を決めて作ります!!
- 「OAuth2」という画面で「クライアントID」「クライアントシークレット」を取得できます
-
$EDITOR=vim bin/rails credentials:edit -e developmentで開きます
discord:
client_id: クライアントID
client_secret: クライアントシークレット
5.リダイレクトの設定を行います
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で設定した名前やニックネーム、アバター画像が表示される。

おまけ
実装後、数日経ったのちローカルホストを立ち上げ、ログインしてみると

OAuth2 redirect_uriが無効ですと出ました💦
多分こういう事象に遭われた方がいらっしゃると思います。
実はこれDiscordのDevelopper Portalで設定したOAuth2のリダイレクトに記載されているドメインでなければいけないのです。

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