世界を動かす技術を、日本語で。

OAuthとは何ですか?

概要

OAuthの本質は「安全な委任」の標準化 歴史的背景と設計理由を中心に解説 OpenID Connectとの関係や進化の経緯 具体的なユースケース動機の紹介 複雑化の理由と設計思想の整理

OAuthの歴史と設計理由

  • OAuth は、ユーザーの パスワードを渡さず に他サービスへ権限委譲するための標準仕様
  • 2000年代半ば、 Twitter やFlickrなど多くのWebサービスが 外部アプリからのアクセス を求められる状況
  • 当時は各サービスが 独自仕様や非安全な方法 (パスワード直渡し等)を採用
  • これを解決するため、 共通の安全な枠組み としてOAuthが誕生
  • XKCD 927「標準の乱立」ジョークの通り、標準化の必要性の高まり

OAuthのコアアイデア

  • ユーザーの 明示的な同意 のもと、 委任先(アプリ)多用途な秘密情報(トークン) を発行
  • 委任先はそのトークンを使って、 ユーザーの代理 としてAPI等にアクセス
  • これにより パスワードを共有せず に安全な連携が可能
  • 具体的な流れ
    • ユーザーがアプリに権限付与を許可
    • アプリは発行されたトークンでAPIにアクセス
  • 設計動機 :Web 2.0時代の多様なクライアント(デスクトップ、ウェブ等)対応

OpenID Connectとの関係

  • OpenID Connect(OIDC) はOAuthの上に構築された「サインイン」用仕様
  • OIDCの本質は「 マジックリンク認証」に近い
    • ユーザーしかアクセスできない場所(例:メール)に秘密を送る
    • その秘密を提示できることで本人確認
  • OIDCは 認証(Authentication)、OAuthは 認可(Authorization) に主眼
  • OIDCの登場で、OAuthの応用範囲がさらに拡大

標準化の経緯と「フレームワーク」的性質

  • OAuthは 厳密な仕様 というより フレームワーク的 な側面
    • すべての実装が全機能を持つ必要はない(HTMLと同様)
  • 標準化には 合意形成・用語整理・UX設計 など多様な要素が関与
  • 標準の策定は セキュリティや相互運用性 確保のため、複雑化しがち
  • OIDCはOAuthとOpenIDの長所を組み合わせた進化形

OAuthが複雑に見える理由と本質

  • 本質は「 安全な委任」だが、標準化の過程で 多くの細則や例外 が追加
  • 実装時は「 何をしたいか」という目的意識が重要
  • 標準の複雑さに惑わされず、「 本当に必要な要件」を見極めることが肝要
  • 複雑に見えるのは、 実際の目標や動機が隠れてしまう から

まとめ:OAuth設計の根本動機

  • パスワード共有を避けたい という明確な要請
  • 安全性と利便性 の両立
  • 多様なクライアント・サービス連携 への対応
  • 標準化による相互運用性とセキュリティ向上
  • なぜこの設計なのか?」を理解することで、OAuthの本質が見えてくる

Hackerたちの意見

OAuthって実はすごくシンプルなんだよね。でも、シンプルになるまでに、誰も説明してくれない複雑な詳細をたくさん理解しなきゃいけないんだ。

「Twitterでログイン」っていうのが新しい革命的なアイデアだった頃に、OAuthログインを作ったことを思い出すよ。その頃は、詳細を扱うためのライブラリなんてなかったから、TwitterやFacebookのエンジニアが書いたブログを元に直接作ってたんだ。あの頃はまだ標準化もされてなかったと思う。あの辛い経験のおかげで、今はOAuthが本当にシンプルに感じるようになった。V2でかなり整理されたしね。

私にとって、MicrosoftのOAuth 2.0に関するページを読むのがすごく助けになったよ。イラスト付きのフローチャートがあって、それからRFCに戻るといい感じ。とはいえ、非自明な詳細がたくさんあって、特に多くの場合、OAuth 2.0を基にしたOIDCを扱わなきゃいけないから、急にJWKやら何やらに直面することになるんだよね。

OAuthについて、謙虚に言うと、もっと良いアナロジーを借りたいんだけど、ダグラス・クロックフォードからのもので、彼が関数型プログラミングのモナドについてコメントした内容をアレンジすると、こんな感じになる。「OAuthはシンプルなアイデアだけど、呪いがある:理解すると、説明する能力を失う。」

