Web API
Memo
400エラーでは理由を返す
ほかのレスポンスステータスでは理由を返す必要はないが、400エラーではリクエストに問題があるということなので、フィードバックしたほうがよい。
リソースに改変を加えるエンドポイントでは、そのリソースを返す
フロンエンドと、バックエンドのテストで便利なので。リソースを返さないとDBを見てチェックしないといけない。
Bearerトークン
Bearerトークンは、セキュリティトークンのうちその利用可否が「トークンの所有」のみで決定されるもの。持参人トークン・署名なしトークンとも呼ばれる。
Bearerトークンはしばしば切符に例えられる。切符は乗り物への乗車=アクセスを制御するトークンである。切符の利用権利は単純に「切符を持ってきた人=Bearer」に付与される。誰が切符を購入し管理していたかは関係がない。極端な例では拾った切符であっても(切符の権利者でなくても)持ってきた人=Bearerに乗車権利が付与される。このように切符はBearerトークンと同じ性質を持っている。
Bearerトークンの対比としてproof-of-possessionトークン(PoPトークン、「所有の証明」トークン、記名式トークン)が挙げられる。PoPトークンはトークンの所有に追加してトークン権利を所有することの証明を必要とする[1]。Bearerトークンは切符に例えられるが、PoPトークンは国際線飛行機チケットに例えられる。国際線飛行機はチケットを提示するだけではなく、チケットに記された氏名の確認、すなわち権利所有者であることの証明が必要である(パスポートを利用する)。Bearerトークンは単純にトークンの所有のみが求められる点でPoPトークンと異なる。
CORSの簡単な仕組み
異なるドメインからのAPI呼び出しを制御して安全にする仕組み。なのでバックエンド、フロントエンドが別ドメインになっているときに考慮しないといけない。
フロントエンド側にバックエンド呼び出しが書かれているとき、バックエンド側で許可ドメインのヘッダーを入れてレスポンスを返して一致しないと、許可されない。通信する前にバックエンドに対してプリフライトリクエストを行って、許可されているかチェックする。
- FE -(FEのドメインを入れたプリフライトリクエスト)> BE -(BEの許可ドメインを入れたプリフライトレスポンス)>
- BEの許可ドメインにFEドメインが含まれる場合、本題リクエスト。 FE -(本題リクエスト)> BE -(レスポンス)> FE
という感じ。
バックエンドにクッキーの情報を渡す
認証をセッションによって行っているとする。ありがちな流れ↓だとする。
- ログイン成功時にセッションキーを発行し、DB・クライアントブラウザのCookieに保存する
- ログインが必要なページでは毎回、Cookieの値とDBの値が合致するかチェックしてログインしているか判定する
バックエンドとフロントエンドが同じ場合、クライアントは常にブラウザのためCookieをチェックできる。が、異なる場合は、クライアントはバックエンドへ直接アクセスしないために、バックエンドからクライアントCookieにアクセスできない。結果、常にセッションキーが一致しないのでログイン行為そのものは成功するが、再度ログイン画面に戻される挙動となる。
- クライアント →(○ Cookie)→ FE →(✗ Cookie)→ BE
解決策は、クッキーが渡されるようにすればよい。 FE → BE間のリクエストヘッダーに、クッキーをそのままつけるようにする。
Access-Control-Allow-Credentials: true
あるいはプロキシを使ってFE → BEをFE → FEに見せかけることでも可能。
クエリパラメータを使うとき
翻訳: WebAPI 設計のベストプラクティス - Qiita
フィルタ・ソート・検索はクエリパラメータを使う。ベースとなるURLはできるだけシンプルにリソースを示したものにする。機能はクエリパラメータで指定する。
Swagger
SwaggerはAPIドキュメントツールである。ymlやjsonを記述して、ブラウザで閲覧できる。 Railsでのラッパーライブラリはrswagで、自然に扱うことができる。
- リポジトリ rswag/rswag: Seamlessly adds a Swagger to Rails-based API’s
- コードの例 ruslantolstov/rswag-example: Demo how to use rswag-api, rswag-specs.
- 記法例 開発効率を上げる!Swaggerの記法まとめ - ZOZO TECH BLOG
まとまっているサイト。SwaggerでRESTful APIの管理を楽にする - Qiita
Reference
ProgrammingPercy
WebSocketのわかりやすい説明。
[RESTful API]パスパラメータ、クエリパラメータ、リクエストボディの違いと設計 - Qiita
- パスパラメータ
- クエリパラメータ
- リクエストボディ
の使い分け。
オリジン間リソース共有 (CORS) - HTTP | MDN
CORSのドキュメント。
なんとなく CORS がわかる…はもう終わりにする。 - Qiita
ドメイン間でのポリシー。
Rails のルーティング - Railsガイド
ルーティングの公式ドキュメント。
APIs Dashboard | ProgrammableWeb
パブリックAPI集。設計の例としても使える。
Archives
DONE Web API: The Good Parts | 水野 貴明 |本 | 通販 | Amazon
- 90
- URIとメソッドの関係は、操作するもの(リソース)と操作方法(何をするか)の関係であるといえる。
- だから名詞と動詞
- webページの通常のリンクはGETを使ってアクセスするものとみなされる。formを使うとpostとgetを選択できる。
HTTPのメソッドはHTTPリクエストヘッダの先頭行の最初に以下のようにつけられて、サーバに送信される。
GET /v1/users/123 HTTP/1.1 Host: api.example.com
POSTメソッドは指定したURIに属する新しいリソースを送信する、新しい情報を登録するのが本来の目的。
- POSTは指定したURIの配下にデータを登録する。
- PUTはリソースがすでにあって、それを更新する。
- PUTは完全に上書きし、PATCHは一部を上書きする。
- 他のサイトを参考にしながら単語を決める
- APIがバックエンドのテーブル構造を反映する必要はない
- すべてのAPIが同じデータ構造を返すために実際のデータをくるむための構造をエンベロープという。ステータスはHTTPヘッダにやらせればよいことで、冗長な表現となる。
- JSON構造はなるべくフラットにすべきだけど階層化したほうが絶対によい場合は階層化もあり
- 多くのAPIで同じ意味に利用されている一般的な単語を用いる
- なるべく少ない単語数で表現する
- 複数の単語を連結する場合、その連結方法はAPI全体を通して統一する
- 変な省略形は極力利用しない
- 単数形/複数形に気をつける
- 性別をどうするか
- 文字列保持のケースが多い
- 生物学的な性別が必要な場合はsex
- そうでない場合…社会的・文化的な性別の場合はgender
- エラーの形式を統一し、クライアント側でエラー詳細を機械的に理解可能にする
- 認証と認可の違い。
- 認証(Authentication)とは、「アクセスしてきたのが誰であるのかを識別すること」
- 認可(Authorization)とは、「特定のユーザに対してある操作の権限を許可すること」
- XSSは別のサイトでjavascriptを走らせることで情報を盗んだり不正な操作をさせること。対策はサニタイズして、外部のjavascriptを評価しないこと
- CSRF(XSRF)はpostなどのHTTPメソッドで別のサイトからURLアクセスさせること。対策はトークン、変更を加える操作はGET以外でやらないこと
- クライアントを信用せず、値を必ず検証する