{"meta":{"title":"OAuth アプリを作成するためのベスト プラクティス","intro":"OAuth appのセキュリティとパフォーマンスを向上させるには、次のベスト プラクティスに従ってください。","product":"アプリ","breadcrumbs":[{"href":"/ja/apps","title":"アプリ"},{"href":"/ja/apps/oauth-apps","title":"OAuth アプリ"},{"href":"/ja/apps/oauth-apps/building-oauth-apps","title":"OOAuth アプリの構築"},{"href":"/ja/apps/oauth-apps/building-oauth-apps/best-practices-for-creating-an-oauth-app","title":"ベスト プラクティス"}],"documentType":"article"},"body":"# OAuth アプリを作成するためのベスト プラクティス\n\nOAuth appのセキュリティとパフォーマンスを向上させるには、次のベスト プラクティスに従ってください。\n\n## 代わりに GitHub App を使用する\n\n可能であれば、GitHub Appの代わりにOAuth appを使用することを検討してください。 一般に、 GitHub Apps は OAuth appsよりも好ましい。\nGitHub Apps は、きめ細かいアクセス許可を使用し、アプリがアクセスできるリポジトリをより細かく制御し、有効期間の短いトークンを使用できるようにします。 これらの特徴により、アプリの資格情報が漏洩した場合に発生するおそれがある損害を制限することで、アプリのセキュリティを強化できます。\n\nOAuth appsと同様に、GitHub Appsは引き続き OAuth 2.0 を使用し、OAuth トークンの種類 (アクセス トークンと呼ばれます) を生成し、ユーザーに代わってアクションを実行できます。 ただし、 GitHub Apps はユーザーとは独立して動作することもできます。\n\nGitHub Apps の詳細については、「[GitHub アプリの作成について](/ja/apps/creating-github-apps/about-creating-github-apps/about-creating-github-apps)」を参照してください。\n\n既存の OAuth app を GitHub Appに移行する方法の詳細については、「 [OAuth アプリを GitHub Apps に移行する](/ja/apps/creating-github-apps/about-creating-github-apps/migrating-oauth-apps-to-github-apps)」を参照してください。\n\n## 最小限のスコープを使用する\n\nOAuth appは、アプリが目的の機能を実行するために必要なスコープのみを要求する必要があります。 アプリのトークンが侵害された場合、これにより発生するおそれのある損害の量を制限できます。 詳しくは、「[OAuth アプリの承認](/ja/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps)」をご覧ください。\n\n## 徹底的かつ持続的に承認する\n\nユーザーにサインインした後、アプリ開発者は追加の手順を実行して、ユーザーがシステム内のデータにアクセスできるようにする必要があります。 各サインインには、メンバーシップ、アクセス、現在の SSO 状態に関する新しいチェックが必要です。\n\n### 永続的で一意の `id` を使用してユーザーを格納する\n\nユーザーがサインインしてアプリケーションでアクションを実行するときは、次回サインインしたときに同じリソースへのアクセス権を付与するために、どのユーザーがそのアクションを実行したかを覚えておく必要があります。\n\nユーザーをデータベースに正しく格納するには、常にユーザーの `id` を使用します。 この値は、ユーザーに対して変更されることも、別のユーザーを指し示すために使用されることもないため、意図したユーザーへのアクセスを確実に提供できます。 ユーザーの `id` を `GET /user` REST API エンドポイントで確認できます。 「[ユーザーの REST API エンドポイント](/ja/rest/users/users#get-a-user)」を参照してください。\n\nリポジトリ、組織、および企業へのリファレンスを格納する場合は、それらの `id` を使用して、リンクが正確であることを確認します。\n\nユーザー ハンドル、組織の置換フィールド、メール アドレスなど、時間の経過に伴い変化する可能性のある識別子を *絶対に* 使用しないでください。\n\n### 新しい認証ごとに組織へのアクセスを検証する\n\nユーザーをサインインさせるときは、ユーザーのトークンがどの organization に対して認可されているかを追跡する必要があります。 これは、サインイン後の時間が経過してユーザーが organization から削除されたときに変化する可能性があります。 組織が SAML SSO を使用していて、ユーザーが SAML SSO を実行していない場合、ユーザー アクセス トークンはその組織にアクセスできません。 `GET /user/installations` REST API エンドポイントを定期的に使って、ユーザー アクセス トークンがアクセスできる organization を確認することをお勧めします。 ユーザーが organization へのアクセスを許可されていない場合は、そのユーザーが SAML SSO を実行するか、organization に再参加するまで、自身のアプリケーション内で organization が所有するデータへのアクセスを禁止する必要があります。 詳しくは、「[GitHub App インストール用の REST API エンドポイント](/ja/rest/apps/installations#list-app-installations-accessible-to-the-user-access-token)」をご覧ください。\n\n### 組織および企業のコンテキストでユーザーデータを格納する\n\n`id` フィールドを使用してユーザー ID を追跡するだけでなく、各ユーザーが操作している組織または企業のデータを保持する必要があります。 これにより、ユーザーがロールを切り替えた場合に、機密情報が漏えいしないようにすることができます。\n\n次に例を示します。\n\n1. ユーザーは、SAML SSO を必要とする `Mona` 組織にいて、SSO の実行後にアプリにサインインします。 これで、アプリはユーザーが `Mona` 内で行うあらゆるものにアクセスできるようになりました。\n2. ユーザーは、`Mona` 内のリポジトリから多数のコードを抜き取り、分析するためにアプリに保存します。\n3. その後、ユーザーはジョブを切り替え、`Mona` 組織から削除されます。\n\nユーザーがアプリにアクセスしても、ユーザー アカウントに `Mona` 組織のコードと分析をまだ表示できますか?\n\nこのため、アプリが保存しているデータのソースを追跡することが重要です。 それ以外の場合、アプリは組織のデータ保護にとって脅威であり、アプリがデータを正しく保護しているか信頼できない場合は、そのアプリを禁止する可能性があります。\n\n### アプリへのユーザー アクセスを検証する\n\nOAuth アプリに組織外または企業外のユーザーがアクセスできます。 組織または企業のメンバーのみがアプリを使用できるようにする場合は、ユーザーがアプリにサインインするときにユーザーのメンバーシップの状態をチェックする必要があります。\n\nユーザーがメンバーになっている組織の一覧を見つけるには、「認証済みユーザーの組織を一覧表示する」エンドポイントを使用できます。 その後、アプリに対して承認された組織の一覧に対してこの一覧を検証できます。 詳しくは、「[組織のREST APIエンドポイント](/ja/rest/orgs/orgs#list-organizations-for-the-authenticated-user)」をご覧ください。\n\n## アプリの資格情報をセキュリティで保護する\n\nクライアント シークレットとユーザーの承認コードを使用すると、アプリはユーザーをサインインさせ、アクセス トークンを生成できます。 これらのトークンを使用すると、ユーザーに代わって API 要求を行うことができます。\n\n可能であれば、アプリのクライアント シークレットと生成されたトークンを安全に格納する必要があります。 ストレージ メカニズムとその相対的なセキュリティは、統合アーキテクチャと稼働するプラットフォームによって異なります。 一般に、使用中のプラットフォームに機密データを保存することを目的とした保存方法を使用する必要があります。\n\n### クライアント シークレット\n\nクライアント シークレットは、アプリがデバイス フローを使用しない限り、アプリのアクセス トークンを生成するために必要です。 詳しくは、「[OAuth アプリの承認](/ja/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps#device-flow)」をご覧ください。\n\nアプリが機密クライアントである場合(つまり、クライアント シークレットを安全に保つことができます)、クライアント シークレットをキー コンテナー (\\<c0、>Azure Key Vault</c0> など)、または暗号化された環境変数またはシークレットとしてサーバーに格納することを検討してください。\n\nアプリがパブリック クライアント (ユーザーのデバイスで実行されるネイティブ アプリ、CLI ユーティリティ、または単一ページ Web アプリケーション) である場合、クライアント シークレットをセキュリティで保護することはできません。 アプリケーションのコードにクライアント シークレットを組み込む必要があり、認証フローをより安全にするために PKCE を使う必要があります。 パブリック クライアントは簡単になりすましができる、つまり、誰でもアプリのクライアント ID を再利用してサインインできるため、アプリで生成されたトークンに基づいて独自のサービスへのアクセスをゲートする予定の場合は注意が必要です。\n\n#### 理由なしにデバイス フローを有効にしない\n\nパブリック クライアントでのクライアント シークレットの使用が懸念される場合は、デバイス フローよりも PKCE を使った認証コードを使うことをお勧めします。 デバイス フローではリダイレクト URI はまったく必要ありません。つまり、攻撃者はデバイス フローを使って、フィッシング攻撃の一環としてリモートからアプリを偽装することができます。 このため、制約のある環境 (CLI、IoT デバイス、ヘッドレス システム) でアプリを使っている場合を除き、アプリケーションでデバイス フローを有効にしないでください。\n\n### アクセス トークン\n\nアプリが Web サイトや Web アプリの場合は、バックエンドでトークンを暗号化し、トークンにアクセスできるシステムのセキュリティを確保する必要があります。 アクティブなアクセス トークンとは別の場所に更新トークンを保存することを検討してください。\n\nアプリがネイティブ クライアントやクライアント側アプリの場合、またはユーザー デバイスで稼働している (サーバー上で稼働しているのではなく) 場合は、トークンとサーバー上で稼働するアプリをセキュリティ保護できないことがあります。 アプリのプラットフォームに推奨される方法を使用してトークンを保存する必要があり、保存方法が完全に安全ではないことがあることに注意してください。\n\n## 適切なトークンの種類を使用する\n\nOAuth apps では、認証された API 要求を行うためにアクセス トークンを生成できます。 アプリで認証に personal access token または GitHub パスワードを使用しないでください。\n\n## 期限切れのアクセス トークンを使用する\n\n定期的なトークン ローテーションを適用し、侵害されたトークンの影響を軽減するには、有効期限が切れたアクセス トークンを使用するように OAuth app を構成する必要があります。 有効期限が切れたアクセス トークンをアプリで使用すると、アクセス トークンを生成するときに更新トークンを受け取ります。 アクセス トークンは 8 時間後に期限切れになり、更新トークンは 6 か月後に期限切れになります。 更新トークンを使用して、新しいアクセス トークンと新しい更新トークンを生成できます。 詳しくは、「[OAuth アプリの承認](/ja/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps#expiring-access-tokens)」をご覧ください。\n\nトークンの期限切れのサポートをテストして段階的にロールアウトするには、他のスコープに加えて `offline_access` スコープを要求することで、サインインの期限切れトークンを受け取ることを選択できます。 アプリがGitHub Enterprise ServerとGitHub.comの両方をサポートしている場合は、GitHub Enterprise Server インスタンスがまだ期限切れのトークンをサポートしていない可能性があるため、`offline_access` スコープが無効になる準備をしてください。 トークン応答に `expires_in` フィールドが存在するかどうかを確認して、アプリが期限切れのトークンを受け取ったかどうかを確認します。\n\n## 必要な場合にのみ、コールバック URL のワイルドカード 一致を有効にする\n\n> \\[!WARNING]\n> ワイルドカード 照合を有効にすると、攻撃者がコールバック URL のサブドメインまたはサブディレクトリに承認コードを送信できるため、アプリがセキュリティ リスクにさらされる可能性があります。 ワイルドカード マッチングは、絶対に必要であり、コールバック URL のすべての可能なサブドメインとパスを完全に制御することが確実な場合にのみ有効にします。 詳細については、 [OAuth 2.0 のセキュリティのベスト カレント プラクティス](https://www.rfc-editor.org/info/rfc9700/#section-4.1.1-11)を参照してください。\n\n## セキュリティ侵害を処理するための計画を立てる\n\nセキュリティ侵害をタイムリーに処理できるように、計画を立てる必要があります。\n\nアプリのクライアント シークレットが侵害された場合は、新しいシークレットを生成し、新しいシークレットを使用するようにアプリを更新し、古いシークレットを削除する必要があります。\n\nアクセス トークンが侵害された場合は、すぐにこれらのトークンを取り消す必要があります。 詳しくは、「[OAuth 承認用 REST API エンドポイント](/ja/rest/apps/oauth-applications#delete-an-app-token)」をご覧ください。\n\n## 定期的な脆弱性スキャンを実施する\n\nアプリで定期的な脆弱性スキャンを実行する必要があります。 たとえば、アプリのコードをホストするリポジトリに対して、コード スキャンとシークレット スキャンを設定できます。 詳細については、「[コード スキャン](/ja/code-security/concepts/code-scanning/code-scanning)」および「[シークレット スキャン](/ja/code-security/concepts/secret-security/secret-scanning)」を参照してください。\n\n## 適切な環境を選択する\n\nアプリがサーバー上で稼働している場合は、サーバー環境がセキュリティ保護され、アプリで予想される量のトラフィックを処理できることを確認します。\n\n## 安全な方法でサービスを使用する\n\nアプリでサードパーティのサービスを利用する場合は、セキュリティで保護された方法で利用する必要があります。\n\n* アプリで利用するすべてのサービスでは、固有のログイン情報とパスワードを指定する必要があります。\n* アプリケーションは、SaaSサービスを管理するためのメールやデータベースサービスのようなサービスアカウントを共有するべきではありません。\n* 管理業務を行う従業員のみが、アプリをホストするインフラストラクチャへの管理者アクセス権を持つ必要があります。\n\n## ログと監視を追加する\n\nアプリにログ記録と監視機能を追加することを検討してください。 セキュリティ ログには、以下が含まれている場合があります。\n\n* 認証及び認可イベント\n* サービス設定の変更\n* オブジェクトの読み書き\n* ユーザーとグループのアクセス許可の変更\n* ロールの管理者への昇格\n\nログでは、各イベントで一貫したタイムスタンプを使う必要があります。また、ログに記録されたすべてのイベントのユーザー、IP アドレス、ホスト名を記録する必要があります。\n\n## データの削除を有効にする\n\n他のユーザーがアプリを利用できる場合は、ユーザーにデータを削除する方法を提供する必要があります。 ユーザーは、自分のデータを削除するために、サポート担当者にメールを送信したり、電話したりする必要はないはずです。\n\n## 参考資料\n\n* [GitHub Marketplace 上のアプリのセキュリティのベスト プラクティス](/ja/apps/github-marketplace/creating-apps-for-github-marketplace/security-best-practices-for-apps-on-github-marketplace)\n* [アプリケーションの顧客体験のベストプラクティス](/ja/apps/github-marketplace/creating-apps-for-github-marketplace/customer-experience-best-practices-for-apps)"}