実装が正しいかどうかをチェックするためのバリデーションやテストスイートって、どこかにありますか?

たくさんの人が苦労する理由は、消費者の視点からOAuthを始めるからだと思う。つまり、彼らはデータをリクエストする第三者で、OAuthの実装はリソース保持者によって強制されるから、明確な理由がない多くの手続きを踏まなきゃいけない。サービスプロバイダーやリソース保持者の視点からOAuthを始めると、全てがクリアになるよ。ウェブセキュリティもそんな感じで、CORSやHTTPSのような問題に直面する人は、セキュリティの問題を解決しようとしているわけじゃなくて、上流のプロバイダーがユーザーのデータを信頼されるためにセキュリティ基準を上げるように強制されているからなんだ。

うまく解決できるといいですね!ありがとう、でもできなかった。OAuthとOpenID Connectは、それを扱わなきゃいけない人間の脳に対するサービス拒否攻撃だよ。

自宅のラボでOIDC(Autheliaを使って)を使ってるけど、すごく簡単に扱えるよ。何をやってるのかよく分からないけど、ドキュメントを信じてるし、特に難しい設定ってわけでもないんだ。

AはBにアカウントを持ってて、Cにも別のアカウントがある。AはCにBのデータにアクセスさせたい(またはAの代わりにBにデータを送信させたい)。BはCがAの代わりに行動しているとどうやって確信できるの?Aはリスクを減らすためにCに特定のデータだけにアクセスを許可することはできるの?その三者間の交渉を可能にするプロトコルがOAuthなんだ。ほとんどの仕様書と同じように、複雑さは後の年に、何千人ものユーザーや複雑なエッジケースを持つ企業によって追加されていくんだ。彼らが議会を支配していて、彼らのニーズが新しいバージョンを推進してる。だから、ほとんどの仕様を学ぶ最良の方法は、古い仕様から新しいものに学ぶことだよ。OAuth2を最初に読んだり使ったりすると、余計な複雑さに圧倒されるから、現役の専門家もそんな風には始めてないよ。追いつきたいなら、いつも古い仕様やバージョンから始めるのがいいよ。

OAuthをクライアントとサーバーの両方で実装したことがあるけど、一番複雑なのは散らばったドキュメントや、異なるプロバイダーからのちょっとしたトラブルだね。全体としては、そんなに複雑じゃないんだ。

いや、それはSAMLのことを考えてるよ。

完全に同意だね。OAuth、Auth0、Okta、OIDC。

OAuthはRFC7517を学ぶまで、あまり意味がわからなかった。JSON Web Keysを使うことで、参加者が「このURLのすべてのキーは有効です。もし不明な場合はここをチェックしてください」と言えるようになる。最大の利点は、他のパーティに通知したり頼ったりせずに、証明書をローテーションできること。新しい信頼できるパーティをURLを提供するだけでオンボードできるし、これを徹底すれば手動の証明書交換も不要になる。多くのフィンテックベンダーがこの方向に進んでいるのを見ているよ。相互のクライアントは、アクセスに対してより細かい制御を求めている。これらの新しいスキームでは、リソーストークンは数分しか有効じゃない。ほとんどの場合、同じユーザー名とパスワードを使って銀行のコアにアクセスしていた世界から来ているんだ。

ここの中心の段落は本当に理解しづらいね。「OAuthのコアは、委任のための標準的な方法で、最初の半分は、同意をもって、既知の委任者に多用途の秘密を送ることに存在する。OAuthのもう一方の半分は、その委任者がどのようにその秘密を使って、同意を与えた人の代わりにその後のリクエストを行うことができるかを詳細に説明している。」この段落には定義が必要な言葉がたくさんあって(「委任者」という言葉はそのページには出てこないし)、'最初の半分'、'第二の半分'の使い方も混乱する。最初の半分って何の半分?もっとわかりやすく説明できるはずじゃない?

その文は正しいし、OAuthを正確に説明してるよ。デリゲートってただの標準的な言葉だから、辞書で調べてみて。内部の技術的定義はまさにその文の中にあるんだ。 >「何の前半か」 仕様書、標準の半分はXについて、もう半分はYについて扱ってる。つまり、一方はユーザーが第三者に許可を与える方法で、もう一方はその第三者がメインのデータ保持者にリクエストをする方法だよ。別の定義が必要なら、OAuthはユーザー、サービスプロバイダー、第三者の三者間プロトコルだよ。ユーザーは特定の権限を第三者に与えて、サービスプロバイダーがその第三者と特定のリソースを共有できるようにするんだ。

