REST APIの設計について、ログアウトAPIのHTTPメソッドについて社内で議論があったので、メモしておきます。
ログアウトといっても連携サービス(OpenID Connectなど)からのログアウトなど、サーバサイドでのユーザ属性の変化など、データ変更を伴うものではなく、単なるセッション切り替えの話です。
結論: 方針
方針としては以下のように決めていくのがいいかと思います。
- APIが存在しないべき:
- RESTfulならそもそもセッションのステートはサーバが持っていないはずなので、ログアウトAPI自体が存在しないべき.
- サーバサイドでDB変更などの処理を行っていないため、クライアントでtoken/sessionの破棄を行えば事足りるはず。
- DELETE:
- TokenのrevokeならDELETEだろう.
- 名前やエンドポイントがlogoutとかでも意味的にはtoken revokeならDELETEがRESTfulか.
- POST:
- RESTにこだわらず、ブラウザのprefetch等で勝手にログアウトされることを恐れるならPOSTにすべき.
- RESTfulではなくなるし、場合によってはAPI一貫性は捨てることになるかもしれない.
- サーバ側の設計思想というよりもクライアントの仕様を吸収するためのワークアラウンドとしての対応になる.
- GET:
- クライアントサイドからクッキー削除するだけなら、サーバサイドの変更がないクライアントのログアウト状態取得APIと割り切ってGETにするのも良い.
- REST APIと言えなくもなさそう.
- linkタグに埋め込むケースなど、frameworkによってはブラウザのpre-fetchを誘発してしまう可能性がある.
- (コメントより)CSRF攻撃を受ける可能性がある。
- 今回の例のようにサーバ側にロジックがなく、レスポンスもブラウザが受け取れなければ特に副作用がない。
- サーバ側にロジックがある場合は問題。
現状
POSTを採用する、という意見が有力です。
ツールAPIと割り切ってRESTっぽさを残してGET APIにするのも割と好きですが、社内では反論があり、pre-fetchの実害も可能性としてあるため、POSTにしよう、という話になっています。
そもそもそれほどRESTfulにAPIを設計できていないので、RESTらしさを求めるよりも実用性やわかりやすさを重視する方がいいですね。
この辺の妥協というか折衷は重要になるでしょう。
感想
もうぐちゃぐちゃですが、RESTfulの正解、って本当はあまりないのかもしれませんね。
tokenでの認証をベースにしていればDELETEを採用するのが僕は好きです。
(これをきっかけにtokenベースの認証に切り替えたくもあります)
こういう議論は正解がない(or正解では実現が難しい,冗長になりすぎる,わかりづらい,支持を得ない)ことで好き嫌いの問題や実環境の都合になりがちですが、API設計のコンセンサスをとって、選択していけるといいですね。
参考
stackoverflowの議論を中心に。
- DELETE派
sessionidやtokenを削除する、という意味でDELETEがRESTfulとされています - POST派
pre-fetchの弊害を避けるという理由だけでもPOSTを支持するには十分そうです.-
Logout: GET or POST?
2013/1/29の回答 -
HTTP Verbs
2016/2/25の記事
-
Logout: GET or POST?
- GET派
メソッドの副作用や冪等性からGETが支持されています.-
RESTfully design /login or /register resources?
2011/8/30の回答
-
RESTfully design /login or /register resources?
- その他参考
-
ログアウトはGETではなくPOSTで処理するべきか。
2012/3/16更新の記事
コメント欄でユーザが手軽にリクエストできる、という意味でGETが支持されたりもしてますね。
-
ログアウトはGETではなくPOSTで処理するべきか。