Open3

API設計のTIPS

ハトすけハトすけ

APIのパスに/admin/のようなroleを含めるべきか

  • 一般的には含めずに認証ヘッダに含まれるJWTにroleを含めて識別すべき
  • しかし 、/admin/のようなpathを含めることで middlewareレベルで統一した挙動を実現できる
  • ただし、同一リソースに対してさまざまなロールによるアクセスレベルが存在する場合、ロールごとにパスを作成するのは大変になる
  • 前提として、role制御はscopeによる認可制御よりも粒度が粗いことは理解しておく

結論
jwtのroleによる認可をシステムの前提としつつ、利便性のために採用するのはあり。
ただし、adminやanonなど、極端なroleぐらいしか採用できない。これらはセキュリティ的に特別扱いするのは全然OKだし、その労力に見合う対価はありそう。

ハトすけハトすけ

/parents/:parentId/children/:childIdのような親子リソースをAPIのパスで表現すべきかどうか?

  • childIdがグローバルユニークかどうかによる。グローバルユニークでなければparentsIdが必須になる。
  • もし仮に childIdが グローバルユニークであるとき、技術的には children/:childIdというAPI設計は可能
    • 本当は親子関係だけど、利便性やセキュリティのため、公開用idとして自然PKとは別にユニークidをもっているパターン
    • 何も考えずにとりあえず、サロゲートkeyをすべてのリソースで採用しているパターン
    • 真に親子関係かどうかを考えるには、親リソースを削除したときに、子リソースが独立して生存可能かどうかを考えれば良い
  • childIdがその公開idであれば、そもそもURLの短縮が目的なので素直にchildren/:childIdとすればよい
  • マルチテナント型のサービスの場合、多くは parentsIdはテナントidを示す。
  • この場合、基本的に /parents/:parentIdをAPIに含めた方が良い。
    • middlewareレベルで、childrenリソースがparentIdに属するものか検証しやすい
    • middlewareレベルで、リクエストアカウントがparentIdに属するか検証できる

結論

  • テナントリソースかグローバルリソースかを意識する
  • 将来のシャーディング(DB分割)を踏まえて、基本的に自然PKを採用する
  • セキュリティ的にリソースidを隠したい、URLを短くしたいなどのニーズがある場合、自然PKとは別に公開idを用意する
    • 公開idは将来シャーディングしにくいリスクがあることを承知する
  • リソースを扱うAPIは基本的に自然PKをAPIで表現する
  • マルチテナント型のサービスの場合、
    • 基本的には /tenants/:tenantId/をprefixとしてAPIに設定しておいたほうが、セキュリティを検証しやすい
    • リソースのネストが深くなってしまう場合(親 > 子 > 孫)、孫リソースを直接tenantIdの子として移動できないか考える(親 > (子、孫))。子(孫から見た直接の親)をPKとしてもたずFKとする。
ハトすけハトすけ

単一のリソースを指定するとき、/resources/:resourceIdとするか/resources?resourceId=:resorceIdとするべきか

結論

  • クエリは配列が返ってくる前提なので、単一のリソースはPKのidを指定する。これは複合PKの場合も同様