3rd Party API on Rails
by
tsuwatch
×
Copy
Open
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Slide 1
Slide 1 text
3rd Party API on Rails Kaigi on Rails 2022 2022.10.21 - 22 @internet(online) 株式会社ZOZO ブランドソリューション開発本部 バックエンド部 ディレクター 諏訪 智大(@tsuwatch) Copyright © ZOZO, Inc. 1
Slide 2
Slide 2 text
© ZOZO, Inc. 株式会社ZOZO ブランドソリューション開発本部 バックエンド部 ディレクター 諏訪 智大 2015年ドワンゴ入社、2021年4月ZOZO入社 WEAR開発責任者 Twitter/GitHub: @tsuwatch 2
Slide 3
Slide 3 text
© ZOZO, Inc. https://wear.jp/ 3 ● ファッションコーディネートアプリ ● 1,600万ダウンロード突破、コーディネート投稿総数は1,300万件以上 (2022年6月末時点) ● ピックアップタグから最新のトレンドをチェック ● コーディネート着用アイテムを公式サイトで購入可能 ● WEAR公認の人気ユーザーをWEARISTAと認定。モデル・タレント・デザ イナー・インフルエンサーといった各界著名人も参加
Slide 4
Slide 4 text
© ZOZO, Inc. 4 今日お話しすること
Slide 5
Slide 5 text
© ZOZO, Inc. 5 APIの公開 ● WEARのコーディネートデータを広く活用し、他サービスを通じてファッションの悩みを解決 ○ コーディネート検索APIを提供 ■ Yahoo!天気 ● 現在の天気からおすすめのコーディネート ■ Yahoo! BEAUTY ● 髪型に合っているコーディネート ■ ZOZOTOWN PayPayモール店 ● 販売している服を使用したコーディネート 背景 ※ 実際のYahoo! 天気アプリでの表示
Slide 6
Slide 6 text
© ZOZO, Inc. 6 APIの公開 ● 実現したいこと ○ 利用できるクライアントを限定 ○ 利用できるエンドポイントをクライアントごとに限定 ○ セキュアに提供 どう公開するか?
Slide 7
Slide 7 text
© ZOZO, Inc. 7 APIの公開 ● OAuth2.0 ○ サードパーティーアプリケーションによるHTTPサービスへの限定的なアクセスを可能にする認可フレームワー ク ○ スコープによってリソースへのアクセスを制御 ○ 安全 どう公開するか?
Slide 8
Slide 8 text
© ZOZO, Inc. 8 アプリケーションの構成 ● WEAR ○ API ■ WEARアプリ用既存API ○ 3rd Party API ■ 3rd Party用新規API ● リソースの取得、スコープの確認 ● AuthZ Service ○ API ■ AccessTokenの発行、検証 ■ 公開鍵の提供 ○ Management Web ■ 開発者用管理画面 ● クライアントIDの発行
Slide 9
Slide 9 text
© ZOZO, Inc. 9 スコープの設計 ● 仕様 ○ 大文字と小文字を区別しない ○ スペース区切りのリストで表現 ○ 省略した場合無効とするかデフォルト値とする ○ https://www.rfc-editor.org/rfc/rfc6749#section-3.3 ● 例 ○ Twiiter ■ tweet.read ● TwitterのツイートをGETする系のAPIが使える とても自由度が高く、どう作るか自分たちで考える必要がある
Slide 10
Slide 10 text
© ZOZO, Inc. 10 スコープの事例 ● スコープ例 ○ repo ■ repo:status ■ repo:invite ○ write:packages ○ read:packages ○ admin:org ● コロンでネームスペースを区切ってうまく考えている印象 ○ 権限:リソース、リソース指定だけで全権限 ● スコープ指定なしでパブリックな情報へのアクセス権限付与 GitHub OAuth Apps
Slide 11
Slide 11 text
© ZOZO, Inc. 11 スコープの事例 ● スコープ例 ○ https://www.googleapis.com/auth/youtube.readonly ■ YouTubeアカウントの表示 ○ https://www.googleapis.com/auth/youtube.upload ■ YouTube動画のアップロード、管理 ● URLの形式 ○ text/plainでスコープ名がレスポンスされる ○ パスに権限が表現されている ○ 内部でこのURLにアクセスして動的になにかしら制御している? YouTube Data API
Slide 12
Slide 12 text
© ZOZO, Inc. 12 スコープの事例 ● スコープ例 ○ profile ○ profile%20openid%20email ● スペース区切りのリストで表現はされているが、特定の組み合わせのみサポート LINE
Slide 13
Slide 13 text
© ZOZO, Inc. 13 スコープの事例 ● スコープ例 ○ tweet.read ○ tweet.write ○ users.read ○ follows.write ● GitHubと似ているドット区切りで指定 ○ リソース.権限 Twitter
Slide 14
Slide 14 text
© ZOZO, Inc. 14 スコープの事例 サービス スコープ例 GitHub ● repo ○ repo:status ● write:packages ● admin:org YouTube ● https://www.googleapis.com/auth/youtube.readonly ● https://www.googleapis.com/auth/youtube.upload LINE ● profile ● profile%20openid%20email Twitter ● tweet.read ● users.read ● follows.write
Slide 15
Slide 15 text
© ZOZO, Inc. 15 スコープの設計 ● リソースサーバが使用するフレームワークや提供するAPIによって変わりそう ○ 今回はRESTful APIへの認可 ■ リソース単位で権限を付与 ● RESTと相性がよく、明快 ■ リソースに対するアクションで権限を分割 ● リソースに対して何でもできるのは権限として大きすぎる
Slide 16
Slide 16 text
© ZOZO, Inc. 16 スコープの設計 ● HTTPメソッドとリソースを組み合わせる ○ 権限 ■ HTTPメソッド(GET、POST、PATCH) ○ リソース ■ パス ● 例 ○ get:coordinates ○ post:coordinates RESTful APIとスコープ
Slide 17
Slide 17 text
© ZOZO, Inc. 17 スコープの設計 ● Railsのコントローラは便利 ○ action_name ■ メソッド名を取得可能 ○ controller_name ■ コントローラ名を取得可能 ● 例 ○ create:coordinates ○ update:coordinates Ruby on Railsとスコープ
Slide 18
Slide 18 text
© ZOZO, Inc. 18 WEARで導入しているスコープ ● Ruby on Railsでエンドポイントごとにスコープを分割するのは簡単にできそう ○ 細かく分割しすぎるとスコープの管理コストがとても高い ○ 作成権限を付与して、更新権限がないというのはあまり考えられない ● 結論 ○ read or write:controller_name ■ リソース名はcontroller_nameで取得しつつ、権限はもう少し大雑把にする ■ readとwriteで分割 ● read ○ GET ● write ○ POST、PUT、PATCH、DELETE 結局どうしたのか
Slide 19
Slide 19 text
© ZOZO, Inc. 19 スコープの検証 def required_read_scope scope_name = "read:#{controller_name}" render_unauthorized unless current_access_token.scopes.include?(scope_name) end def required_write_scope scope_name = "write:#{controller_name}" render_unauthorized unless current_access_token.scopes.include?(scope_name) end 権限ごとにメソッドを実装
Slide 20
Slide 20 text
© ZOZO, Inc. 20 スコープの検証 class CoordinatesController < ApplicationController before_action :required_read_scope, only: [:show] def show; end end before_actionで制御
Slide 21
Slide 21 text
© ZOZO, Inc. 21 1st Partyでも利用したい ● ほぼほぼ全APIが利用可能 ○ allというスコープを用意し、read、writeで制御しているスコープについて全権限付与 def required_read_scope return if current_access_token.scopes.include?('all') scope_name = "read:#{controller_name}" render_unauthorized unless current_access_token.scopes.include?(scope_name) end def required_write_scope return if current_access_token.scopes.include?('all') scope_name = "write:#{controller_name}" render_unauthorized unless current_access_token.scopes.include?(scope_name) end
Slide 22
Slide 22 text
© ZOZO, Inc. 22 特定クライアント専用のAPIを提供したい ● 権限とリソースの組み合わせのスコープ ■ クライアント間でユニークなスコープではない ● 意図しないクライアントにも権限が付与されてしまう可能性 ● zozotownなどのクライアント名をスコープとして追加 ○ クライアント単位でユニークなスコープを作成 ■ 特定のクライアントからのみ利用されることを保証
Slide 23
Slide 23 text
© ZOZO, Inc. 23 特定クライアント専用のAPIを提供したい ● クライアント名でスコープを作成 ○ allを付与していても利用できなくすることが可能 def required_specified_scope(custom_allow_scope) render_unauthorized unless (custom_allow_scope & current_access_token.scopes).present? end class CoordinatesController < ApplicationController before_action -> { required_specified_scope(‘zozotown’) }, only: [:show] def show; end end
Slide 24
Slide 24 text
© ZOZO, Inc. 24 実際に導入してみて ● controller_nameが同じになってしまい、意図せず権限を付与してしまうケース ○ 例:read:coordinates ■ GET v1/coordinates/:id(CoordinatesController#show) ● コーディネートの詳細 ■ GET v1/companies/:id/coordinates(Companies::CoordinatesController#index) ● Companyのコーディネート一覧 ○ 企業のコーディネート情報の権限は付与したくない場合の回避策 ■ 新たな権限を設ける ● company:coordinates ■ スコープを意識したパスを考える ● read:company_coordinates ■ ネームスペースも含める ● read:companies::coordinates
Slide 25
Slide 25 text
© ZOZO, Inc. 25 実際に導入してみて ● スコープとAPIを同時に設計する必要がある ○ APIを実装したら半自動的にスコープ名も決定 ■ 誰のためのどういうリソースなのかを考える必要があり、良い設計になりやすい ● ※APIを実装しようと思ったらすでに同名エンドポイントがあり、既存APIの処理内容に違和感があるとい うことが起こりにくくなりそう ● スコープ名を見ただけでどのエンドポイントが利用できるか影響範囲がわかりやすい
Slide 26
Slide 26 text
© ZOZO, Inc. 26 今後の課題 1st Partyでの使用 ● WEARのWEBサイトでも1st PatryとしてAPIを利用している ○ ログインしていない(アクセストークンが存在しない)ユーザーにもAPIを提供しなければならない ● 同じエンドポイントでもアクセストークンを検証する場合としない場合を制御する必要
Slide 27
Slide 27 text
© ZOZO, Inc. 27 今後の課題 ● 各社制限のつけかたは十人十色 ○ 全エンドポイント、エンドポイント単位、特定のグループ単位 ● 一応RFCに仕様があるので従っておいたほうが良さそう ○ https://datatracker.ietf.org/doc/html/draft-polli-ratelimit-headers-01 ○ レスポンスヘッダ ■ RateLimit-Limit: 単位時間内の割り当てられているリクエスト数 ■ RateLimit-Remaining: 単位時間内に割り当てられている残りのリクエスト数 ■ RateLimit-Reset: 割り当てがリセットされるまでの時間 ○ リソースサーバでアプリケーションごとに実行回数をDBなどに保存してレスポンスするとか Rate Limit
Slide 28
Slide 28 text
© ZOZO, Inc. 28 まとめ ● Ruby on Railsで外部にAPIをOAuthで提供しました ○ スコープの設計が大切 ■ controller_name、action_nameが便利 ○ 良いAPIになりやすい ● まだまだやるべきことは残っている ● みなさんもAPIを公開していきましょう
Slide 29
Slide 29 text
No content