【编者按】这篇文章介绍了 OAuth 的实践中的问题,如:OAuth 标准过于庞大和复杂、每个人的 OAuth 都有细微的不同、许多 API 在 OAuth 中添加了非标准的扩展、 调试 OAuth 很难、在 API 之上构建应用需要繁琐的审批、OAuth 存在安全性问题等。作者构建的一个开源服务 Nango,它旨在简化 OAuth 的流程和提高安全性,适用于多种 API,来解决这些问题。
链接:https://www.nango.dev/blog/why-is-oauth-still-hard
未经允许,禁止转载!
作者 | Robin Guldener 译者 | 明明如月
责编 | 夏萌
出品 | CSDN(ID:CSDNnews)
我们为 50 个最受欢迎的 API 实现了 OAuth。结果:一言难尽。
图源:nango.dev
OAuth 是一个标准协议,它支持 OAuth 2.0 的客户端库已经存在,几乎适用于你能想象到的所有编程语言。你可能因此会得出结论,有了客户端库,你应该能在大约 10 分钟或至少一小时内实现任何 API 的 OAuth。然而,理想很丰满,现实很骨感。很难想象一个人能够在 10 分钟或一小时内实现任何 API 的 OAuth。
实践中的 OAuth
我们针对 50 种最受欢迎的 API 使用了OAuth,如 Google (Gmail、日历、表格等),HubSpot,Shopify,Salesforce,Stripe,Jira,Slack,Microsoft (Azure, Outlook, OneDrive),LinkedIn,Facebook 和其他使用OAuth 的 APIs。
私たちの結論: 現在の OAuth エクスペリエンスは、2008 年の JavaScript のブラウザ API とほぼ同じです。物事をどのように行うべきかについては一般的な合意がありますが、事実上すべての API には、標準に対する独自の解釈、実装の違いや特異性、標準以外の動作や拡張機能があります。その結果、あらゆる細部に問題やエラーが発生する可能性があります。
問題は正確にどこにあるのか、掘り下げてみましょう。
問題 1: OAuth 標準は大規模かつ複雑すぎる
「この API も OAuth 2.0 を使用しています。数週間前に実行しました。明日には実行できます。」 - インターンの最後の言葉
OAuth は巨大な標準です。公式Webサイト上の17のRFC(標準を定義する文書)で構成されています。OAuth フレームワークやベアラー トークンから脅威モデルや秘密キー JWT まで、あらゆるものをカバーしています。
「これらの RFC はすべて、単純なサードパーティのアクセス トークン承認 API に関するものですか?」と疑問に思うかもしれません。その通りです。典型的な API サードパーティ アクセスの使用例に関連する可能性のある事項に焦点を当ててみましょう。
OAuth 標準: OAuth 2.0 がデフォルトになりましたが、一部の API は依然として OAuth 1.0a を使用します (2.1 も予定されています)。API がどちらを使用しているかがわかったら、次のステップに進みます。
認証タイプ: authorization_code、client_credentials、または device_code が必要ですか? これらは何をするものですか?いつ使用する必要がありますか? 疑問がある場合は、authorization_code を試してください。
ちなみに、リフレッシュ トークンも付与の一種ですが、アクセス トークンを取得する代わりに、アクセス トークンの有効性を延長するために使用されます。それらがどのように機能するかは標準化されていますが、そもそもどのようにそれらをリクエストするかは標準化されていません。後で話す。
リクエストの準備ができたので、公式の OAuth パラメータを見てみましょう。パラメータは 72 個あり、それぞれに明確な意味と動作があります。ここで確認できます。一般的な例としては、プロンプト、スコープ、対象ユーザー、リソース、アサーション、login_hint などがあります。ただし、私たちの経験では、ほとんどの API プロバイダーは、現在あなたと同じようにこのリストについては無知であるようですので、あまり心配する必要はありません。
これはまだ複雑すぎて、学ぶべきことがたくさんあると思われる場合は、私たちもあなたの意見に同意する傾向があります。パブリック API を構築しているほとんどのチームがこれに同意しているようです。これらは完全な OAuth 2.0 標準に準拠しているわけではなく、API の使用例に基づいて一部の OAuth 機能を選択的に実装するだけです。これにより、この特定の API で OAuth がどのように機能するかを概説するドキュメントの長いページが作成されます。しかし、彼らを責めるのは難しく、彼らは複雑な標準に従うのではなく、優れた開発者エクスペリエンス (開発者エクスペリエンス、DX) を提供し、API を使いやすく理解しやすいものにしたいだけなのです。おそらく、OAuth 2.0 標準は複雑すぎるか、自分たちのシナリオには適していないと考えたため、便利だと思われる機能をいくつか選んだだけでしょう。これは善意で行われたものかもしれませんが、混乱や不一致を引き起こす可能性もあります。
authorization_code Salesforce の OAuth フロー。このシンプルな 10 ステップのプロセスを明確に把握できる点が気に入らない点はありますか?
問題は、OAuth とは何なのかについて人それぞれ異なる考えを持っているため、最終的にはさまざまな (サブ) 実装が多数存在することです。
問題 2: OAuth は人によって若干異なります
各 API は OAuth の異なるサブセットを実装しているため、その長い OAuth ドキュメントを熟読する必要があります。
1. 認可呼び出しではどのようなパラメータが期待されますか?
Jira の場合、audience パラメーターを設定して、アクセスする Jira インスタンスの URL を指定する必要があります。Google はこれを別のスコープで処理する傾向がありますが、プロンプト パラメータを非常に重視しています。一方、Microsoft の誰かが response_mode パラメータを発見し、常にクエリに設定するように依頼しました。
Notion API は、ユビキタスなスコープ パラメーターを廃止するという根本的なアプローチを採用しています。実際、API ドキュメントには「スコープ」という言葉さえ見つかりません。Notion ではこれらを機能と呼び、アプリケーションを登録するときに設定します。私たちは何が起こっているのかを理解するまで混乱して 30 分かかりました。なぜ彼らは車輪の再発明をするのでしょうか?
offline_access では状況はさらに悪くなります。最近のほとんどの API では、アクセス トークンが一定期間後に期限切れになります。リフレッシュ トークンを取得するには、「offline_access」をリクエストする必要があります。これは、パラメータ、スコープ、または OAuth アプリケーションの登録時に設定したものを通じて行う必要があります。詳細については、API または OAuth の医師に問い合わせてください。
2. トークン要求呼び出しでは何を期待していますか?
Fitbit などの一部の API は、リクエスト ヘッダーでデータを取得することを要求します。Notion のように、JSON としてフェッチすることを好む少数の人を除いて、ほとんどの人は、x-www-url-form-encoded としてエンコードされた本文内にそれを含めることを実際に望んでいます。
このリクエストの認証には基本認証を使用することを期待する人もいます。多くの人はこれを気にしません。ただし、明日には考えが変わるかもしれないので注意してください。
3. ユーザーをどこにリダイレクトして認証すればよいですか?
Shopify と Zendesk には、各ユーザーがサブドメイン (たとえば、{サブドメイン}.myshopify.com) を持つモデルがあります。はい、これには OAuth 認証ページも含まれるため、モデルとフロントエンド コードで動的 URL を構築することをお勧めします。
Zoho Books は、さまざまな地域の顧客にさまざまなデータセンターを提供しています。彼らが自分のデータがどこにあるか覚えていてほしい: アプリを認証するには、米国の顧客は https://accounts.zoho.com にアクセスし、ヨーロッパの顧客は https://accounts.zoho.eu にアクセスし、インドの顧客は https://accounts.zoho.eu にアクセスしてください。 //accounts.zoho.in. リストは続きます。
4. しかし、少なくともコールバック URL を選択することはできますよね?
Slack API コールバックとして http://localhost:3003/callback と入力すると、「セキュリティ上の理由から https を使用する」ように注意してくれるでしょう。はい、ローカルホストでも機能します。幸いなことに、ローカルホストで OAuth リダイレクトを実行するソリューションがあります。
長く続けることもできますが、もう要点は理解していただけたと思います。
OAuth は複雑すぎるため、必要なものがすべて揃った、よりシンプルなバージョンの OAuth を作成しましょう。© XKCD
問題 3: 多くの API が OAuth に非標準の拡張機能を追加している
OAuth 標準は包括的ですが、多くの API にはまだいくつかの機能が欠けていることがわかります。私たちが遭遇する一般的な問題は、API と対話するために access_token に加えていくつかのデータが必要であるということです。この追加データが OAuth フロー中に access_token とともに返されれば、さらに便利になります。
ただし、これは、API ごとに特別に実装する必要がある非標準的な動作を意味します。
以下は、私たちが確認した非標準拡張機能の一部のリストです。
Quickbooks は、すべての API リクエストで渡す必要があるレルム ID を使用します。realmID が通知されるのは、OAuth コールバックの追加パラメータとしてのみです。安全な場所に保管したほうがいいですよ!
Braintree も companyID を使用して同じことを行います
Salesforce は顧客ごとに異なる API ベース URL を使用し、これを「instance_url」と呼びます。ありがたいことに、トークン応答でアクセストークンとともにユーザーのinstance_urlが返されますが、実際にはそこからそれを解析して保存する必要があります。
残念ながら、Salesforce はさらに厄介なことも行いました。アクセス トークンは、ユーザーがカスタマイズできる事前設定された期間が経過すると期限切れになります。ここまでは問題ありませんが、何らかの理由で、受け取ったばかりのアクセス トークンの有効期限がいつ切れるかがトークン応答で通知されません (他の人はすべて通知します)。代わりに、追加のトークン詳細エンドポイントをクエリして、トークンの (現在の) 有効期限を取得する必要があります。Salesforce、なぜですか?
Slack には 2 つの異なるタイプのスコープがあります。Slack ボットとして保持されるスコープと、アプリを承認するユーザーの代わりに動作できるスコープです。賢いのですが、スコープごとに異なるスコープを追加するのではなく、認可呼び出しで渡す必要がある個別の user_scopes パラメーターを実装しました。このことを認識し、これをサポートする OAuth ライブラリを見つけてください。
簡潔さと単純さのために、これまでに遭遇した標準的ではない OAuth フローの多くを省略しました。
問題 4: 「invalid_request」 - OAuth のデバッグが難しい
分散システムのデバッグは十分に困難ですが、サービスが広範な一般的なエラー メッセージを返す場合はさらに困難になります。
OAuth2 には標準化されたエラー メッセージがありますが、タイトルの例と同様に、何が起こっているかを伝えるのに役立ちます (ちなみに、これは OAuth 標準で推奨されているエラー メッセージの 1 つです)。
OAuth は標準であり、すべての API が文書化されているため、デバッグの必要がないと思われるかもしれません。たくさんの。ドキュメントが何回間違っているかわかりません。または詳細が不足しています。または、最新の変更が反映されていません。あるいは、初めて見たときに見逃していたもの。私たちが実装する OAuth フローの約 80% には、初めて実装するときにいくつかの問題があり、デバッグが必要です。
Randall は私の気分を読んで OAuth フローをデバッグできるようですか? © XKCD
一部のフローは、一見ランダムな理由で中断します。たとえば、PKCE (Proof Key for Code Exchange) パラメーターを渡すと、LinkedIn OAuth が中断します。どのようなエラーが発生しますか? 「クライアント エラー - 無効な OAuth リクエスト。」これは...説得力がありますか? 受信した (オプションで通常は無視される) PKCE パラメーターがフローの中断の原因となっているものを特定するのに 1 時間かかりました。もう 1 つのよくある間違いは、事前に登録したアプリケーションと一致しないスコープを送信することです。(スコープを事前登録しますか? はい、現在、多くの API でこれが必要です。) これにより、通常、スコープの問題に関する一般的なエラー メッセージが表示されます。イライラします。
問題 5: API 上にアプリを構築するには面倒な承認が必要です
実のところ、サードパーティ API を利用して他のプラットフォームやサービス用のアプリケーションを構築している場合、おそらく弱い立場にあるでしょう。顧客はすでに他のシステムを使用しているため、統合を求めています。今、あなたは彼らを幸せに保つ必要があります。
客観的に言えば、多くの API は柔軟性があり、開発者がアプリケーションを登録して OAuth の使用を開始できる便利な自己登録フローを提供します。ただし、最も人気のある API の中には、アプリが公開されてユーザーが利用できるようになる前にレビューが必要なものもあります。もう一度公平を期すために、ほとんどのレビュープロセスは合理的であり、数日以内に完了できます。エンドユーザーにとって、安全性と品質が純的に向上する可能性があります。
ただし、悪名高い例の中には完了までに数か月かかるものや、収益分配契約の締結が必要なものもあります。
電子メールの内容など、より機密性の高いユーザー データを含むスコープにアクセスする場合、Google は「セキュリティ監査」を要求します。これらのレビューが完了するまでに数日から数週間かかる場合があり、かなりの量の作業が必要になると聞いています。
リップリングと統合したいですか? 30 以上の質問に答え、制作前の安全性スクリーニングに備える準備をしてください。(承認された場合) アクセスできるようになるまでに数か月かかると聞いています。
HubSpot、Notion、Atlassian、Shopify など、統合マーケットプレイスやアプリ ストアを利用しているほぼすべての人が、そこに掲載するにはレビューが必要です。穏やかなレビューもあれば、デモ ログイン、ビデオ デモ、ブログ投稿 (はい!) などの提供を要求するレビューもあります。ただし、市場や店舗への出品は通常はオプションです。
Ramp、Brex、Twitter、その他多くのサービスでは、開発者に自己登録プロセスが提供されておらず、手動でアクセスするにはフォームに記入する必要があります。多くはすぐにリクエストを処理する予定ですが、一部のリクエストは数週間後に返答を待っています。
特に極端な例は、有料 API である Xero です。接続アカウント数の制限 25 を超えたい場合は、Xero パートナーになり、Xero パートナーのアプリ ストアにアプリを掲載する必要があります。(この記事の執筆時点で) 彼らは、そのストアから生成されたすべての見込み客の 15% の収益分配を受け取ります。
問題 6: OAuth にはセキュリティの問題がある
OAuth セキュリティの脆弱性の発見とネットワーク技術の進歩により、OAuth 標準は常に更新され、改善されています。現在のセキュリティのベスト プラクティスを実装したい場合は、OAuth ワーキング グループが参照できる詳細なガイドを提供しています。まだ OAuth 1.0a を使用している API を使用している場合は、下位互換性が継続的な課題であることに気づくでしょう。
幸いなことに、セキュリティは反復を繰り返すごとに改善されていますが、通常は開発者の作業量が増加します。次期 OAuth 2.1 標準では、現在のベスト プラクティスの一部が必須となり、必須の PKCE (現在これを必要とする API は少数のみ) とリフレッシュ トークンに対する追加の制限が含まれます。
少なくとも OAuth は 2 要素認証モデルを実装しています。© XKCD
おそらく最大の変化は、期限切れのアクセス トークンとリフレッシュ トークンの導入によって引き起こされたものです。理論的には、このプロセスは単純に見えます。アクセス トークンの有効期限が切れるたびに、リフレッシュ トークンでリフレッシュし、新しいアクセス トークンとリフレッシュ トークンを保存します。実際、この関数を実装するときは、次のことを考慮する必要があります。
競合状態: 現在のアクセス トークンを更新している間、他のリクエストが実行されていないことを確認するにはどうすればよいですか?
一部の API では、一定の日数使用しない (またはユーザーがアクセスを取り消した) 場合に、リフレッシュ トークンが期限切れになります。一部の更新は失敗することが予想されます。
一部の API では、更新リクエストごとに新しい更新トークンが提供されます。
...しかし、古いリフレッシュ トークンを保持して使い続けることを暗黙のうちに想定している人もいます。
一部の API は、アクセス トークンの有効期限が絶対的に切れる時期を通知します。他の人はそれを相対的な「今から数秒後」で表現するだけです。さらに、Salesforce などの企業は、この種の情報を軽々しく開示しません。
最後に: まだ話していないこと
残念ながら、ここでは OAuth 実装の表面をなぞっただけです。OAuth フローが機能し、アクセス トークンを取得したので、次のことについて考えてみましょう。
これらのアクセス トークンとリフレッシュ トークンを安全に保存する方法。これらはユーザー アカウントのパスワードのようなものです。ただし、一方向の暗号化はオプションではなく、安全で元に戻せる暗号化が必要です。
付与されたスコープが要求されたスコープと一致することを確認します (一部の API では、ユーザーが認可フロー中に付与されたスコープを変更できます)。
トークンが更新されるときに、複数のリクエストが同じトークンを同時に変更する状況 (競合状態とも呼ばれます) を回避します。
プロバイダ側のユーザーが取り消したアクセストークンを検出します。
アクセス トークンの有効期限が切れたことをユーザーに通知し、アプリを再認証するように指示します。
不要になった (または GDPR に基づいてユーザーから削除を求められた) アクセス トークンを取り消す方法。
また、利用可能な OAuth スコープの変更、プロバイダーのバグ、ドキュメントの不足などにも対処する必要があります。
もっと良い方法はありますか?
これを読んでいるあなたは、おそらく「もっと良い方法があるに違いない!」と考えているでしょう。
私たちはそれがあると考えており、それが Nango を構築している理由です。これは、事前に構築された OAuth フロー、安全なトークン ストレージ、90 以上の OAuth API の自動トークン更新を提供するオープンソースの自己完結型サービスです。
ぜひ試してみてください。フィードバックをお聞かせください。最悪の OAuth ホラーストーリーを私たちと共有したい場合は、Slack コミュニティでもぜひ聞いてください。
OAuth の実践において、この記事で挙げた問題以外にどのような問題があるでしょうか?
推奨読書:
▶オラクル、Javaライセンスを再度厳しくチェック中 ネチズン:同社はJavaをアンインストールし、新システム開発のためプログラマーを再募集した!
▶資金不足のため、フルタイムの開発者は次のように述べました: このオープンソース ソフトウェアには未来がないかもしれません。