Rails の devise を使ったログイン画面で  
Chrome 使った場合だけ  
`Can't verify CSRF token authenticity.`  
が出るんですが  
Safari を使うと正常にログインできます

[サーバー環境]  
MacOSX 上の docker 19.03.5 上の 4.9.184-linuxkit x86_64 GNU/Linux イメージ上  
ruby 2.5.1p57  
Rails 5.2.0  
devise 4.7.1

[クライアント]  
MacOSX Chrome最新版(84.0.4147.125) で発生  
(6月ぐらいまでの Chrome では発生していませんでした)

Safari 13.0.3 (15608.3.10.1.4) では発生しません

docker 上のサーバーに http://localhost:3000 でアクセスする場合のみ発生するようで  
同じブランチを AWS amazonlinux2 上にデプロイして  
nginx + unicorn + Rails で https のドメイン名でアクセスしたときは Chrome でも発生しません

Rails 側の設定のせいだと思って dervise のコードを読んでみたりしたんですが原因がわからず  
Safari だと問題なく動いたのでどうも Chrome + docker の組み合わせが原因みたいなのですが  
どうしてこういうことが起こるか解決法をご存知の方はいらっしゃいませんか

* * *

こちらが Chrome が生成しているヘッダ(ログインできないケース)

```

    CONTENT_LENGTH:251
    CONTENT_TYPE:application/x-www-form-urlencoded
    GATEWAY_INTERFACE:CGI/1.1
    HTTP_ACCEPT:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
    HTTP_ACCEPT_ENCODING:gzip, deflate, br
    HTTP_ACCEPT_LANGUAGE:ja,en-US;q=0.9,en;q=0.8
    HTTP_CACHE_CONTROL:max-age=0
    HTTP_CONNECTION:keep-alive
    HTTP_COOKIE:email=xxxxx; remember=true
    HTTP_HOST:localhost:3000
    HTTP_ORIGIN:http://localhost:3000
    HTTP_REFERER:http://localhost:3000/users/login
    HTTP_SEC_FETCH_DEST:document
    HTTP_SEC_FETCH_MODE:navigate
    HTTP_SEC_FETCH_SITE:same-origin
    HTTP_SEC_FETCH_USER:?1
    HTTP_UPGRADE_INSECURE_REQUESTS:1
    HTTP_USER_AGENT:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36
    HTTP_VERSION:HTTP/1.1
    
```

これが safari の生成しているヘッダ(ログインできるケース)

```

    CONTENT_LENGTH:299
    CONTENT_TYPE:application/x-www-form-urlencoded
    GATEWAY_INTERFACE:CGI/1.1
    HTTP_ACCEPT:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    HTTP_ACCEPT_ENCODING:gzip, deflate
    HTTP_ACCEPT_LANGUAGE:ja-jp
    HTTP_CONNECTION:keep-alive
    HTTP_COOKIE:email=xxxxx; remember=true; _session_id=xxxxx
    HTTP_HOST:localhost:3000
    HTTP_ORIGIN:http://localhost:3000
    HTTP_REFERER:http://localhost:3000/users/login
    HTTP_UPGRADE_INSECURE_REQUESTS:1
    HTTP_USER_AGENT:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Safari/605.1.15
    HTTP_VERSION:HTTP/1.1
    
```

違う項目は  
HTTP_ACCEPT の種類が多いのは関係ないとして

```

    HTTP_CACHE_CONTROL:max-age=0
    
```

があること

```

    HTTP_COOKIE に _session_id=xxxxx 
    
```

の項目がないけどこれは１度も成功してないから？  
そもそも初回は Cookie はないものなので関係なさそう

```

    HTTP_SEC_FETCH_DEST:document
    HTTP_SEC_FETCH_MODE:navigate
    HTTP_SEC_FETCH_SITE:same-origin
    HTTP_SEC_FETCH_USER:?1
    
```

という４項目があって CSRF に関係しそうな HTTP_SEC_FETCH_SITE:same-origin という項目があるんですが Rails
内でどう使われているか不明  
ただ same origin check 自体は通過していてトークン自体の照合に失敗しているようなのです

あと気になるのが form data が safari は

```

    rack.request.form_hash:{"utf8"=>"✓", "authenticity_token"=>"xxxxx", "user"=>{"email"=>"xxxxx", "password"=>"xxxxx", "remember_me"=>"1"}, "commit"=>"ログイン"}
    
```

と commit の項目があるのに対して chrome が送信したものには

```

    rack.request.form_hash:{"utf8"=>"✓", "authenticity_token"=>"xxxxx", "user"=>{"email"=>"xxxxx", "password"=>"xxxxx", "remember_me"=>"1"}}
    
```

と commit が含まれません

```

    <input type="submit" name="commit" value="ログイン" data-disable-with="ログイン">
    
```

という HTML は当然表示されてるんですが  
ブラウザによって form タグの HTML の解釈方法が違ったりするのでしょうか…

* * *

コメントで教えていただいた  
<https://qiita.com/yu_suke1994/items/39fa64ef96aa2a67dc2a>  
こちらのサイトを確認して各チェック項目をデバッグ表示したところ

```

    request.origin => 'http://localhost:3000'
    request.base_url => 'http://localhost:3000'
    valid_request_origin? => true
    
```

で same origin check には成功していて

`any_authenticity_token_valid? => false`

になるのでトークン自体の照合に失敗しているようなのです

<https://qiita.com/ksilverwall/items/1dfdc2f7a45cea591dd4>

こちらのサイトと同じ現象のようなのですが原因は不明みたいです
CC BY-SA 4.0
2020-08-11T08:00:30.003
69451
2020-08-12T08:04:21.767
2020-08-12T08:04:21.767
question
ruby-on-rails docker google-chrome
Rails の devise ジェムを使ったログイン画面に Chrome でだけログインできない