TwitterのOAuthの流れを整理しておく
これはなに
SPAでTwitterのOAuthを実装しようとしていたのだけど、
Twitter Developerで取得できる
Consumer API key
Consumer API key secret
このあたりをどうやって隠蔽するのかというのを考えていたらよくわからなくなってきたので、
基礎知識としてサーバーサイドでTwitter認証する時の流れを整理しておく。
※Consumer API keyは過去にConsumer tokenと呼ばれていたらしい。今は名前が変わった。
TwitterのOAuthの流れ
TwitterのDeveloperアカウントを設定して払い出されるConsumer API key
,Consumer API key secret
を使って、
任意のユーザーがAPIを呼び出すためのaccess_token
,access_token_secret
を得るのがゴール
流れは下記のとおり
Consumer API key
,Consumer API key secret
を使ってrequest_token
を得るhttps://api.twitter.com/oauth/authenticate?oauth_token={$request_token}
に遷移oauth_token
とoauth_verifier
を使ってアクセストークンを発行する
1. request_token
を得る
まずはrequest_token
を得る
これはConsumer API key
,Consumer API key secret
を使って、oauth/request_token
にPOSTリクエストを投げると取得することができる。
ちなみにoauth_callback
というパラメーターにTwitterDeveloperのcallback
に指定したURLのいずれかを設定してリクエストを送信する必要がある。
2. request_token
認証を使って認証画面に遷移する
前の手順で得られたrequest_token
をoauth_token
パラメーターにつけて
https://api.twitter.com/oauth/authenticate?oauth_token={$request_token}
というURLにアクセスすると、Twitter側の提供されるログイン画面に遷移する。
※oauth_token={$request_token}
がすでに気持ち悪いが気にしない。
3. アクセストークンを発行する
連携画面でログインが成功すると、callback
で指定したURLに遷移する。
遷移時のGETパラメーターに
oauth_token={$oauth_token}&oauth_verifier={$oauth_verifier}
という形でパラメーターが付与されるので、
Consumer API key
,Consumer API key secret
,oauth_token
, oauth_verifier
をつかって
oauth/access_token
に対してPOSTのリクエストを投げる。
するとaccess_token
とaccess_token_secret
が得られる。
複雑なように見えるが実際は三度の通信が走るだけになっている。
※なおTwitterのOAuthはシグネチャを生成して、リクエストに含める必要がある。 リクエストパラメーターやtokenをひとまとめにしたデータを先性して、パラメーターを送信し整合性チェックを行う設計らしい。
ファイル末尾に自動的に改行文字を挿入する(VSCode)
VSCodeを利用していて、ファイルの末尾に自動的に改行コードを加えたくなるときがありました。 具体的にはSchema作成用のSQLファイルを作っていると、最後に改行文字が必要なのですが、 大体これを入力し忘れる。
自分はメインのエディタがVSCodeなので、VSCodeで末尾に自動的に改行文字を挿入する設定をまとめました。
VSCodeのPreferenceを開く
設定画面で
files.insertFinalNewline
で検索
files.insertFinalNewline
で設定を検索して、こちらの設定をONにしてください。
jsonで設定ファイルを記述する場合は"files.insertFinalNewline": true
です。
以上。
LaravelでAjaxリクエストかFormリクエストかどうかは誰が判定しているか
LaravelでAPIを書いていて、適当なRestClientを使ってリクエストを送った際に、 Validationエラーで引っかかると、HTTPステータスコード302でリダイレクトされるということがあった。 APIなので、単純にValidationのエラー結果をjsonなりで返してくれればいいのだけどHTTPヘッダーが不足していた。
FormリクエストだとValidationに引っかかった時に、もとのページにリダイレクトして、 Ajax通信の場合はjsonを返すという仕様は公式ドキュメントにも書かれている。
AJAXリクエストとバリデーション この例ではアプリケーションにデータを送るために伝統的なフォームを使いました。しかし、多くのアプリケーションでAJAXリクエストが使用されています。AJAXリクエストにvalidateメソッドを使う場合、Laravelはリダイレクトレスポンスを生成しません。代わりにバリデーションエラーを全部含んだJSONレスポンスを生成します。このJSONレスポンスは422 HTTPステータスコードで送られます。
結論から言うと、
X-Requested-With
ヘッダーにXMLHttpRequest
を渡せば、Ajaxリクエストとして判定してくれてValidationエラーの内容がjsonで返ってくるのだけど、
少し気になったのでコードを読んでみた。
vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php
/** * Create a response object from the given validation exception. * * @param \Illuminate\Validation\ValidationException $e * @param \Illuminate\Http\Request $request * @return \Symfony\Component\HttpFoundation\Response */ protected function convertValidationExceptionToResponse(ValidationException $e, $request) { if ($e->response) { return $e->response; } return $request->expectsJson() ? $this->invalidJson($request, $e) : $this->invalid($request, $e); }
vendor/laravel/framework/src/Illuminate/Http/Concerns/InteractsWithContentTypes.php
/** * Determine if the current request probably expects a JSON response. * * @return bool */ public function expectsJson() { return ($this->ajax() && ! $this->pjax() && $this->acceptsAnyContentType()) || $this->wantsJson(); }
vendor/laravel/framework/src/Illuminate/Http/Request.php
/** * Determine if the request is the result of an AJAX call. * * @return bool */ public function ajax() { return $this->isXmlHttpRequest(); }
vendor/symfony/http-foundation/Request.php
/** * Returns true if the request is a XMLHttpRequest. * * It works if your JavaScript library sets an X-Requested-With HTTP header. * It is known to work with common JavaScript frameworks: * * @see http://en.wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript * * @return bool true if the request is an XMLHttpRequest, false otherwise */ public function isXmlHttpRequest() { return 'XMLHttpRequest' == $this->headers->get('X-Requested-With'); }
こんな感じ。