https://youtu.be/996OiexHze0?is=5OPbjDzeMAo-UmNE もう10年近く前のクラシックな解説動画だね。元々解決するために設計された問題の視点から説明してるよ。

これがOAuthについて知っておくべき唯一のことだよ。ちなみに…Eran HammerはOAuth 1.0の著者で、OAuth 2.0仕様の初期エディターだよ。 [1] 「…Eran HammerはOAuth 2.0プロジェクトのリード著者の役割を辞任し、IETF作業部会から撤退し、2012年7月に仕様から名前を外した。Hammerは、ウェブとエンタープライズ文化の間の対立を辞任の理由として挙げていて、IETFは「エンタープライズユースケースに関するコミュニティ」であり、「シンプルなことには対応できない」と述べている。「今提供されているのは、認可プロトコルの青写真であり、それはエンタープライズのやり方で、コンサルティングサービスや統合ソリューションを売るための新しいフロンティアを提供している」と彼は指摘している。OAuth 2.0とOAuth 1.0を比較すると、Hammerは「より複雑で、相互運用性が低く、役に立たず、未完成で、最も重要なことに、セキュリティが低下した」と指摘している。彼は、2.0のアーキテクチャの変更がクライアントからトークンを解放し、プロトコルレベルで全ての署名と暗号化を削除し、トークンが取り消せないために期限切れのトークンを追加し、認可処理を複雑にしたことを説明している。仕様には「この作業部会の性質上、どんな問題も小さすぎて詰まったり、各実装が決めるために開けておくことはない」として、多くの項目が未指定または無制限のままだった。David Recordonも後に、未指定の理由で仕様から名前を外した。Dick Hardtがエディターの役割を引き継ぎ、フレームワークは2012年10月に公開された。メールクライアントPegasus Mailの著者David Harrisは、OAuth 2.0を「絶対にめちゃくちゃ」と批判し、開発者が各サービス(Gmail、Microsoft Mailサービスなど)に特有のカスタムモジュールを書く必要があり、特にそれらに登録しなければならないと指摘している。」 [1] https://en.wikipedia.org/wiki/OAuth

Googleのログイン確認方法10種類のリストが大好き。OAuthは最高だね。MFAは永遠に!

IETFは「企業のユースケース」に特化したコミュニティで、「シンプルなことができない」。彼は「今提供されているのは認可プロトコルの青写真であり、企業のやり方だ」と指摘し、「コンサルティングサービスや統合ソリューションを販売するための全く新しいフロンティアを提供している」と述べた。ロックダウン中に行われたインディーやフェディバースのカンファレンスでのOAuth 2.0に関するトークの終わりに、当時Oktaに勤めていたアーロン・パレッキが、実際にサービスを必要とするプロトコル/フローの部分を分離する価値があるのではないかと尋ねられた。つまり、あなたの「プロバイダー」が静的サイトをホスティングしている個人ドメインの場合でも、限られた認証やアイデンティティタグ付けができるようにするためだ。彼はすぐに、リモートカンファレンスだったから、仮想の部屋で最も愚かな人に話しかけているかのように振る舞い、そんな愚かな質問に対処することで肉体的な痛みを感じているかのように反応した。

一方、暗号技術のエンジニアリングの界隈では、「少なくとも変な暗号試みは全部取り除かれたから、今は同一オリジン/TLSのセキュリティだけだね」っていうのが一般的な感想だったと思う。

個人的には、oauthプロバイダーにアプリを登録する必要があるのはプラスだと思う。

どうしてこういうデザインになっているのか理解したいし、そのデザインを促す具体的なユースケースも見たい。著者は質問を褒めつつ、全く答えないという技を見せたね。

OAuthのドキュメント自体を読んでるみたいだけど、なんか自分が理解できてないんじゃないかって思っちゃうような言い回しなんだよね。OAuthのドキュメント全体が、ぼーっと読んでるか、疲れてるときに目がさまよって、現実に戻るまで何も理解できない感じ。

