Mt.Log

編入、編入後の勉強

RailsのOmniAuthでSpotifyの認証をする

はじめに

OmniAuthでTwitterFaceBookにログインすることができますが今回Spotifyを使うことになったので調べてみました。
OmniAuthを使ったログイン機能の実装に関する記事はTwitterは多くありますが、Spotifyはなかったのでメモっておきます。
とはいえ、ほとんどTwitter認証と同じです。

どうやらSpotifyにもOmniAuthのGemがあるようなので使ってみます。

Spotify for DeveloperでAppの作成

まず、SpotifyでAppを作成します。
下記サイトにとんで、DashboardからAppの作成をしてください。
developer.spotify.com

作成後、EDIT SETTINGSから
Website : http://127.0.0.1:3000
Redirect URI'S : http://127.0.0.1:3000/auth/spotify/callback
を追加します。
Twitterの場合はlocalhostで作成できなかったので上のURIで作成します。

[Client ID]と[Client Secret]が作成されるのでメモっておきましょう。

KEYの保存

では、アプリを作成してKEYを保存します。
先ほど作成したIDやSecretはコントローラーやモデル内に書くべきではないのでcredentialsに書き込んでいきます。
Rails5.2からsecret.ymlがなくなってcredentialsになったみたいです。このサイトを参考にしました。
Rails5.2から追加された credentials.yml.enc のキホン

エディターはEmacsに設定します。(Atomはなぜかうまく表示されないのでViかEmacsを推奨)

$ echo 'export EDITOR="emacs"' >> ~/.bash_profile
$ source ~/.bash_profile
$ echo $EDITOR
  #=> emacs

これで毎回エディタを選択する必要がなくなります。

$ bin/rails credentials:edit

これにKEYを追加していきます。

# aws:
#   access_key_id: 123
#   secret_access_key: 345

client_key: [Your ID]
client_secret: [Your Secret ID]

# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: 8be8e637d755f79c799048bed8be0c...

これには

Rails.application.credentials.[hogehoge]

で値を取れます。

OmniAuthの設定

config/initializer/omniauth.rbを作成し、先程のKEYをOmniAuthに登録します。

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :spotify,
     Rails.application.credentials.client_id,
     Rails.application.credentials.client_secret,
     scope: 'playlist-read-private user-read-private user-read-email'
end

ログイン機能の作成

まず、ユーザーモデルを作成します。

$ rails g model user provider:string uid:string nickname:string image_url:string
$ rails db:migrate

ログイン機能のためのビューを書きます。
app/view/layout/application.html.erb

    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav navbar-right">
        <li><%= link_to 'Spotifyでログイン', '/auth/spotify/' %></li>
      </ul>
    </div>
    <div class="container">
      <% if flash[:notice] %>
        <div class="alert alert-success">
          <%= flash[:notice] %>
        </div>
      <% end %>
      <%= yield %>
    </div>

コントローラーを作成します。

$ rails g controller sessions top

コントローラーに書いていきます。
app/controllers/sessions_controller.rb

class SessionsController < ApplicationController
  def top
  end

  def create
    user = Spotifyuser.find_or_create_from_auth_hash(request.env['omniauth.auth'])
    session[:user_id] = user.id
    redirect_to root_path, notice: 'ログインしました'
  end
end

続いて、user.rbです。
app/models/user.rb

class User < ApplicationRecord
  def self.find_or_create_from_auth_hash(auth)
  provider = auth[:provider]
  uid = auth[:uid]
  user_name = auth[:info][:user_name]
  image_url = auth[:info][:image]

    self.find_or_create_by(provider: provider, uid: uid) do |user|
      user.user_name = user_name
      user.image_url = image_url
    end
  end
end

最後にルーティングを設定します。

Rails.application.routes.draw do
  get '/'=>'sessions#top'
  get '/auth/:provider/callback' => 'sessions#create'
end

これでできました。

お疲れ様でした!

追記:
Credentialでキーの管理は普通にできるのですが、なぜがその後のエラーが多い気がします。
僕は現在キーの管理をdotenvというgemでやっています。

参考

OmniAuthを利用して、Twitterログイン機能を作る【初心者向け】
RailsでOmniauthを使ってTwitterログインする