OAuth認証やってまいります。
WP REST API の OAuth 認証用のプラグインの github レポジトリのドキュメントのフローの通り進めます。また、リクエストの送信には、Paw という Mac アプリを利用します。
この記事自体の中に上記のドキュメントで伝えられていることを逐次翻訳して残しておこうと思います。上記のドキュメントは読まなくても大丈夫になるように頑張ります。間違いがあったら、 @shinichiN へお願いします。
STEP 0: Client Key と Client Secret を作成する
ドキュメントサイトの方には「OAuth のプラグインにUIはありません。そのうち作ります」などと書かれておりましたが、実際にはありました。
wp-cli を利用して $ wp oauth1 add
みたいなことをしないといけない、とドキュメントサイトにはありますが、管理画面でできました。
というわけでさっそく作っていきましょう。
Name
と Description
は管理用のものだと思われますので適当に入れます。Callback URL
はよく分からないですが必須なので /success
としました。
Client Key
と Client Secret
をメモしておきましょう。
OAuth フローの概要と、その意義
OAuth1/Auth-Flow.md at master · WP-API/OAuth1 にある OAuth 認証のフローを翻訳します。クライアント側から見ると、3つのフローに分かれています。
- Temporary Credentials Acquisition: The client gets a set of temporary credentials from the server.
- Authorization: The user “authorizes” the request token to access their account.
- Token Exchange: The client exchanges the short-lived temporary credentials for a long-lived token.
翻訳(と若干の色々を追加)は、
- 一時的な証明書の取得: サーバから、一時的な証明書を受け取る(この証明書のことを一般的にリクエストトークンと呼ぶ)
- 認証: ユーザー(人間)が、リクエストトークンを認証してアカウントにアクセスする
- トークンの交換: クライアントが一時的な証明書を、長期的な証明書と交換する
となります。(交換後の証明書のことを、一般的にアクセストークンと呼ぶ)
となります。
OAuth 認証の意義は、以下の様なことと理解するとよいと思います。
まず、WordPress のサイトが有り、OAuth プロバイダとして動くことができます。今、やろうとしていることは、WordPress の REST API を利用して認証済みのアプリケーションでなければ行えないことを実行したい、ということです。
ログインしていないとできないこととはたとえば、投稿のメタデータを取得するとか、データをアップデートする、といったことです。WP REST API では、ログインしていないユーザーであっても公開情報を取得することは可能ですが、内部的なデータは取得できませんし、データを追加したり変更したり削除したりといったことももちろんできません。
外部のアプリケーション(スマホアプリやウェブアプリ、デスクトップアプリなど)から、こうしたことを行いたい場合に、最初に思いつくのは毎回ユーザー名とパスワードを送ってログインさせればいいじゃないか、ということですが、もちろんこれは大問題となります。
- 毎回パスワードを送るのがまずい。
- 外部のアプリケーションにユーザー名とパスワードを教えてあげないといけないのがまずい。
そこで OAuth の認証の仕組みが必要になるわけですね。3つの複雑なフローを経る中で、一度、WordPress サイトにログインできる人間が、外部のアプリケーションに対して一度許可を与え、許可を与えられたアプリケーションが上記で述べたようなログインユーザーにしかできない処理を行えるようにする、という仕組みです。
賢いですねぇ。誰が考えたんだろう。この話は、高橋文樹さんも書いてくれていますので読んでみてください。
OAuth 認証で使う3つの エンドポイント URL
さて、上記の3つのフローですが、それぞれのステップに対応するエンドポイントURL があります。これらは WP REST API のプラグインが用意してくれるものです。
これらのエンドポイントURL は、 /wp-json
にアクセスするとご案内があります。
$.authentication.oauth1.request
: リクエストトークンをもらうためのエンドポイント$.authentication.oauth1.authorize
:認証用のエンドポイント$.authentication.oauth1.access
:アクセストークン取得用のエンドポイント
これから行なう3つのフローの中で、上記のURL にリクエストを送り、新しい情報をもらったり、ログインと認証を行うなどの作業をしていくことになります。
では、OAuth 認証フローを始めます。
Step 1: Temporary Credentials Acquisition (リクエストトークンの取得)
まずは、一時的な証明書(リクエストトークン)を貰いに行きます。エンドポイント URL は /oauth1/request
です。
このエンドポイントに対して、 Step 0 で取得してきた Client Key
と Client Secret
を使って作成した色々なものを組み合わせたリクエストを送ります。
下の画像は、Client Key
と Client Secret
を入力しているところです。
/oauth1/request
に送信する際のリクエストヘッダーは以下のようになりました。
GET /oauth1/request HTTP/1.1 Authorization: OAuth oauth_consumer_key="fbQ9KPUmdDLP", oauth_nonce="4Lxk40ujU5KQU7j53E06dKGlLwQkKm1W", oauth_signature="Ra%2BrRiy2tLKk9ub0qMABW4g57gQ%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1451907555", oauth_version="1.0" Host: wp-api.dev Connection: close User-Agent: Paw/2.2.7 (Macintosh; OS X/10.9.5) GCDHTTPRequest
2行目の Authorization: から始まる欄にいろいろな key=value
型のデータが入っています。
oauth_consumer_key
は WordPress の管理画面から取得したClient Key
のことです。oauth_nonce
は Paw が勝手に入れてくれています。nonce
はnumber used once
のことです。OAuth プロバイダ(ここではWordPress)が同じリクエストを2回以上処理しないようにするために送ります。oauth_timestamp
も Paw が勝手に作ってくれます。これは、認証に時間制限を持たせるためではなく(もちろんそうすることもできるけど)、nonce
やトークンをプロバイダが永遠に保持しておかないといけないのを防ぐためのものoauth_signature
も Paw が作ってくれます。これは署名で、作り方がポイントで、ざっくり概要を掴むと、以下の作り方になります。client key
や タイムスタンプ、nonce
などを組み合わせてある文字列を作成するclient key
とclient secret
を組み合わせた文字列を作成する- 上記の2つの文字列を、
HMAC-SHA1
というメソッドでハッシュ化する(あと、base64 エンコードもする)
サーバ側(WordPress側)では、送信されてきたこれらのデータを使って同じことを繰り返すことで、データを送信してきたクライアント(ここでは Paw アプリ)が悪いやつじゃないかを確認します。client secret
自体は送信しておらず、でも署名の生成過程の中には含まれている、というところがポイントです。上記のリクエストヘッダーの中でも、client secret
自体は送信していませんね。Paw に入力したのは signature
(署名)の生成のためなのでした。
サーバ側での確認が終わり、有効なクライアントであることがわかると、レスポンスを返してくれます。
oauth_token
、oath_token_secret
(と oauth_callback_confirmed
)が返ってきました。raw は以下です。
HTTP/1.1 200 OK Date: Mon, 04 Jan 2016 10:00:56 GMT Server: Apache X-Powered-By: PHP/7.0.0 Content-Length: 134 Connection: close Content-Type: application/x-www-form-urlencoded; charset=utf-8 oauth_token=CZpmXOtP98rsvrBk668QZZxE&oauth_token_secret=CTAdf4c1ZdLzoJJvC195VoMN3t9t3oPphK3sAbSceHYfUjwl&oauth_callback_confirmed=true
oauth_token
と oath_token_secret
がリクエストトークンと呼ばれる一時的な証明書(Temporary Credentials)です。
これが第一ステップでした。
Step 2: Authorize 認証
上記の oauth_token
を使って認証のステップに進むことができます。
oauth_token
を、2個目のエンドポイント URL である、 /oauth1/authorize/
に GET パラメータとして渡します。このステップでは、WordPressのログイン画面への転送や、人間による認証のプロセスがありますのでブラウザを使います。
つまり以下のURLにアクセスすることになります。
http://example.com/oauth1/authorize?oauth_token=<step1で取得してきたoauth_token>
このURLにブラウザでアクセスをすると、
- 「このアプリ(Paw)を認証しますか?」という人間向けの画面に転送される
- WordPress にログインをしていない場合には、その前にログイン画面に転送される
ここで、人間が登場してこのクライアントアプリに対して権限を与えることになります。ここで GET パラメータとして使われている oauth_token
は client key/secret
を知っていないと作れないことに留意ですね。
Authorize をクリックすると、以下のような画面になり、oauth_verifier
という値を受け取ることができます(これは CSRF を防ぐためのもので次のステップで使います。)。
またこの時、WordPress側ではこの oauth_token
が認証されたとマーキングされます。
ここまでで、Step 2は完了です。
Step 3: Token Exchange (トークンの交換)
最後のステップです。 verification token
を利用して3つ目のエンドポイントでトークンを long-lived のものと交換します。
Step 1 で取得した oauth_token
と oauth_token_secret
はリクエストトークンと呼ばれる一時的なものでした、これを、もっと長い期間使うことができるものに差し替えてもらいます。そうすると同じ oauth_token
、oauth_token_secret
ではあるもののアクセストークンと呼ばれるものになります。
交換が終わったら、アクセストークンを利用して交信を行うようになります。リクエストトークン、 verification token
は破棄してOKになりますし、保持していても意味のないものになります。
Paw での操作はちょっと複雑になります。エンドポイント URL は /oauth1/access/
となります。一番下の Additional Params 欄に oauth_verifier=<step2で取得したoauth_verifier>
を追加して POST 送信します。
送信ヘッダーは以下のようになります。
POST /oauth1/access/ HTTP/1.1 Authorization: OAuth oauth_consumer_key="fbQ9KPUmdDLP", oauth_nonce="cEsC2kNG16ETXhjmjCb4wOe0otwH6fhN", oauth_signature="KgLDxSAYSbkGh1htQwPPZ8PMoKw%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1451915663", oauth_token="CZpmXOtP98rsvrBk668QZZxE", oauth_version="1.0", oauth_verifier="Etrc3Asa5EYRikFxUN6WMzJT" Host: wp-api.dev Connection: close User-Agent: Paw/2.2.7 (Macintosh; OS X/10.9.5) GCDHTTPRequest Content-Length: 0
Step1 でリクエストトークンを取得した時と同様に、今回も
- client key / secret
- oauth_token , oauth_token_secret
- nonce, verifier, timestamp
を利用して文字列生成やハッシュ化を経て、 oauth_signature
が送信されます。ここでも *_secret
という名前のものは送信しないけれども、それらを利用して作られた oauth_signature
は送信しています。サーバ側でもkey や token およびそれらとペアになる secret は保持していますので、アクセストークンを渡してよいクライアントなのかの判断が可能になる仕組みです。
確認が済むと、新しい oauth_token
と oauth_token_secret
が発行されます。今後は、これを古いものと差し替えて利用します。アクセス権を示すトークンをアクセストークンと呼び、アクセストークンをリクエストするためのトークンをリクエストトークンと呼ぶ、というわけですね。
ここまでで OAuth 認証は完了です。
アクセストークンを使ってみる
アクセストークンを得られたので、投稿の更新や認証無しでは取得できないデータが受け取れるようになったかどうかを確認してみます。くわしくは次回以降やりますが、今回はこれらが本当に使えるのかどうかだけ確認してみましょう。
Paw の oauth_token
と oauth_token_secret
を差し替えて、これまでは取得できなかった投稿のメタデータをリクエストしてみます。
ちゃんと取れていますね。リクエストを見てみましょう。
GET /wp-json/wp/v2/posts/1/meta HTTP/1.1 Authorization: OAuth oauth_consumer_key="fbQ9KPUmdDLP", oauth_nonce="UqeSQCG8m1C4Px5QMcH2Je5OhEc6OQr7", oauth_signature="ZfwTyXEm3UE6CQJ5E52D82QNU%2B0%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1451916352", oauth_token="PdJ2r3GHkbKlwQNKb5OZoZRE", oauth_version="1.0" Host: wp-api.dev Connection: close User-Agent: Paw/2.2.7 (Macintosh; OS X/10.9.5) GCDHTTPRequest
仕組みとしては同じみたいですね。
というわけで、今日はここまで!
コメント
コメント一覧 (2件)
[…] This is a translation of a post of mine originally written in Japanese, and based on and following the flow described in a documentation written by @rmccue, the author WP REST API – OAuth 1.0a Server plugin, and the API. […]
[…] WP REST API の OAuth 認証の方法と何が起こっているのかとなぜそんなことをしているのか – Shinichi Nishikawa's […]