Ruby on Rails: twitterでユーザー認証

> 注意: この記事は2018年10月頃から情報を更新していないため、内容がかなり古くなっています。
> この記事を参考にされるより、[公式のサイト](https://developer.twitter.com/en/docs/twitter-for-websites/log-in-with-twitter/login-in-with-twitter)を参考にしていただきたいです。
> 実行手順: https://developer.twitter.com/en/docs/twitter-for-websites/log-in-with-twitter/guides/implementing-sign-in-with-twitter

#Twitter Application Managementへ登録
https://apps.twitter.com
まず上記サイトへ行き、右上の「Create new app」を押し登録を進めます。
![2018-02-16.png](https://qiita-image-store.s3.amazonaws.com/0/210573/18275296-cde3-ba22-e211-d6655d8ef0be.png)
上記のようなサイトへ進んだら画像のように入力します。
Name:アプリの名前
Description:アプリの説明
Website:サイトのURL
Callback URL:登録後に遷移するページのURL(これを指定しないと401エラーになる)
※2018/07/06現在Callback URLは2つ設定しないといけない仕様に変わりました。ですので、下記のようにCallback URLを変更してください。
----Callback URL----
http://127.0.0.1:3000
http://localhost:3000/auth/twitter/callback


入力後利用規約にチェックを入れて「Create」ボタンを押してください。
その後ページに表示されるConsumer KeyとConsumer Secretはこの後に使います。
#Twitterと連携
次にommniauthとomniauth-twitterをインストールします。これらは、twitterとの連携を簡単に行えるようにしてくれるものです。
dotenv-railsは環境変数を簡単に利用できるようにしてくれるもので、公開したくない情報を隠すことができます。詳しくは使うときに書きます。

```ruby:Gemfile
gem 'omniauth'
gem 'omniauth-twitter'
gem 'dotenv-rails' #環境変数を簡単に利用できるgem
```
```
bundle i
```
上記の工程が終わり、gemをインストールしたら次に「config/initializers/omniauth.rb」を作成し、下記のように記入します。TWITTER_CONSUMER_KEYとTWITTER_CONSUMER_SECRETは環境変数です。

```ruby:.env
TWITTER_CONSUMER_KEY    =  #自分のConsumer Key
TWITTER_CONSUMER_SECRET =  #自分のConsumer Secret
```

上記のように環境変数を指定しgitignoreにファイル名を記入することで公開されてはいけない情報を隠すことが出来る。

```ruby:secrets.yml
default_twitter: &default_twitter
  twitter_api_key: <%= ENV["TWITTER_CONSUMER_KEY"] %>
  twitter_api_secret: <%= ENV["TWITTER_CONSUMER_SECRET"] %>



development:
  secret_key_base: #最初から記入されているはず
  <<: *default_twitter

test:
  secret_key_base: #最初から記入されているはず
  <<: *default_twitter

production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
  twitter_api_key: <%= ENV["TWITTER_CONSUMER_KEY"] %>
  twitter_api_secret: <%= ENV["TWITTER_CONSUMER_SECRET"] %>
```

```ruby:omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :twitter, ENV['TWITTER_CONSUMER_KEY'], ENV['TWITTER_CONSUMER_SECRET']
end
```

次にModelとControllerです。

```ruby:コンソール
rails g model user provider:string uid:string username:string image_url:string 
```

```ruby:user.rb
class User < ApplicationRecord

  def self.find_or_create_from_auth_hash(auth_hash)
   provider = auth_hash[:provider]　#providerはどのサービスで認証したのかを見分けるもの
   uid = auth_hash[:uid]
   name = auth_hash[:info][:name]
   image_url = auth_hash[:info][:image]

   #find_or_create_by()は()の中の条件のものが見つければ取得し、なければ新しく作成するというメソッド
   self.find_or_create_by(provider: provider,uid: uid) do |user|
     user.username = name
     user.image_url = image_url
   end
  end

end
```

```ruby:users_controller.rb
 def create
    user = User.find_or_create_from_auth_hash(request.env['omniauth.auth'])#request.env['omniauth.auth']はTwitter認証で得た情報を格納するもの
    if user
      session[:user_id] = user.id
      redirect_to '/posts/index', notice: "ログインしました。"
    else
      redirect_to root_path, notice: "失敗しました。"
    end
  end
```

```ruby:routes.rb
Rails.application.routes.draw do

  get 'auth/:provider/callback' => 'users#create'#このpathを通して認証が行われる。

  root 'home#top'
end

```

```ruby:top.html.slim
= link_to 'Twitterでログイン', '/auth/twitter' #twitterの認証画面へのURL
```
これで設定は終了です。
ここまでできれば、local環境でtwitterの認証機能は動くはずです。

最後に本番環境でHerokuを使う場合はHeroku側で環境変数を設定しないといけません。

```
$ heroku config:add TWITTER_CONSUMER_KEY="自分のConsumer Key"
$ heroku config:add TWITTER_CONSUMER_SECRET="自分のConsumer Secret"
```
これでHerokuでも動くはずです。

以上で終わりです。
間違い等があれば指摘していただければと思います。