MyFirstRails

Mastodonログイン サンプル

概要

Railsにこれから初めて触れる方を対象にしたチュートリアルです

RailsにMastodonでのログイン機能を実装するチュートリアルになります

チュートリアル

アプリのひな型を作る

まず、rails newを実行し、アプリのひな型を作成します

rails new mastodon_login

次に、作成したアプリのディレクトリへと移動します

cd mastodon_login

Deviseの導入

Twitterでのログイン機能を実装するにあたって、Deviseを使用します まず、Gemfilegem 'devise'を追加してbundle installを実行します

gem 'devise'
bundle install

この時、sqlite3がインストールできないエラーが発生するかもしれません その場合は以下のようにsqlite3のバージョンを修正してbundle installを実行してください

gem 'sqlite3', '1.3.13'
bundle install

bundle install後、以下のコマンドを実行してDeviseをインストールします

rails g devise:install

次に、Deviseで使用するViewファイルを作成します

rails g devise:views

そして、Deviseで使用するModelを作成し、マイグレーションを実行します

rails g devise user
rails db:migrate

これでDeviseの導入は完了です!

Mastodonにアプリを作成

Mastodonでのログインを実装するためには、Mastodonへアプリケーションの登録が必要になります

自分のアカウントがあるMastoonインスタンスにてユーザー設定をクリックし、開発という項目をクリックします。 新規アプリをクリックし、アプリ名を入力の上送信をクリックします。

その後、作成したアプリをクリックするとクライアントキーシークレットキーを取得できます。 この二つは後々で使いますのでわかるようにメモしておきます(ただし、第三者とは絶対に共有しないでください!)

Dotenvの導入

Mastodonから取得したクライアントキーシークレットキーをソースコードにそのまま貼り付けてしまうと悪意のある第三者に利用されてしまう可能性があります 実際に、発生した事例としては以下のようなものがあります

AWSが不正利用され300万円の請求が届いてから免除までの一部始終

Peing脆弱性案件に見る初動のまずさ

こういったことを回避するためにもDotenvなどを使用してソースコードに直接書かないようにする必要があります

まず、Gemfilegem 'dotenv-rails'を追加します

gem 'dotenv-rails'

その後、bundle installを実行します

bundle install

そして、先ほど取得したキーなどを.envに書き込みます .envGemfileと同じ位置に作成します

# Using Mastodon API
MASTODON_CLIENT_KEY=`クライアントキー`
MASTODON_SECRET_KEY=`シークレットキー`

最後に、.gitignoreを編集し、.envGitの管理対象から外します

# See https://help.github.com/articles/ignoring-files for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
#   git config --global core.excludesfile '~/.gitignore_global'

# Ignore bundler config.
/.bundle

# Ignore the default SQLite database.
/db/*.sqlite3
/db/*.sqlite3-journal

# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep

# Ignore uploaded files in development
/storage/*
!/storage/.keep

/node_modules
/yarn-error.log

/public/assets
.byebug_history

# Ignore master key for decrypting credentials and more.
/config/master.key
.env

これでDotenvの導入は完了です!

Mastodonログインの実装

Mastodonアカウントでのログイン機能はOauthという認証を使用します

まず、必要なgemGemfileに追加します

gem 'omniauth'
gem 'omniauth-mastodon'
gem 'mastodon-api', require: 'mastodon'

bundle installgemをインストールします

bundle install

Userモデルにカラムを追加してマイグレーションを行います

rails g migration AddColumnsToUsers uid:string provider:string
rails db:migrate

次に、Mastodonのドメイン情報などを記憶するモデルMastodonClientを以下のコマンドで作成します。

rails generate model MastodonClient domain:string client_id:string client_secret:string 

config/initializers/devise.rbを編集してDevise側の設定を変更します

Devise.setup do |config|

  #<省略>

  # ==> OmniAuth
  # Add a new OmniAuth provider. Check the wiki for more information on setting
  # up on your models and hooks.
  # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'

  config.omniauth :mastodon, ENV['MASTODON_CLIENT_KEY'], ENV['MASTODON_SECRET_KEY']

  config.omniauth :mastodon, scope: 'read follow', credentials: lambda { |domain, callback_url|
    client = MastodonClient.where(domain: domain).first_or_initialize(domain: domain)

    return [client.client_id, client.client_secret] unless client.new_record?

    new_client = Mastodon::REST::Client.new(base_url: "https://#{domain}").create_app('MastodonLoginSample', callback_url, 'read follow')

    client.client_id = new_client.client_id
    client.client_secret = new_client.client_secret
    client.save

    [client.client_id, client.client_secret]
  }

 #<以下省略>
end

Dotenv経由でMastodonのクライアントキーなどを読み取っています

その後、Userモデルに:omniauthableを追加します

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :omniauthable
end

その後、self.find_for_oauth(auth)というメソッドを追加します

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :omniauthable

  def self.find_for_oauth(auth)
    user = User.where(uid: auth.uid, provider: auth.provider).first

    unless user
      user = User.create(
        uid:      auth.uid,
        provider: auth.provider,
        email:    User.dummy_email(auth),
        password: Devise.friendly_token[0, 20]
      )
      user.save!
    end
    current_user = user
  end

  private

    def self.dummy_email(auth)
      "#{auth.uid}"
    end
end

このメソッドにより、アカウントが既に作成されているかをチェックし、アカウントがない場合は新しく作成することができるようになります

app/controllers/users/omniauth_callbacks_controller.rbというコールバック処理を行うコントローラーを作成します

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def mastodon
    callback_from :mastodon
  end

  private

  def callback_from(provider)
    provider = provider.to_s

    @user = User.find_for_oauth(request.env['omniauth.auth'])

    if @user.persisted?
      flash[:notice] = I18n.t('devise.omniauth_callbacks.success', kind: provider.capitalize)
      sign_in_and_redirect @user, event: :authentication
    else
      session["devise.#{provider}_data"] = request.env['omniauth.auth']
      redirect_to new_user_registration_url
    end
  end
end

最後に、config/routes.rbにコールバック先のルーティングを追加します

Rails.application.routes.draw do
  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
end

これでTwitterでのログイン機能は実装できました!

静的なページの作成

最後に、Mastodonログインが実際に機能しているかどうかを確認するためのページを作成します

rails g controller web index

app/views/web/index.html.erbにTwitterログインのリンクなどを追加します

<h1>Web#index</h1>
<p>Find me in app/views/web/index.html.erb</p>

<%= link_to 'Mastodon Login', user_mastodon_omniauth_authorize_path %>

<% if user_signed_in? %>
    Your Welcome!
<% end %>

また、config/routes.rbを以下のように編集します

Rails.application.routes.draw do
  root 'web#index'
  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
end

Mastodon Loginをクリックしてログインできるようになっています また、ログインするとYour Welcome!の文字が画面に表示されるようになっています

実際にログインしてみよう

rails sでローカルサーバを起動し、localhost:3000にアクセスします

その後、Mastodon LoginのリンクをクリックするとMastodonのアプリ認証の画面が表示されます

認証後、localhost:3000Your Welcome!と表示されていればOKです!