misskey-dev / misskey

🌎 A completely free and open interplanetary microblogging platform 🚀
https://misskey-hub.net/
GNU Affero General Public License v3.0
9.95k stars 1.35k forks source link

/signin の設計がおかしい可能性がある #14699

Closed syuilo closed 1 week ago

syuilo commented 1 week ago

Summary

仕様通り想定して飛んできているリクエストに対してエラーを返すのはおかしい

Purpose

Do you want to implement this feature yourself?

kakkokari-gtyih commented 1 week ago

成功時も次の入力項目を指示するときも200にして、レスポンスをこんな感じにする?

成功時

{
    "success": true,
    "id": "xxxxxxxx",
    "i": "xxxxxxxx"
}

次の入力項目を指示

{
    "success": false,
    "next": "password"
}
syuilo commented 1 week ago

そうね

kakkokari-gtyih commented 1 week ago

これでいくか

syuilo commented 1 week ago

successというよりfinishとかの方がよさそう

kakkokari-gtyih commented 1 week ago

うーん資格情報が足りない状態でのレスポンスに200は強い違和感を持ちますね

403が違うってのは多分そうなのですが、401は不適当ですし400あたりがよいと私は感じます (https://github.com/misskey-dev/misskey/pull/14700#issuecomment-2393353797)

@syuilo

anatawa12 commented 1 week ago

仕様通り想定して飛んできているリクエストに対してエラーを返すのはおかしい

私はおかしくないと思います。

資格情報が足りない状態でのレスポンスに200は強い違和感を持ちます

403が違うってのはある程度同意しますし、401は不適当ですし400あたりがよいと私は感じます

syuilo commented 1 week ago

API側の実装がこれで正しいとしたら、クライアント側をエラーが出ないようにリクエストするように修正するべきだわね

kakkokari-gtyih commented 1 week ago

API側の実装がこれで正しいとしたら、クライアント側をエラーが出ないようにリクエストするように修正するべきだわね

200を返さずにエラーを出さずにそれをしようとしたら結局前のログイン画面に戻ってしまう(新ログイン画面はエラーが返ってくる or 次の操作が示されることを前提に組まれている)

syuilo commented 1 week ago

そう、だからどちらかの設計がおかしいということになる

kakkokari-gtyih commented 1 week ago

エラーとして返ってくるのってそんなにまずいかしら

syuilo commented 1 week ago

そもそもsigninという名のAPIがsignin以外の処理(次のステップを指定するなど)を担当している時点で若干おかしい

syuilo commented 1 week ago

エラーとして返ってくるのってそんなにまずいかしら

とてもまずい 発生したエラーを報告するような仕組みが入っていたとしたら、(正常な手順で)ログインするたびにエラーが報告されることになる

anatawa12 commented 1 week ago

4xxを期待してリクエストすることも私はおかしくないと考えます。

私はHTTPのステータスコード上のエラーとプログラム上のthrowされるようなエラーとは別物と考えてます

syuilo commented 1 week ago

ステータスコードじゃなく、実際にプログラム上もエラーやfailedとして表現されている

anatawa12 commented 1 week ago

バックエンド的にはエラーではあると思う。

フロント的にはthrowしない方が適切かも

syuilo commented 1 week ago

バックエンド的にエラーなのだとしたら、フロントエンドはバックエンドがエラーになってしまわないように正しく実装するべきという話になる でも現在のフロントエンドの実装が問題ないのだとしたら間違っているのはバックエンドということになりそう

anatawa12 commented 1 week ago

そもそもsigninという名のAPIがsignin以外の処理(次のステップを指定するなど)を担当している時点で若干おかしい

これも資格情報不足でチャレンジ種別を返すはそこまでおかしくないと思います(401もそうなってるし)

kakkokari-gtyih commented 1 week ago

フロント的にはthrowしない方が適切かも

これはそうしてあるはず

syuilo commented 1 week ago

そこまでおかしくはないけど、ちょっとはおかしい(直感的ではない) ちょっとでもおかしいのであれば直した方が良い

anatawa12 commented 1 week ago

別のエンドポイントとして必要資格情報を返すエンドポイントは追加した方が良いかも

けどsigninは足りない資格情報がある時は4xxを返してあげるべきだと思う。(ここに必要資格情報を含めるかはどっちでもいいけど今あるならついてて良さそう)

kakkokari-gtyih commented 1 week ago

別のエンドポイントとして必要資格情報を返すエンドポイントは追加した方が良いかも

これすると二要素認証が有効化されているかどうかなどが簡単に取れてしまう(UserDetailedに二要素認証関連のプロパティが公開されているのと何ら変わらなくなる)ので目的を達成できなくなる(工夫次第かも?)

syuilo commented 1 week ago

エンドポイント分けると場合によってはリクエストが二度手間というか無駄になる場合がありそう

anatawa12 commented 1 week ago

これすると二要素認証が有効化されているかどうかなどが簡単に取れてしまう(UserDetailedに二要素認証関連のプロパティが公開されているのと何ら変わらなくなる)ので目的を達成できなくなる(工夫次第かも?)

これサインイン試行でも同じこと起きるものだと私は認識してるのですが違う感じですか(現状の理解不足があるかも)

kakkokari-gtyih commented 1 week ago

発生したエラーを報告するような仕組みが入っていたとしたら、(正常な手順で)ログインするたびにエラーが報告されることになる

そういうシステムって単純なHTTPリクエストのエラーもログ取るの?(throwされたときやUnhandled Exceptionに動くものだと思っていたけど)

kakkokari-gtyih commented 1 week ago

これすると二要素認証が有効化されているかどうかなどが簡単に取れてしまう(UserDetailedに二要素認証関連のプロパティが公開されているのと何ら変わらなくなる)ので目的を達成できなくなる(工夫次第かも?)

これサインイン試行でも同じこと起きるものだと私は認識してるのですが違う感じですか(現状の理解不足があるかも)

二要素認証(ワンタイムパスワード)が必要かどうかはパスワードを入力して送信するまでわからない(次に必要な資格情報を一回ごとに返す仕様になっているので)

syuilo commented 1 week ago

エラーとして返ってくるのってそんなにまずいかしら

とてもまずい 発生したエラーを報告するような仕組みが入っていたとしたら、(正常な手順で)ログインするたびにエラーが報告されることになる

一般にエラーは問題だとして通知・報告される傾向にある 例えばブラウザの開発者ツールでもリクエストがエラーになったら目立つようにされている けど今回のケースはこれら一連のフローは事前に想定されたもので、すべて仕様通りに動いてるわけだから問題であるとして通知される必要はない

kakkokari-gtyih commented 1 week ago

確かに想定されたリクエストがエラーとして表示されるのは気持ち悪いかも vs 一般のWebアプリとかのAPI見たらちゃんと対応するステータスコード返しているので問題ないのかも

image

anatawa12 commented 1 week ago

二要素認証(ワンタイムパスワード)が必要かどうかはパスワードを入力して送信するまでわからない(次に必要な資格情報を一回ごとに返す仕様になっているので)

なるほど

エラーを集める仕組みにかんしては後処理でどうにかするべきな気がする

別言語の例になっちゃうけどjavaのClassLoaderではとあるローダで見つからなかったのを例外とするんだけど、複数のローダを組み合わせて使う場合はそのエラーは別のローダへのフォールバックのトリガーになるので、ある意味意図しているもので、そういうのはthrowされたタイミングでログが残されるべきではないし残されないようにログの収集側がするべきだと私は思ってる

syuilo commented 1 week ago

本当に対応したステータスコードなのだろうか?

syuilo commented 1 week ago

API側もこのフローを想定して実装されているのだから、エラー系のステータスコードを返すのはおかしいように思う

syuilo commented 1 week ago

エラートラッキングサービスなどがあることからも分かるように、エラーは

といった観念が含まれているけど、今回はどれにも当てはまらない(仕様通りでこれを前提としたフローなのだから報告される必要もないし起こしてはならないものでもないし修正されるべきものでもない)

anatawa12 commented 1 week ago

HTTPのステータスコードには起こさないべきものという程の意味はないと思うけどなぁ...(そういう意味付けをしてるツールがあるかもしれないけど)

400はリクエストのどっかが期待したもの(今回は2faトークン等)ではなかったということで、実際サインインするという操作については足りないっていうエラーを返すべきだと思う

syuilo commented 1 week ago

実態にあまりそぐわない /signin という名前だから「情報が足りなかったらエラーにする」のが正しいように思えてしまうのだと思う これが /process-signin-flow みたいな名前だとしたらどうだろうか

kakkokari-gtyih commented 1 week ago

MisskeyはRESTじゃないからべつに https://github.com/misskey-dev/misskey/issues/14699#issuecomment-2393416190 のプラクティスに絶対に則っておくべきということはない(これが公開APIなら仕様が一般的ではなく受け入れ難いかもしれないけど、内部API(外部アプリが使用しないエンドポイント)なのでそのへんのハンドリングはある程度やりやすいようにしても良いのかも)

anatawa12 commented 1 week ago

これが /process-signin-flow みたいな名前だとしたらどうだろうか

あーこれなら200でもいいと感じる

syuilo commented 1 week ago

このAPIはサインインするにあたっての情報が足りない状態でリクエストされることを期待しているのだから何もエラー要素がない

kakkokari-gtyih commented 1 week ago

これが /process-signin-flow みたいな名前だとしたらどうだろうか

仮に /process-signin-flow 的な名称にするとして、/signin は消す?(Misskey Web上にあるのは対話式のサインインのみなのでおそらく使う機会はなくなる)

syuilo commented 1 week ago

消す

kakkokari-gtyih commented 1 week ago

/signin-flow とかでも良さそう