[学習用]Rails5+herokuで Twitter認証を実装する：deviseを使ってない場合

![Twitterauthapp (1).jpg](https://qiita-image-store.s3.amazonaws.com/0/132580/aa566ac4-3716-a31c-16c5-3ee546db8bf4.jpeg)
![Twitterauthapp (2).jpg](https://qiita-image-store.s3.amazonaws.com/0/132580/8acaeb72-8e0e-7766-5ad4-7b60686b00ae.jpeg)

![Twitterauthapp.jpg](https://qiita-image-store.s3.amazonaws.com/0/132580/d03c49c4-fda5-f84b-8e62-c597b60ddd4f.jpeg)

くじけそうになったが何とか認証まで成功したのでメモ

# 結論
いろんなサイトのコードをマネして何度も失敗しましたが、ソースコードが間違っているのではなくcallbackの記述が間違っているかと思われます。
成功した流れとコードをメモしておきます。
※ローカルでもHerokuでも動作確認できました。
　callbackにローカルアドレス入れたら出来ました。

## 環境
```
Rails 5.2.1
Ruby  2.5.1
heroku

ubuntu16
IntelliJ IDEA
```

# 重要：困ったら
## API keysを作成と確認
![Twitter Developers.jpg](https://qiita-image-store.s3.amazonaws.com/0/132580/e07ccbc6-8959-d110-f020-12220358ca3c.jpeg)

Twitter から Consumer API keys　を作成する

- API key
- API secret key

これが無いと作れません。
キーを間違わない様にコピペしておきましょう。
Consumer API keysの方で良いです。

## 苦戦する Callback URL の確認
![Twitter   アプリケーション認証.jpg](https://qiita-image-store.s3.amazonaws.com/0/132580/96024fac-dfe0-ebf8-901d-3103b2aabd55.jpeg)

Callback URL は色々なところで書かれているが、
APIの仕様が結構変わるらしく最新の記述方法じゃないとエラーで弾かれます。

結局 2018/11/30 時点で成功した方法は

```
https://ドメイン名 ＋ auth/twitter/callback　が正解でした。
```

Heroku例：https:// ドメイン名.herokuapp.com/auth/twitter/callback
ローカル例：http:// 192.168.xx.yy:3000/auth/twitter/callback

![Twitter Developers (1).jpg](https://qiita-image-store.s3.amazonaws.com/0/132580/849f48ca-ac3d-9a2e-b954-a04611816774.jpeg)


たぶんどこのサイトの例やサンプルコードをマネしてもエラーが出るのはこの記述が違うから弾かれるんだと思います。


# アプリ作成：ここからはじまり
```
$ rails new twitterauthapp -d postgresql
$ cd twitterauthapp
$ bundle
```

# gem の追加
```ruby
gem 'omniauth'
gem 'omniauth-twitter'
```

# env ファイルを作成
```/.env
APP_ID = "API key を入れます"
APP_SECRET = "API secret key を入れます"
```

空ファイルを作成して上記の内容を記載します。
Twitter から Consumer API keys コピペースとします。

# env を公開しない設定
```/.gitignore
/.env
```

.gitignore へ 上記を追加することでConsumer API keysがアップロードされなくなります。


# omniauth.rb を作成
```/config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :twitter, ENV['APP_ID'], ENV['APP_SECRET']
end
```
ファイルを新しく手動で作成します。
空ファイル作成してコピペでOK。

# user モデルを作成
```
$ rails g model user provider:string uid:string user_name:string image_url:string
```

devise を使ってないバージョンです。
既に使っている場合は書き方が違いました。


## 作成した user モデルに記述
```/app/models/user.rb
class User < ApplicationRecord
  def self.find_or_create_from_auth(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 g controller sessions
```

```/app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
  def create
    user = User.find_or_create_from_auth(request.env['omniauth.auth'])
    session[:user_id] = user.id
    flash[:notice] = "ユーザー認証が完了しました。"
    redirect_to root_path
  end

  def destroy
    reset_session
    flash[:notice] = "ログアウトしました。"
    redirect_to root_path
  end
end
```

# ヘルパーメソッドを追加
```/app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  helper_method :current_user, :logged_in?

  private

  def current_user
    return unless session[:user_id]
    @current_user ||= User.find(session[:user_id])
  end

  def logged_in?
    !!session[:user_id]
  end

  def authenticate
    return if logged_in?
    redirect_to root_path, alert: "ログインしてください"
  end
end
```

# ログイン画面を作成
```
$ rails g controller home index
```
とりあえず、ログイン出来るリンクを追加するので作成します。

## Twiiterログインリンクを作成
```/app/views/home/index.html.erb
<% if session[:user_id]==nil %>
  <%= link_to "Twitterログイン", "/auth/twitter"%>
<% else %>
  <%= link_to "Twitterログアウト", "/logout"%>
<% end %>
```

ログイン用のリンク。


# ルーティングを設定する
```/config/routes.rb
Rails.application.routes.draw do
  get 'home/index'
  get '/auth/:provider/callback', to: 'sessions#create'
  get '/logout', to: 'sessions#destroy'
  root 'home#index'
end
```

ログイン用のリンクをTOPにしておきます。

# ローカルで画面の確認
```
$ rails db:create
$ rails db:migrate
```

TOP画面は問題無く出せました。
ローカル環境でも動作確認できました。

ここでローカルが動作しないのであれば、
ローカル用の Callback URL が適切でないかなと思います。

※rails db:create はしなくても良いと思いますが、自分の環境では何度も書いて消したので
　データベースが残ってたか作成されてなかったので作成しました。


# Herokuへデプロイ
```
$ heroku create twitterauthapp 
$ git init
$ git add .
$ git commit -am "test auth"
$ git push heroku master
```

```
$ heroku run rails db:migrate

$ heroku config:set APP_ID=API key を入れます
$ heroku config:set APP_SECRET=API secret key を入れます
```
Herokuに API key、API secret key を登録します。

```
$ heroku config
```
API key、API secret keyが登録されているか確認できます。

アプリURLを決めてから毎度おなじみコマンドです。
HerokuへAPI key、API secret key とdb:migrateを忘れずに。

# 認証成功した画面
![Twitter   設定.jpg](https://qiita-image-store.s3.amazonaws.com/0/132580/bf781c27-f7cd-2ab0-226f-06ec3a20598c.jpeg)

これでアップした画面のURLをクリックするとTwitter認証画面がでます！