シュッと開発日記

学んだことのアウトプット。ポートフォリオ作ってます。

OmniAuthでTwitterのプロフ画像を取得する

OmniAuthでTwitterのログインを実装する記事なんかはたくさんあるのですが、 Twitterアバター画像をOmniAuth経由で取得する記事はあまりなかったので書いていきたいと思います。

前提

前提として、OmniAuthを通じてログインができる状態を作っておきます。 私は以下の記事を参考に実装しました。

画像アップロードにはActive Storageを使用しています

実装

ログイン機能ができたら、早速画像の取得も実装していきます。

# app/controllers/users/omniauth_callbacks_controller.rb

  def twitter
    callback_from :twitter
  end

  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
      session[:user_id] = @user.id

    else
      session["devise.#{provider}_data"] = request.env['omniauth.auth']
      redirect_to new_user_registration_url
    end
  end


# app/models/user.rb

class << self
    def find_for_oauth(auth)
      provider = auth[:provider]
      uid = auth[:uid]
      user_name = auth[:info][:name]
      image_url = auth[:info][:image]
      uri = URI.parse(image_url) # パースする必要がある
      image = uri.open
      email = User.dummy_email(auth)
      password = Devise.friendly_token[0, 20]

      find_or_create_by(provider: provider, uid: uid) do |user|
        user.name = user_name
        user.email = email
        user.password = password
        user.avatar.attach(io: image, filename: "#{user.name}_profile.png")
      end
    end
  end

# app/config/initializers/devise.rb

Devise.setup do |config|
  config.omniauth :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET'], :image_size => 'original'

  • TwitterAPIからの情報を取得(ここで画像のURLも取得)
  • URLをパースしてimageに挿入
  • 一意の値になるproviderとuidの組み合わせでユーザーがいるか確認し、いなければユーザーを作る(この中で画像をアバターとしてアタッチする)

というような流れになっています。

ポイント

ポイントは

  • 画像URL等を直で叩く場合は、parseしなければならない
  • Twitterのデフォルトの画像サイズではかなり小さいため、画像サイズを設定しなければならない

の2点です。

画像のパース

image_url = auth[:info][:image]
uri = URI.parse(image_url) # パースする必要がある
image = uri.open

の部分を

image_url = auth[:info][:image]
image = open(image_url)

としてしまうと 下記のように、コマンドラインで直接コマンドを叩かれてしまう可能性があります。 open('|/bin/sleep 20;').read #20秒停止するコマンド

Twitterの画像のサイズの設定

image_urlで取得できるurlにある画像は_normalというサフィックス(?)がついていてかなり小さいです。 (000000000000000000_normal.jpgのような感じ)

そのため、オリジナル(設定された時の大きさ)で取得するには app/config/initializers/devise.rbのなかで、

Devise.setup do |config|
  config.omniauth :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET'], :image_size => 'original'

とする必要があります。

これで、Twitterでログイン時にアイコンが取得できるようになりました。

参考