【備考録】CurlでAtCoderのログイン認証が通るか試してみる

[千葉大学 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/c-tech)の10日目の記事

11/30に投稿したんだけど、カレンダーが空いてたんで10日目に入れちゃいました👍


## 概要
AtCoderでコードの自動提出ツールでもやろうと思って、
ログイン認証に関する記事をみてやってみると、403ばっか。。。

```bash
...
Forbidden
...
REVEL_CSRF: tokens mismatch.
...
```

イライラするもなんとか成功したんで忘れないように

## 成功例
1. まずCookieとcsrf_tokenを取得する

```bash
$ curl -c cookie https://atcoder.jp/login | grep csrf

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  6382  100  6382    0     0  35853      0 --:--:-- --:--:-- --:--:-- 35653
                var csrfToken = "PlbAkhFA4c4dopnBLyILMdxSgBZHMfLKkC4O4bsrPSI="
                <input type="hidden" name="csrf_token" value="PlbAkhFA4c4dopnBLyILMdxSgBZHMfLKkC4O4bsrPSI=" />
                        <input type="hidden" name="csrf_token" value="PlbAkhFA4c4dopnBLyILMdxSgBZHMfLKkC4O4bsrPSI=" />
```

cookie情報は`cookie`ファイルに書き込まれたはずだ。
csrf_tokenは上の例だと`PlbAkhFA4c4dopnBLyILMdxSgBZHMfLKkC4O4bsrPSI=`がそれに当たる。

2. 実際に認証が通るかテスト

```bash
$ curl -i -b cookie https://atcoder.jp/login -X POST -F "csrf_token=PlbAkhFA4c4dopnBLyILMdxSgBZHMfLKkC4O4bsrPSI=" -F "username=あなたのユーザーネーム" -F "password=あなたのパスワード"
...
HTTP/1.1 302 Found
Date: Fri, 29 Nov 2019 16:41:57 GMT
Content-Length: 0
Connection: keep-alive
Server: nginx
Cache-Control: no-cache, no-store, must-revalidate, private
Expires: Fri, 1 Jan 2010 00:00:00 GMT
Location: /
Pragma: no-cache
Set-Cookie: REVEL_FLASH=%00success~; Path=/; HttpOnly
Set-Cookie: REVEL_SESSION=~; Path=/; Expires=Wed, 27 May 2020 16:41:57 GMT; Max-Age=15552000; HttpOnly
X-Content-Type-Options: nosniff
X-Xss-Protection: 1; mode=block
```

成功するとステータスコード302 & Set-Cookieでsuccessと出るはずだ
**成功した時のCookieを使うことで、ログインが必要な操作がし放題！**

## 失敗例

```bash
$ curl -b cookie https://atcoder.jp/login -X POST -H "Content-Type: application/json" -d '{"csrf_token":"PlbAkhFA4c4dopnBLyILMdxSgBZHMfLKkC4O4bsrPSI=","username":"あなたのユーザーネーム","password":"あなたのパスワード"}'
...
```

。。。。。なんでだ？
いつもならフォームでの入力はJsonで渡せばよかったのに
というか成功例のCurlオプションの`-F`って何者だ？

原因調査の時間がないのでとりあえず、公式の引用を載せておいて、また後で調べるか

[公式サイト](http://www.mit.edu/afs.new/sipb/user/ssen/src/curl-7.11.1/docs/curl.html)
> -d/--data <data>
> (HTTP) Sends the specified data in a POST request to the HTTP server, in a way that can emulate as if a user has filled in a HTML form and pressed the submit button. Note that the data is sent exactly as specified with no extra processing (with all newlines cut off). The data is expected to be &zerosp;"url-encoded". This will cause curl to pass the data to the server using the content-type application/x-www-form-urlencoded. Compare to -F/--form. If this option is used more than once on the same command line, the data pieces specified will be merged together with a separating &-letter. Thus, using '-d name=daniel -d skill=lousy' would generate a post chunk that looks like &zerosp;'name=daniel&skill=lousy'.
> If you start the data with the letter @, the rest should be a file name to read the data from, or - if you want curl to read the data from stdin. The contents of the file must already be url-encoded. Multiple files can also be specified. Posting data from a file named 'foobar' would thus be done with --data @foobar".
> To post data purely binary, you should instead use the --data-binary option.
> -d/--data is the same as --data-ascii.
> If this option is used several times, the ones following the first will append data.


## 調査結果
どうやら`-F`はクエリパラメーターのような働きをするようだ。

例:

```bash
$ curl https://atcoder.jp/login -X POST -F "csrf_token=PlbAkhFA4c4dopnBLyILMdxSgBZHMfLKkC4O4bsrPSI="
```

これは
`https://atcoder.jp/login?csrf_token=PlbAkhFA4c4dopnBLyILMdxSgBZHMfLKkC4O4bsrPSI=`
にPOSTリクエストを送ることと同じ動作をする。

まじかーいPOSTでBodyにJsonを載せるんじゃなくてクエリパラメーターとして送るんかい😇

## まとめ
AtCoderのログイン認証では必要なデータをPOSTリクエストのBodyではなくクエリパラメーターとして送る