パブリッククライアントと機密クライアントの違いは何ですか?
この記事は、OAuth におけるパブリッククライアントと機密クライアントの違いを、Logto アプリケーションを例にして説明します。
Logto を使用してアプリケーションを作成する際に、Single Page Application (SPA)、ネイティブアプリ、従来の Web アプリケーションなど、いくつかの異なるアプリケーションタイプから選択できることに気づくでしょう。直感的に、ネイティブアプリはスマートフォンのようなデバイスで一般的に使用されるオペレーティングシステム上で実行されることが明らかです。しかし、SPA と従来の Web アプリケーションとは一体何でしょうか?なぜこれらの異なるアプリタイプを区別する必要があるのでしょうか?この記事では、これらの質問の答えを明らかにします。
始める前に、いくつかの概念について簡単に紹介する必要があります。
OAuth とは何ですか?
OAuth はアクセス委任のためのオープンスタンダードであり、インターネットユーザーが他のウェブサイトの情報にパスワードを提供せずにウェブサイトやアプリケーションにアクセスを許可する方法として一般的に使用されます。
ここ数十年で、OAuth は標準的な認可プロセスとなり、Google、Meta、Microsoft など、ほとんどの企業によって広く受け入れられています。現在使用されているバージョンは OAuth 2.0 です。
OAuth の文脈では、先ほど例に挙げたアプリケーションはクライアントと呼ばれます。これらは、リソース所有者(通常はエンドユーザー)の認可を得た場合に、保護されたリソースを要求するこ とができます。
パブリッククライアントと機密クライアント
OAuth は、クライアント資格情報の機密性を維持する能力に基づいて、2つのクライアントタイプを定義しています。
機密クライアント
クライアント資格情報の機密性を維持する能力を持つクライアント(たとえば、クライアント資格情報へのアクセスが制限されたセキュアなサーバーで実装されたクライアント)または他の手段でセキュアなクライアント認証が可能なクライアント。
パブリッククライアント
クライアント資格情報の機密性を維持する能力がないクライアント(たとえば、リソース所有者のデバイス上で実行されるクライアント、ネイティブアプリまたは Web ベースのアプリなど)であり、他の手段でもクライアントとしてセキュアに認証することができません。
SPA、ネイティブアプリケーション、従来の Web アプリケーション
前述の背景知識を踏まえて、Logto の文脈で SPA、ネイティブアプリ、従来の Web アプリが何を意味するか、またそれらがパブリッククライアントまたは機密クライアント と考えられるかどうかを見てみましょう。
SPA
SPA のクライアントサイドコードは、Web サーバーからダウンロードされ、リソース所有者のデバイスのユーザーエージェント(たとえば Web ブラウザ)で実行されます。プロトコルデータと資格情報はリソース所有者にとって容易にアクセス可能(かつしばしば閲覧可能)です。
ネイティブアプリ
ネイティブアプリはリソース所有者のデバイスにインストールされ、実行されます。プロトコルデータと資格情報はリソース所有者にアクセス可能です。一般的に、アプリケーションに含まれるクライアント認証資格情報は抽出可能と仮定されます。
従来の Web アプリ
従来の Web アプリは Web サーバー上で実行されるクライアントです。リソース所有者はデバイスのユーザーエージェントに表示される HTML ユーザーインターフェースを通じてクライアントにアクセスします。クライアント資格情報およびクライアントに発行されたアクセストークンは Web サーバー上に保存され、リソース所有者には公開されておらず、アクセス可能ではありません。
したがって、SPA とネイティブアプリはパブリッククライアントであり、一方、従来の Web アプリは機密クライアントであることが明確にわかります。
Logto で SPA またはネイティブアプリを作成する際には、アプリシークレットがないことに気づくかもしれ ませんが、従来の Web アプリにはアプリ ID とアプリシークレットの両方があります。これは、パブリッククライアントのシークレットはセキュリティが保証できないためです。
クライアントは OAuth 認可フローでどのように機能しますか?
OAuth アプリケーションを開発する際の最初のステップは、OAuth サービスプロバイダーにクライアントを登録することです。クライアント登録には、アプリケーションの名前やリダイレクト URI などの詳細情報を提供します。その後、OAuth サービスプロバイダーはクライアント ID とクライアントシークレットを生成します。これらはアプリケーションの資格情報と見なされます。
クライアント ID は公開情報と見なされ、OAuth プロセス中にユーザーと共有されます。通常、認可 URL に含まれ、エンドユーザーに見える形になります。
一方、クライアントシークレットはアプリケーションのパスワードとして機能し、秘密にしておく必要があります。これは OAuth プロセスで認可コード(これが認可コードフローであると仮定します)を交換し、アクセストークンを取得するために使用されます。クライアントシークレットの存在により、登録されたアプリケーションのみがアクセストークンの交換を完了できるようになります。
PKCE(Proof Key for Code Exchange)の導入
前述のように、パブリッククライアントのクライアントシークレットのセキュリティは保証できず、攻撃者はクライアント資格情報を取得し、クライアントを偽装して保護されたリソースにアクセスすることができます。これはいかなる状況でも許容できません。
PKCE(Proof Key for Code Exchange)は、この問題を解決するために、各認可フローの開始時にコードベリファイアを一時的に生成し、それをローカルに保存して、ハッシュしてコードチャレンジを生成し、認可サーバーに送信します。アクセストークンを交換する際にコードベリファイアを再度認可サーバーに送信します。認可サーバーはコードベリファイアとコードチャレンジが一致することを確認し、パブリッククライアントが偽装されていないことを保証します。
PKCE におけるコードベリファイアは、実際には動的なクライアントシークレットとして機能します。そのセキュリティはハッシュアルゴリズムの不可逆性によって確保されます。
まとめ
本記事では、OAuth における機密クライアントとパブリッククライアントの概念について説明しました。機密クライアントは秘密を保持し、機密情報を安全に保管する能力がある一方で、パブリッククライアントはこの能力がないことを学びました。Logto の製品実践の文脈で、従来の Web アプリ、SPA、ネイティブアプリの 2 種類のクライアントの例を検討しました。
また、OAuth におけるクライアント登録プロセスや、クライアント ID とクライアントシークレットの役割についても説明しました。
さらに、パブリッククライアントがクライアントシークレットを安全に保管できないという制限に直面することを発見しました。この制限を克服するために、OAuth 拡張機能である PKCE(Proof Key for Code Exchange)を紹介し、パブリッククライアントがクライアントシークレットを必要とせずに認可コードを安全に交換できるようにする方法を示しました。
私たちの製品、Logto は、OAuth と OIDC プロトコルのベストプラクティスに従い、PKCE の使用を含むパブリッククライアントのセキュリティを保護するための措置を採用して、すべての段階でセキュリティを確保する包括的な CIAM ソリューションです。