OAuth1.0a を使ったプログラムを書いていて、OAuth について整理したくなったのでメモ。
Webシステムを想定。
OAuth の文脈で言うと、ユーザー、サービスプロバイダー、コンシューマーの3者を想定する。
ユーザーはとにかくサービスプロバイダーのサービスを受けたい。
ここではサービスプロバイダーをZaimとしましょう。
Zaimのサービスを利用するにはユーザーはZaimにアカウントを作ります。
ユーザーに紐付いた情報をサービスするのですから当然ですね。
Zaimは個々のユーザーのデリケートな情報を扱わなければならないので、あるユーザーを他のユーザーと区別しなければなりません。このプロセスを認証(Authentication)といいます。多分。
Authentication の意味を Google 先生に確認してみましょう。
the process or action of proving or showing something to be true, genuine, or valid.
何かが正式なものであることを証明するためのプロセスのことらしいです。コンピューティングにおいては、
the process or action of verifying the identity of a user or process.
とのことで、この場合、サービスプロバイダー(Zaim)が、ユーザーが本当にサービスにアカウントを持っているか、また、ユーザーが誰であるかユーザー自身に証明してもらうプロセスになりますかね。
やさしい世界においては、名前があれば十分かもしれませんし、そのような認証はあちこちに存在しますが、名前は運用上もセキュリティ上も不備が多いです。
Webサービスにおいては、セキュリティの度合いに応じて様々な認証方法が存在するかと思いますが、サービス上でユニークな、ユーザーが任意に決めたユーザー名(もしくはE-mailアドレス)+パスワードという形式がポピュラーなのではないでしょうか。私の認識ではZaimもこの方式です。
サービスプロバイダーはこの2つで1セットの情報をもとに、ユーザーを認証します。いつも思うのですが、なぜ本質的には1つの情報を2つに分けるのでしょうか?パスワードだけでよくない?この疑問は根が深そうですが、少なくともシステムでユニークなIDと任意のパスワードに分けることで、前者が絶対にかぶらないことを保証でき、後者がかぶることを許容でき、全体としては絶対にかぶらないという性質を担保できそうです。
ユーザーがIDとパスワードをサービスプロバイダーに提示して晴れてサービスプロバイダーに認証されると、ユーザーはサービスプロバイダー(Zaim)のサービスを受けることができます。具体的には収支を入力したり統計を閲覧したりとかですね。いわばZaim公式のサービスです。
しかしユーザーの中には、公式のサービスは使いづらいと感じる人がいるかもしれません。Webサービスはだいたい機能とUIがセットなので、機能は欲しいがUIが気に入らないというユーザーにはちょっともったいないですよね。そこで、機能だけを開発者に開放して、UI開発の余地を与えるシステムがOAuthです!(あってる?)
ここでいう開発者が、OAuthでいうコンシューマーですね。サービスプロバイダーの提供する機能を消費(利用)して、独自のUIを設計し、アプリとしてユーザーに提供できるのです。なんて素晴らしい!
ここからが本題なのですが、OAuth1.0aではどうやってこれを実現しているのでしょうか。
私調べでは、まずコンシューマーはあらかじめサービスプロバイダーに開発者としてアカウントを作ります。サービスプロバイダーは、開発者を認証するための「コンシューマーID」と「コンシューマーシークレット」を発行します。ユーザーの例で出てきたIDとパスワードみたいなものですね…ん?
ここで早くも間違いに気づきました。そもそも開発者は、サービスプロバイダーの提供する機能を使って、「アプリ」を作ることが前提となっています。「コンシューマーID」と「コンシューマーシークレット」は「アプリ」に紐付けられます(どうやら)。アプリは複数登録でき、アプリごとに権限範囲など、設定が可能です。このへんの話はZaimの場合の話かもしれませんが、先に進みます。
開発者はアプリの実装上、ユーザーに機能を提供するために、最終的には「シークレットトークン」なる、一定期間だけ有効な鍵のようなものをサービスプロバイダーからゲットする必要があります。この魔法の鍵により、コンシューマーであるアプリがZaimの機能にアクセスして調理し、ユーザーに提供することができるのです。
このシークレットトークンを得るためには、どうしてもユーザーにサービスプロバイダーへの認証をお願いしなければなりません。この認証のための画面だけは、サービスプロバイダーが提供することになります。そうしなければ、コンシューマーが間に入ってユーザーの認証情報を知ってしまうことになるからです。コンシューマーができるのは、サービスプロバイダーの窓口(後述)をユーザーに知らせることだけです。
ユーザーは、コンシューマーにもらった伝票にかいてあるサービスプロバイダーの窓口へ行き、認証してもらい、伝票にハンコを押してもらい、その伝票をコンシューマーの窓口に戻します。この辺の作業はブラウザが手伝ってくれるので、ユーザーはそれほど大変ではありません。伝票とかハンコはあくまでイメージです。
コンシューマーは受け取った伝票をサービスプロバイダーに提出し、間違いなくサービスプロバイダーの認証したユーザーがコンシューマーを通じてサービスプロバイダーの機能を利用することを承諾した旨を確認し、コンシューマーは晴れてシークレットトークンをサービスプロバイダーからゲットすることができます。
ここで一つ説明をおろそかにした部分があるのですが、ユーザーを認証するためのサービスプロバイダーの窓口は、コンシューマーごとに専用の窓口があります。こうすることで、サービスプロバイダーとコンシューマーが連携していることをユーザーに示すことができ、ユーザーは安心して認証プロセスを完了させられるのです(この辺の理解はまだあやふや)。
このユーザー認証窓口を設置するために、コンシューマーはまず最初に自身をコンシューマーIDとコンシューマーシークレットを使ってサービスプロバイダーに認証してもらい、まずリクエストトークンとリクエストシークレットというものをもらい、その2つを使って窓口(認証用URL)を用意してもらうという手順を踏みます。このリクエストトークン&シークレットは、シークレットトークンを得るときにも必要になるので、一旦ブラウザセッションの切れるコンシューマーアプリは、セッションなどに保存しておく必要があります。
以上、先人が何度書いたかわからない、アウトプットのためのOAuthに関するメモでした。