【Rails】SorceryでTwitter認証

## はじめに
Sorceryを使ったTwitterログイン認証の設定です。
基本的には[wiki](https://github.com/Sorcery/sorcery/wiki/External)の通りにすればいいです。

（2020/4/23追記）メールアドレスの取得方法について追記しました。

（2021/4/29追記）個人ブログに移行しました。
[【Rails】SorceryでTwitter認証 – blog\.aiandrox](https://blog.aiandrox.com/posts/tech/2020/03/29/)

-----------------

以下は、ちょっと試してみたことやエラーとの奮闘になります。


## callback_urlを設定しない場合

> For OAuth 1.0a compliance this parameter（注釈：`oauth_callback`のこと） is required .
[POST oauth/request_token — Twitter Developers](https://developer.twitter.com/en/docs/basics/authentication/api-reference/request_token)

ということなので、`callback_url`を設定しないとどうなるのか試してみた。

```rb:config/sorcery.rb
  # config.twitter.callback_url = 'http://localhost:3000/oauth/callback?provider=twitter'
```

```slim:認証画面のURL
https://api.twitter.com/oauth/authenticate?oauth_callback&oauth_token=vyYZbQAAAAABDRHmAAABcRsW6zQ
```

クエリを見ると、`oauth_callback`に値が入っていない。
認証を押すと、PINコードの入力を求められ、リダイレクトしなくなってしまった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322882/569ec856-18b5-00fd-c99b-a092ae459552.png)


## エラーいろいろ
### NoMethodError at /oauth/callback

認証後に`/oauth/callback`に行かない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322882/421eddae-4e26-f86f-1610-613ebfc7991d.png)

```
NoMethodError at /oauth/callback
undefined method `original_callback_url' for nil:NilClass
```

```slim:コールバック時のURL
http://127.0.0.1:3000/oauth/callback?provider=twitter&oauth_token=EHBQ4wAAAAABDRHmAAABcRr4LwQ&oauth_verifier=zFvTO1ay9G316hmbPMcbexTfckA45M4j
```

画面ばかり見て「どうしてoauthsアクションに飛んでいるのだろう」と思っていたのですが、そもそも`NoMethodError`でした。


#### 解決法

```config/routes.rb
  post "oauth/callback", to: "oauths#callback"
  get 'oauth/callback', to: 'oauths#callback' # この行がなかったので追加
  get "oauth/:provider", to: "oauths#oauth", as: :auth_at_provider
```


### Mysql2::Error - Field 'twitter_id' doesn't have a default value:

```terminal
Started GET "/oauth/callback?provider=twitter&oauth_token=qvWE_gAAAAABDRHmAAABcSFi3bQ&oauth_verifier=nUb5kYYSryTHA03FepYw2xSLNzVFMmTc" for 127.0.0.1 at 2020-03-28 22:44:22 +0900
Processing by OauthsController#callback as HTML
  Parameters: {"provider"=>"twitter", "oauth_token"=>"qvWE_gAAAAABDRHmAAABcSFi3bQ", "oauth_verifier"=>"nUb5kYYSryTHA03FepYw2xSLNzVFMmTc"}
Unpermitted parameters: :oauth_token, :oauth_verifier
  Authentication Load (0.8ms)  SELECT  `authentications`.* FROM `authentications` WHERE `authentications`.`uid` = '1048451188209770497' AND `authentications`.`provider` = 'twitter' ORDER BY `authentications`.`id` ASC LIMIT 1
  ↳ app/controllers/oauths_controller.rb:8
   (0.2ms)  BEGIN
  ↳ app/controllers/oauths_controller.rb:13
  User Exists (3.4ms)  SELECT  1 AS one FROM `users` WHERE `users`.`uuid` = '7gl0ZsQ_tTbl' LIMIT 1
  ↳ app/models/user.rb:21
  User Create (1.5ms)  INSERT INTO `users` (`uuid`, `name`, `description`, `created_at`, `updated_at`) VALUES ('7gl0ZsQ_tTbl', 'aiandrox', '小学校の先生やってた。エンジニア目指してRailsとか頑張ってる。#RUNTEQ 1月生。謎解き好き。', '2020-03-28 22:44:24', '2020-03-28 22:44:24')
  ↳ app/controllers/oauths_controller.rb:13
   (0.2ms)  ROLLBACK
  ↳ app/controllers/oauths_controller.rb:13
Completed 500 Internal Server Error in 1349ms (ActiveRecord: 42.5ms)

Mysql2::Error - Field 'twitter_id' doesn't have a default value:
  app/controllers/oauths_controller.rb:13:in `callback'
```

データベース側でtwitter_idカラムに`null: false`制約をかけていたので、このエラーが出ました。
確かにログを見るとtwitter_idカラムには何も入っていない。


#### 解決法

```diff:config/sorcery.rb
  config.twitter.user_info_mapping = {
-   twitter_id: 'user_id',
+   twitter_id: 'id',
    name: 'name',
    description: 'description'
  }
```

Twitterから取得するデータのパラメータが間違っていました。
参考：[User Object(ユーザーオブジェクト)の説明](https://syncer.jp/Web/API/Twitter/REST_API/Object/User/)

## おわりに

特別な内容ではありませんが、参考になれば幸いです。
ご指摘などがございましたら、コメントか編集リクエストでお願いいたします。

### その他参考サイト

- [【Rails】Sorcery で Twitter 認証 \[2\]｜Artefact｜note](https://note.com/artefactnote/n/ne0089a217489)