web-dev-qa-db-ja.com

シングルページアプリでPKCEが推奨されないのはなぜですか?

今日の多くのサービスは、シングルページアプリを開発するときに、OpenID Connect/Oauth2トークン交換の暗黙的なフローを推奨しています。 (見る オクタ -暗黙的なフォールバック付きのPKCEを推奨するようになりました GoogleAuth

いくつかの 新しいガイダンス トークン交換ステップでclient_secretなしで承認コードフローを使用することを指しますが、記事で引用されている理由(たとえば、トークンがブラウザー内に存在しない)に同意できることに同意できます歴史、 ウェブログなど)。この概念がPKCEでさらに一歩進んでいないのはなぜですか? client_secretを完全に省略する代わりに、ネイティブアプリケーションで推奨されている動的なものを利用してみませんか? SPAとネイティブアプリはどちらも「パブリッククライアント」と見なされ、秘密を安全に保持することはできませんが、SPAが過去に保持されているように見えるのは、ネイティブアプリだけがPKCEの推奨を取得します。

PKCEが解決しようとしているセキュリティの影響がブラウザのみのコンテキストに直接関係しないことを理解していますが、これを多層防御メカニズムと見なして利用することはできませんか?経験から、GoogleがWebアプリケーションの資格情報を生成して、SPAに対して暗黙的以外のものを使用することを許可しないことを知っています( この問題 を参照)、承認コードフローはclient_secretとPKCE交換を期待しますネイティブアプリの認証情報タイプを選択した場合にのみ機能しますが、アプリケーションにhttps redirect_uriを指定することはできません。

他のプロバイダーでは、Webコンテキストで承認コードフローを使用したPKCEを許可していますが、プロバイダーからは推奨されていません。これが必要でそれを利用するのは間違っていますか? Web Crypto APIs を使用してコードチャレンジを生成および渡すという追加の手順を追加するのはかなり簡単なようです( targeting 新しいブラウザーと必要に応じてシミング)。

33
someone1

@catanmanは、SPAのPKCEに関する技術的な考慮事項に関して優れた点を述べていますが、最近、IETF Oauthワーキンググループが ベストカレントプラクティスドキュメント を公開しました(2018年12月28日) )述べる:

注:これまでPKCEはネイティブアプリを保護するメカニズムとして推奨されていましたが、このアドバイスは、Webアプリケーションを含むすべての種類のOAuthクライアントに適用されます。

22
Brad J

他のすべての答えは正しいですが、最新の OAuth 2.0 for Browser-Based Apps Best Practices Doc (2019年1月29日)は次のように述べています(強調は私のものです):

  1. 概観

    ブラウザベースのアプリケーション内でユーザーを認証するために、最高の
    現在の慣行は

    o OAuth 2.0認証コードフローをPKCE拡張機能とともに使用します

...

と同様

7.1。ブラウザベースのアプリケーションからの承認リクエストの開始

公開ブラウザベースのアプリはコードの証明キーを実装する必要があります
Exchange(PKCE [RFC7636])
OAuthへの拡張と承認
サーバーは、そのようなクライアントのPKCEをサポートする必要があります。

PKCE拡張機能は、認証コードを交換する同じクライアントインスタンスがフローを開始したものと同じであることを認証サーバーに確認する方法を許可サーバーに提供することにより、認証コードが傍受されて悪意のあるクライアントによってアクセストークンと交換される攻撃を防ぎます。

ブラウザベースのアプリであっても、多層防御として実行する価値があるいくつかの小さな利点があると思います。

20
Eran Medan

SPAはPKCEの恩恵を受けません。 PKCEは、あなたが説明している問題とは異なる問題を解決します。

まず、SPAsの場合、現在のベストプラクティスは、承認コードフローではなく暗黙のフローを使用することです。 暗黙的なフローでは、アクセストークンは、クエリコンポーネント(?)ではなく、リダイレクトURIのハッシュフラグメント(#)に含まれます。ブラウザはリクエスト時にURIのハッシュフラグメント部分を含めないため、トークンしないは ブラウザの履歴、ウェブログ...

ネイティブアプリの場合、 rfc8252セクション6 は次のように述べています。

パブリックネイティブアプリクライアントは、コード交換用の証明キーを実装する必要があります(PKCE RFC7636])


余談ですが、PKCE要件はpublicネイティブクライアントに対するものであることに注意してください。ネイティブアプリがパブリックにできないのはなぜだろうと思うかもしれません。答えは セクション8.4 にあります:

動的クライアント登録[RFC7591]などのメカニズムを使用してインスタンスごとのシークレットをプロビジョニングする場合を除き、ネイティブアプリはパブリッククライアントとして分類されます

どこにも言及されている機密のネイティブクライアントを見たことがないので、これらのクライアントを参照する方法が正確にわかりません。多分非公開のネイティブクライアントは動作します:)


あなたの質問に答えるには、なぜPKCEの認証コードフローは、SPAではなくパブリックネイティブアプリに必要なのですか?

ロジックは次のとおりです。

  1. OAuth2の主な目的の1つは、ユーザーの資格情報がクライアントに公開されないようにすることです。
  2. ネイティブアプリがこの要件を満たすには、ユーザーは、ネイティブアプリがアクセスできる場所に資格情報を入力してはなりません。したがって、ネイティブのログイン画面とWebビューは避けなければなりません。
  3. この解決策は、ネイティブアプリが外部ユーザーエージェントを起動することです( rfc8252付録B を参照)。ここで、ユーザーは承認サーバーで認証し、アプリケーションを承認します。ネイティブアプリは外部ユーザーエージェントにアクセスできないため、ユーザーの認証情報は安全です。
  4. ただし、SPAには存在しなかった新しい複雑化が導入されました。外部ユーザーエージェントは、承認サーバーの応答をネイティブアプリに返す必要がありますか?答えはアプリ間通信です( セクション5 および セクション7 を参照)
  5. 残念ながら、いくつかの種類のアプリ間通信は、悪意のあるサードパーティアプリによって傍受される可能性があります。暗黙のフローでは、これは悪意のあるアプリによってアクセストークンが盗まれる可能性があることを意味します。これは非常に悪いことです。これが、ネイティブアプリで暗黙的フローが使用されない主な理由の1つです。
  6. ただし、代わりに認証コードフローを使用しても、悪意のあるサードパーティアプリは認証コードを傍受し、クライアントシークレットがないため、それを使用してアクセストークンを取得できます。したがって、パブリックネイティブアプリの暗黙的なフローの代わりに認証コードフローを使用することは役に立たないようです。
  7. これがPKCEの出番です。PKCEは、悪意のあるアプリが認証コードを傍受したとしても、それをアクセストークンと交換できないようにします。これは、アクセストークンを要求しているエンティティが、そもそも認証コードを要求したエンティティと同じであることを証明することを要求することによって実現されます。

うまくいけば、今あなたはその理由を理解しています:

  • SPAではすべてがブラウザ内で発生するため、SPAはPKCEのメリットをまったく受けません。 PKCEは、アプリ間通信がある場合にのみ役立ちます。
  • パブリックネイティブアプリは、アプリ間通信が安全でない場合があるため、暗黙的なフローを使用しないでください。
  • パブリックネイティブアプリは、認証コードフロー+ PKCEを使用する必要があります

詳細については、次のブログ投稿をご覧ください。 https://medium.com/@justinsecurity/mobile-apps-and-oauths-implicit-flow-68e72c6515a1

14
catanman