Qiita APIのOAuth認証は一筋縄ではいかない


きっかけ

Qiita API で遊んでみようと思い、OAuthのライブラリを使ってサクッと認証をしようと試みましたがうまくいきませんでした。
自分なりに調べたところ、どうも Qiita API の認証は OAuth の仕様とちょっと違う気がしたのでメモも兼ねて投稿します。

ご意見・ご指摘あればコメントしていただけると助かります!

この記事の内容は 2019年2月27日 時点での内容です。今後のQiita APIの修正・変更によって内容に差異が生じる場合があります

何が困るのか

仕様と違うと仕様に準拠して作られた認証ライブラリを使って認証できません。
なのでQiita APIの認証用にちょっとライブラリを書き換えるか、最悪 自前で実装する必要がでてきます。

この記事の内容がライブラリを書き換えたり、設定する際のヒントになれば幸いです。

1. アクセストークン発行リクエストの Content-Type が違う

仕様では Content-Typeapplication/x-www-form-urlencoded
Qiita APIでは application/json になっている

解説

Qiita API の OAuth 認証ではアクセストークンの発行リクエストの Content-Typeapplication/json を指定するよう指示があります。

参考: https://qiita.com/api/v2/docs#post-apiv2access_tokens

しかし、OAuth 2.0の仕様では

クライアントはトークンエンドポイントに対して, 次のようなパラメーターを付与してリクエストを送信する. 
(中略)application/x-www-form-urlencoded フォーマットで含める.

(中略)

Content-Type: application/x-www-form-urlencoded

参考: https://openid-foundation-japan.github.io/rfc6749.ja.html#token-req

とあるように Content-Type には application/x-www-form-urlencoded を指定するよう仕様で策定されています。
認証ライブラリを使う場合、そのライブラリが OAuth 仕様に準拠していると application/x-www-form-urlencoded でリクエストを行うため Qiita API の OAuth 認証に失敗します。
invalid_content_type というエラーレスポンスが返ってきます)

Qiita でもこの Content-Type 問題でつまずいてる方がいらっしゃいました。

2. アクセストークンレスポンスのJSONの形が違う

仕様ではJSON内のトークンのキーは access_token
Qiita APIでは token になっている

解説

Qiita APIのドキュメントによると、アクセストークンのリクエストに成功すると次のようなレスポンスが返ってきます。

{
  "client_id": "a91f0396a0968ff593eafdd194e3d17d32c41b1da7b25e873b42e9058058cd9d",
  "scopes": [
    "read_qiita"
  ],
  "token": "ea5d0a593b2655e9568f144fb1826342292f5c6b7d406fda00577b8d1530d8a5"
}

参考: https://qiita.com/api/v2/docs#post-apiv2access_tokens

仕様では次のように定められています

アクセストークンリクエストが正当かつ認可された場合,(中略)
成功レスポンス例を以下に示す.

{
    "access_token":"2YotnFZFEjr1zCsicMWpAA",
    "token_type":"example",
    "expires_in":3600,
    "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
    "example_parameter":"example_value"
}

参考: https://openid-foundation-japan.github.io/rfc6749.ja.html#anchor25

Qiita APIでは肝心のトークンの key が access_token ではなく token となっています。
Content-Type のときと同様に OAuth 仕様に準拠したライブラリでは access_token を前提にするので、「トークンが取得できない」といったようなエラーが発生する可能性があります。

まとめ

  • 認証フローをQiita APIのドキュメント読みながら自分でガリガリ書いちゃう人は問題なし
  • OAuth認証ライブラリを使う場合は注意。Qiitaの認証を通したい場合は自分でライブラリに手を加える必要があるかも
  • 「OAuth認証」と銘打ってるのだから仕様準拠のライブラリで認証できるように Qiita さんには修正してもらいたい……