OAuthを仕事で結構扱ってきた者として、基本的には好きだけど、めちゃくちゃ大きくて複雑なんだよね。ほとんどの人がOAuthを「三脚リダイレクト」フローだと思ってる。あるサイトが別のサイトに送って、「はい、承認します」と言って戻ってくると、そのサイトが他のサイトで自分の代わりに行動できるようになる。でも、それは氷山の一角に過ぎないんだ!これは「認可コード」グラントって呼ばれていて、実装的には一つのサイトが特別な一回限りの認可コードをもう一つのサイトに渡して、それをサーバー間で交換して実際の敏感なアクセス資格情報を手に入れるんだ。もしその瞬間に人間が関与していなかったら?それが「クライアント資格情報」グラントだよ。テレビとかの限られた入力デバイスだったら、「デバイス」グラントになるし、クライアントがクライアントシークレットを安全に保存できない場合、つまりシングルページのウェブアプリやモバイルアプリの場合は、パブリッククライアントにしなきゃいけなくて、フローの整合性のためにPKCEやPARを使うことになる。もしクライアントを事前に設定できない場合は?DCRがあって、今はMCPとともに重要なんだ。でも、それだと認証されていないリクエストがデータストアにリソースを作成するのを許可しちゃうか、他の認証手段でブートストラップする必要がある。全体として、すべてを試みるからこそ、ただの巨大なフレームワークになってるんだ。

ただの巨大なフレームワークになってるんだ、だってすべてを試みるから。そうだね、確かにそうなりがちだけど、必ずそうなるわけじゃない。必要なものによるし、もしマシン間認証みたいなものが必要で、クライアントを事前に設定できないなら、何か手を打たなきゃいけないし、他の人が知ってるものを使えばいいんじゃない?

ただの巨大なフレームワークになってるんだ、だってすべてを試みるから。私も仕事でOAuthを結構使ってるよ。SAMLも扱ったことがあるけど、週のどの日でもSAMLよりOAuthを選ぶね。単にOAuth(少なくともv2)が7年若いからだけじゃなくて、OAuthはその広がりがあるにもかかわらず、焦点を当てるべき部分を選べるし、時間とともに進化してきたから。全体のフレームワークはみんなのニーズに応えようとしてるけど、異なる仕様やRFCを通じてそれを実現してる。一方、SAMLは800ページの巨大な仕様で、時が止まってる。利用可能なツール(XMLとか)を使って、みんなのためにすべてになろうとしたけど、仕様は進化してないし(WGも閉鎖された)、決して消えないよ。多くの既存システムにとって解決策として埋め込まれすぎてるから。OAuthの代わりになるものが何かも分からない。GNAPを見たけど、OAuthに匹敵するものは見当たらないね。

ただの巨大なフレームワークになってるんだ、だってすべてを試みるから。そうだね、でも同時にそれは素晴らしいことでもある。すべてのことを扱ってくれるから。でも、全部使う必要はないんだ。私にとってOAuthのポイントは、認証層で起こる複雑な混乱があっても、最終的にはベアラートークンと多分リフレッシュトークンが得られることなんだ。自分でその認証の混乱を構築することもできるし、いくつかの異なるサードパーティプロバイダーを使ってそれをやってもらうこともできる。彼らはみんな同じベアラーとリフレッシュトークンをくれるから。そうすれば、認証を気にせずにアプリを構築できるんだ。すべてがそのOAuthのボックスの中で処理されるから。今、クライアント資格情報グラントからのリクエストを処理してるのか、認可コードグラントからのリクエストを処理してるのか?それがPKCEクライアントだったのか?クライアントの外では関係ないよ。

最初の方でのOAuthの良い説明だね。でも、著者は具体的な質問に対してあまり良い答えをしてないと思う。この兄弟コメントの方がずっといいよ[0]。私はこの部分が好きなんだけど[1]、私も手伝って書いたから。OAuth/OIDCのさまざまな一般的なモダリティをカバーしてる。(正直言って、分けるのは本当に難しいよ;しばしば混同されるから。)以前にHNで話題になったね[2]。 0: https://news.ycombinator.com/item?id=47100073 1: https://fusionauth.io/articles/oauth/modern-guide-to-oauth 2: https://news.ycombinator.com/item?id=29752918

上で言ったoauth2-proxyの提案が、これには一番簡単な方法かもね。nginxレベルのoauthで気をつけるべきことは、トークンの有効期限だよ。短命のトークンを設定する必要があるけど(それがベスト)、プロキシ層がリフレッシュを静かに処理しないと、友達がセッション中にログイン画面に戻されちゃうからね。もし数人のためにGoogleやGitHubのログインが必要なだけなら、メールのホワイトリストを使ったoauth2-proxyの方が、フルのアイデンティティプロバイダーを運営するよりずっと楽だよ。