読者です 読者をやめる 読者になる 読者になる

趣味プログラマによるOSS開発日誌

趣味で作っているOSSソフトウェアの紹介や関連技術の紹介、楽曲製作、Webデザイン勉強状況を紹介します。

Qiita投稿アプリ開発(7) OAuth認証

InAppBrowserの問題をクリアし、OAuth認証の完成まであと少しという段階です。

しかし!
Qiitaの公式にOAuth認証の最後のアクセストークン取得のドキュメントが無いというとんでもない状況に遭遇です。
ドキュメントが無いといくら認証の手順を知っていてもお手上げですが、何とかなったので今回は苦労したQiitaのOAuth認証について振り返ってみます。
 

OAuth認証とは

OAuth認証は別に最近出来た認証方式ではなく、有名どころではfacebooktwittergoogleなどで採用されています。
アプリ連携しますかと聞かれるあれです。
OAuth認証を利用することで、認証のために必要なデータ量を最小限にできるので、情報漏洩しにくいので最近はBasic認証よりも使われることが多いらしいです。
 
QiitaもAPI v2からOAuth認証を採用し始めていて、

Qiita投稿アプリ開発(4) Qiita APIのバージョン - 趣味プログラマによるOSS開発日誌

の記事でも書いたとおり、QiitaでもOAuth認証を推奨しているそうです。
 

OAuth認証の流れ

まずOAuthって何ぞやということで、

OAuthプロトコルの中身をざっくり解説してみるよ - ( ꒪⌓꒪) ゆるよろ日記

を参考にOAuth認証についての勉強から始めました。
思ったより煩雑だなと感じつつ、最後まで流し読みし、なんとなく理解出来たところでQiitaのドキュメントを見ながら認証の手順確認します。
ざつくりと考えたのが以下の手順ですが、かなり省略しています。
今後Qiitaに手順をまとめる予定です。
  1. Qiitaでアプリケーションを登録し、生成されたClient IDとClient Secretを確認する
  2. https://qiita.com/api/v2/oauth/authorize?client_id=(Client ID)&scope=read_qiita+write_qiita&state=(任意の16進数)のURLを開く
  3. 認可された時に1.で登録したリダイレクト先のURLに飛ぶので、URLのクエリであるcodeの値を取得する
  4. Client ID, Client Secret, codeを使い、https://qiita.com/api/v2/access_tokensへPOST送信する
  5. POST送信が成功した時に得られるアクセストークンを保存する
  6. これ以降は、アクセストークンをHTTPリクエストヘッダに含めてQiita APIを叩くことで、Qiitaに対して様々な処理を行うことが可能

ドキュメントの不足

手順通り行けば良いのですが、たいてい何かしら問題が出るのは、開発では良くあることですね。
 
今回問題となったのは、Qiita APIのドキュメントに必要な情報が不足しているという何とも素晴らしいものでした。
Qiitaの公式ページにAPIのドキュメントが公開されていますが、v2についてはかなり断片化されていて、すでにここで初心者お断りな状態です。
特にアクセストークンを取得するところなんかは、送信する情報と受け取れる情報が書かれていない素晴らしい状態で、ドキュメントだけを見て実装することはほぼ不可能ですね。
以下の説明を見ていただければ、その素晴らしさが分かるのではないでしょうか。
GET /api/v2/oauth/authorize
アクセストークンを発行するには、アプリケーションのユーザに認可画面を表示する必要があります。ユーザがアプリケーションからのアクセスを認可すると、アプリケーション登録時に指定されたURLにリダイレクトされます。このとき、リダイレクト先のURLクエリにcodeが付与されます。また指定した場合は state も付与されます。アプリケーションでは、この code の値を利用して POST /api/v2/access_tokens にリクエストを送り、アクセストークンを発行します。
うーん、よくわからん。
手当たり次第確認するのも面倒だし、ここで諦めたくはなかったので、他にQiita APIを使ったプログラムがないか調べてみると、こんな記事がありました。

qiita-js/schema.yml at master · increments/qiita-js · GitHub

ドキュメントを作る前段階のものと思えますが、requireにアクセストークンの取得に必要となりそうものが書いてありました。
    links:
    - description: 与えられた認証情報をもとに新しいアクセストークンを発行します。
      title: create_access_token
      method: POST
      href: "/api/v2/access_tokens"
      rel: create
      schema:
        properties:
          client_id:
            "$ref": "#/properties/access_token/properties/client_id"
          client_secret:
            description: 登録されたAPIクライアントを認証するための文字列です。
            type: string
            pattern: "^[0-9a-f]{40}$"
            example: 01fc259c31fe39e72c8ef911c3432a33d51e9337ff34c4fac86c491a0d37251f
          code:
            description: リダイレクト時に付与される、アクセストークンと交換するための文字列です。
            type: string
            pattern: "^[0-9a-f]{40}$"
            example: fefef5f067171f247fb415e38cb0631797b82f4141dcdee66db846c3ade57a03
        required:
        - client_id
        - client_secret
        - code
これをベースに以下のコードを試したところ、OKが出たのでアクセストークンを得るために送信するデータは間違っていないようです。

PhoneGap Get OAuth's access token in Qiita


さらに今回はこれだけではありませんでした。
こちらはもっと素晴らしく、取得したデータからアクセストークンを取り出す方法がドキュメントに書かれていませんでした。
アプリケーションでは、この code の値を利用して POST /api/v2/access_tokens にリクエストを送り、アクセストークンを発行します。
見てください!
このシンプルイズベストな記事を!
この情報だけで実装出来る人は開発者か超能力者か運が良い人でしょう。
 
私はどれにも当てはまらないので、先ほどのドキュメントの下書きらしきものを再び見て見ました。
すると以下のように書かれていました。
properties:
  access_token:
    title: アクセストークン
    description: APIリクエスト時に認証を行うためのアクセストークンを表します。
    properties:
      client_id:
        type: string
        description: 登録されたAPIクライアントを特定するためのIDです。40桁の16進数で表現されます。
        pattern: "^[0-9a-f]{40}$"
        example: a91f0396a0968ff593eafdd194e3d17d32c41b1da7b25e873b42e9058058cd9d
      scopes:
        type: array
        description: このアクセストークンに許された操作内容を表します。文字列の配列で表現されます。
        items:
          type: string
          example: 'read_qiita'
      token:
        type: string
        description: アクセストークンを表現する文字列です。40桁の16進数で表現されます。
        pattern: "^[0-9a-f]{40}$"
        example: ea5d0a593b2655e9568f144fb1826342292f5c6b7d406fda00577b8d1530d8a5
tokenというのがアクセストークンらしさを出しています。
そこでこのトークンを使って、以下のコードで投稿一覧を取得してみると・・・取得出来ました!
一時はどうなることかと思いましたが、情熱が通じたのでしょうか。
なんとかなるものですね。
 
いろいろと大変でしたが、アクセストークンが得られた時は、独学でプログラミングを勉強して動作した時の嬉しさを久々に味わえた気がします。
そして、今回の件でドキュメントが重要だと改めて感じました。
特にAPIでドキュメントが無い状態というのは、APIが無いのと同じであることと同じですね。
 
折角なので今回の話題をQiitaに投稿し、ドキュメントが不十分であることをサポートにも伝えておきましょうかね。