静的APIトークンは、外部APIを呼び出し、ソフトウェアベンダーなどのサードパーティのリソースにアクセスするために長年使用されてきました。API規格の進化に伴い、より堅牢なセキュリティ、優れた柔軟性、より良い開発者エクスペリエンスを提供する選択肢としてOAuth 2.0が登場しました。静的トークンからOAuth 2.0に移行するメリットについて見ていきましょう。
静的APIトークンのランドスケープ
セキュアなソフトウェアシステムでは、リソースへの読み取りまたは変更アクセスを許可するすべての呼び出しを認可する必要があります。保護されたAPIを呼び出す場合、そのAPIは何らかの方法で認可を検証する必要があります。静的APIトークンは、ユーザーコンテキストなしで、記憶された値を使用してAPIに認可情報を付与する方法です。その結果、開発者が別のアプリにAPIアクセスを許可するための、シンプル(ながらも限定的)なアプローチが提供されました。つまり、トークンを生成して一度保存すれば、タスクを続行できるというものです。
OktaへのHTTP呼び出しの例を見ると、静的なAPIトークンを使用したリクエストは次のようになります。

APIの呼び出し元(クライアント)が、API呼び出しにトークンの値を追加します。呼び出されるベンダーシステムに応じて、APIは静的なトークン値をHTTPヘッダー(標準の認可スキームやOktaのSSWSスキームなどの独自スキームを使用したAuthorizationなど)またはクエリパラメーターに追加する場合があります。
セキュリティを強化するため、静的なAPIトークンからOAuth 2.0に移行する
多くのテクノロジーと同様に、このような使いやすさには、リスクにさらされる機会の増大が伴います。有効期間の短いOAuth 2.0トークンとは異なり、静的トークンは通常、有効期間が長くなっています。クエリパラメーターで設定されたAPIトークンは特に危険です。ブラウザはURLを履歴に保存し、ログシステムはURL全体を記録する可能性があるため、HTTPヘッダーを使用する場合よりもトークンが漏洩しやすくなります。
静的APIトークンに関連するセキュリティ上の懸念をより深く理解するために、その特性を詳しく掘り下げ、代替手段であるOAuth 2.0と比較対照してみましょう。
静的APIトークンを使用する際のアクセスリスク
静的なトークンが不正な人物の手に渡ると、不正アクセスにつながる可能性があります。例えば、静的なトークンが誤ってソース管理システムにチェックインされ、リポジトリの閲覧者やソース管理履歴に意図せず公開されてしまう可能性があります。静的トークンは有効期間が長いため、トークン漏洩のリスクは特に懸念されます。盗まれた静的トークンは、手動で無効化されるか、最終的に有効期限が切れるまでアクティブな状態が続き、不正アクセスを許してしまうため、その影響は甚大です。
トークンローテーションのトラブル
静的トークンをローテーションさせることは、困難なタスクになる場合があります。トークンの値は呼び出し元の環境やソフトウェアシステム内に永続的に存在するため、本番環境を稼働させ続けながら、トークンを迅速に解放し、新しいトークンを生成して保存するというローテーションのタイミングを計ることは、課題となる可能性があります。
スコープを限定することは困難です
静的トークンに限定的なスコープを割り当てるのは、容易ではありません。静的トークンは通常、呼び出されたAPI全体へのアクセス、つまり「オールオアナッシング」のアクセスレベルを付与します。読み取り専用アクセスと書き込みアクセスの比較など、限定されたスコープのアクセスを定義することや、その他のきめ細かなアクセス制御手段は、静的なAPIトークンでは利用できないか、管理が困難な場合があります。
ユーザー生成トークンで継承される権限
ユーザーが生成したアクセストークンは通常、そのトークンを生成したユーザーアカウントの権限を継承します。管理者がトークンを生成した場合、そのトークンには、管理者が実行できるすべてのリソースとアクションに対する完全なアクセス権が付与されます。この懸念を緩和するために、限定的なスコープを持つサービスアカウントを設定してトークンを生成する組織もあります。ただし、そうするとユーザー管理のオーバーヘッドが発生し、ライセンスのシートを消費する可能性があります。
監査の課題
静的トークンの使用状況を追跡するのは困難です。監査における中核的な要件は、ユーザーとAPIの間のやり取りを追跡することです。しかし、静的なAPIトークンには通常、ユーザーコンテキストが含まれていません。APIへのすべての呼び出しで同じ静的なトークンが使用されるため、APIを使った特定のユーザーのアクションを特定することは不可能な場合があります。
静的トークンは脆弱です。
ユーザーアカウントに紐づけられたトークンは、そのユーザーが組織から離れると無効になります。この対策に対処するためにサービスアカウントを使用する組織もありますが、それによってアクセスリスクや管理上のオーバーヘッドが生じます。
静的なAPIトークンに伴うリスクを軽減し、APIにアクセスするための、より優れた安全な方法があります。それは、業界標準のOAuth 2.0フローを使用することです。
OAuth 2.0を導入してセキュリティを強化
OAuth 2.0は、OktaのSSWSトークンのような静的トークンの代わりに、ほぼすべてのシナリオに対応します。ただし、静的なトークンとは異なり、OAuthの仕様には、トークンのローテーション、基本的な認可の判断といった必須事項や、次のような日常的なユースケースのためのセキュアなプラクティスなどが定義されています。
- ユーザーコンテキストなしでバックグラウンドのAPI呼び出しを処理するための、自動化されたサービス間インタラクション
- コマンドライン操作によるタスクベースの自動化
- ユーザーのアクセスレベルに応じてアプリケーションのデータとアクションを制限し、認可のセキュリティを維持する
OAuth 2.0は、一元化された認可サーバーへのリクエストで送信される構成プロパティを通じて、上記の日常的なユースケースのそれぞれをサポートします。一般的なインタラクションは、次のような複数のステップで構成されるプロセスです。
1. 呼び出し元は、ユースケースに必要な設定プロパティを渡して、認可サーバーにアクセストークンを要求します。認可サーバーは、有効期間の短いアクセストークンを返します。トークンの有効期間はユースケースによって異なります。ユースケースによっては元から安全性が高いため、有効期間は変動します。以下のHTTPリクエストは、トークンを取得するためのリクエストの例ですが、必須の構成プロパティは含まれていません。今後の例で、必要な構成プロパティを確認できます。

2. 呼び出し元は、APIリクエストのトークン値を、Bearerスキームを使用してHTTPリクエストのAuthorizationヘッダーの値として使用します。HTTPリクエストは次のようになります。

OAuth 2.0は奥が深いトピックです。詳細については、この記事の最後にあるリソースをご確認ください。本記事では、すべての詳細を掘り下げることはしませんが、前述のユースケースに特化した情報を提供し、それぞれについて概要を説明します。
それぞれのユースケースでOAuth 2.0がどのように対応しているかを見ていきましょう。
サービス間のインタラクション
データを取得したりアクションを実行したりするために、他のAPIを呼び出すバックエンドプロセスが存在する場合があります。OAuth 2.0は、クライアント資格情報と呼ばれる認可フローを使用して、呼び出しに関連付けられたユーザーコンテキストなしで、サービス間またはマシン間のリクエストに対応します。
APIトークンではなくクライアント資格情報を使用するメリット
サービス間のインタラクションにOAuth 2.0を使用すると、静的なAPIキーに比べて大きなメリットがあります。特に、スコープと呼ばれるアクセスレベルに関してその利点は顕著です。OAuth 2.0では、トークンを取得する呼び出しの構成プロパティの一部として、アクセストークンが取得するスコープを特定します。呼び出すAPIがスコープベースのアクセスに対応していること、および必要なスコープへのアクセス権を付与していることを確認する必要があります。例えば、Okta APIでは、リソースAPIに対して`okta.users.read`や`okta.users.write`など、複数のスコープが定義されています。一方または両方のスコープへのアクセスを付与できます。
クライアント資格情報フローは、API認可にサービスアカウントを使用するのと同じではありません。OAuth 2.0は、自動化ユーザーをエミュレートするためにユーザーシートを使用することなく、標準フォーマットでのマシンツーマシンインタラクションをサポートします。スコープを定義する際は、ユーザーレベルではなく、サービスアプリケーションの構成および認可サーバー内で行うことに注意してください。アプリケーション内のユーザーを介してではなく、サービスアプリケーション全体のリソースアクセスを制御できる点がメリットです。サービスアカウントの管理について心配する必要がなくなり、許可した範囲を超えるスコープにアプリケーションがアクセスすることはないと確信できます。
クライアント資格情報を使用してアクセストークンを取得する
このフローのアクセストークンを取得するには、認可フローのタイプ、認証情報、およびアクセストークンが持つスコープを指定するプロパティを送信します。OAuth 2.0では、認可フローを定義するための用語をgrant_typeと呼びます。クライアント資格情報フローの場合、値としてclient_credentialsを渡します。
資格情報には、クライアントの秘密鍵で署名された暗号学的に安全なJSON Web トークン(JWT)、または認可サーバーから生成されたシークレット値のいずれかを使用できます。秘密鍵JWTは、静的なAPIトークンと同様のアクセスに関する懸念を偶発的に生じさせるシークレット値が漏洩するリスクがないため、より安全です。公開/秘密キーのペアを生成し、公開キーをJSON Web Key Set(JWKS)に登録するか、認可サーバーにアップロードします。これにより、認可サーバーは公開キーを使用してJWT署名を検証できるようになります。このプロセスの詳細については、ドキュメント「サービスアプリでOktaのOAuthを実装する」をご覧ください。
アクセストークンを取得するためのHTTP呼び出しの例は、次のようになります。

アクセストークンを取得したら、ヘッダーとしてAPIコールに追加します:Authorization: Bearer access_token。
.NETを使用したサービス間API呼び出しと、PythonでのプライベートJWTの作成について詳しくは、「Secure Your .NET 6 Web API」および「Set Up the Private Key JWT フロー in Three Python Commands」をご覧ください。
タスクベースの自動化
BashやPowerShellなどのコマンドラインターミナルは、ターミナルウィンドウ内で個別のコマンドやスクリプトを実行するためのブラウザーレスプロセスです。これまでのサービス間インタラクションとは異なり、このフローにはユーザーコンテキストが含まれます。コマンドライン操作は自身の認可コンテキストで実行されるため、アクセスが許可されているAPIリソースにのみアクセスできます。OAuth 2.0は、デバイスフローと呼ばれるフローでこのユースケースに対応しています。
このフローでは、アクセストークンの取得は複数のステップからなるプロセスです。サービス間ユースケースのように直接アクセストークンをリクエストする前に、まず認可サーバーの特別なエンドポイントにクライアントIDを送信して、一意の検証コードを取得します。

/device/authorizeの呼び出しからの応答では、デバイスコードとユーザーコードという2つの固有のコードと、検証URIが返されます。ブラウザで検証URIに移動し、ユーザーコードを入力して、認可リクエストを確定します。
アクセストークンを取得するには、呼び出しに構成プロパティとして、ユースケースのOAuth 2.0フローを指定するgrant_typeプロパティとデバイスコードを追加します。

レスポンスのアクセストークンを、`Authorization: Bearer access_token`ヘッダーで使用します。
コマンドラインのDevice Codeフローについて詳しくは、「Authenticate from the Command Line with Java」をご覧ください。
Webアプリケーション経由のユーザーアクセス
最後のユースケースは、Webアプリケーションを使用する際のAPIアクセスにユーザーの認可が適用されるようにするものです。OAuth 2.0は、アプリケーションのアクションを、ユーザーが実行できることや表示できるデータの一部に限定する機能をサポートしています。このフローでは、ユーザーコンテキストを使用してリソースの認可を申請できます。また、ユーザーコンテキストがあることで、個々のユーザーによる呼び出しの監査や追跡がより簡単になります。このユースケースのOAuth 2.0フローは、標準のフローである認可コードフローと、Proof Key for Code Exchange(PKCE)と呼ばれるセキュリティレイヤーを追加するための拡張機能を組み合わせたものです。
PKCEを利用した認可コードフローでは、アクセストークンを取得するために複数のステップが必要になります。これには同意や検証といったユーザーインタラクションが伴い、多要素認証が可能になります。このフローでは、アクセストークンをリクエストする前に、ユーザーを認可サーバーにリダイレクトして認可コードを取得します。
リダイレクトURLには、リクエスト固有のプロパティが含まれており、ユーザーはこれを使用してサインインを完了できます。これには、response_typeプロパティを使用したリクエストタイプの指定やクライアントIDなどのプロパティが含まれます。
ユーザーがサインインに成功すると、アイデンティティプロバイダーは認可レスポンスに認可コードを含めてアプリケーションにリダイレクトします。アクセストークンを取得するには、このフローのグラントタイプ、認可コード、およびリクエスト固有のその他のメタデータを渡します。


アクセストークンを取得したWebアプリは、送信するAPI呼び出しの「Authorization: Bearer access_token」ヘッダーにそのアクセストークンを追加します。
認可コードフローについて詳しくは、「SPAの認証と認可の仕組み」および「OAuth 2.0とSpring BootでPKCEを使用してセキュリティを強化する」をお読みください。
静的なAPIトークンを廃止し、OAuth 2.0を使用する
ソフトウェアの移行には時間と計画が必要であり、優れた戦略を立てることが成功の鍵となります。OAuth 2.0への移行は、小規模かつ段階的に進めることを検討してください。
静的APIトークンからの移行における最初のステップは、使用するAPIがOAuth 2.0をサポートしていることを確認することです。サードパーティのAPIを呼び出している場合は、ベンダーに確認してください。APIが内部向けである場合は、OAuthのサポートを追加する必要があります。呼び出すAPIがOAuthをサポートしていることを確認したら、OAuthアプリケーションのクライアントIDを取得し、スコープなどのアクセス手段を有効にする必要があります。
管理者としてOkta管理コンソールにサインインすると、Okta環境で静的APIトークンを使用しているかどうかを判断できます。サイドバーで[Security(セキュリティ)]>[API]に移動し、[Tokens(トークン)]タブを選択すると、Okta組織で作成されたすべてのトークンが表示されます。このビューでは、APIトークンの使用状況、ユースケース、アクセスレベル(例えば、スーパー管理者が作成したトークンはフルアクセス権を持つ)を把握できます。それぞれを評価し、OAuthを使用するように変換する必要があります。
自動化されたサービス間コールのユースケースに注目してみましょう。APIにOAuth 2.0を一度にすべて組み込むのは大変な作業です。そこで、段階的に組み込む方法を検討してみましょう。コードを変更する前に、ローカルで手動で手順を試し、任意のHTTPクライアントを使用してOAuth 2.0でトークンをリクエストし、APIを呼び出すことができます。このケースでは、秘密鍵JWTを使用したクライアント資格情報フローを使用します。手順は次のとおりです。
- 公開鍵と秘密鍵のペアを生成する
- 公開/秘密キーペアを使用して、秘密キーJWTを生成します。
- アクセストークンを要求する
- APIリクエストにアクセストークンを追加する
- アプリケーションシステムにOAuthを組み込む
1. 公開/秘密鍵ペアを生成する
こちらの手順に従って、公開鍵と秘密鍵のペアを生成できます。Oktaの管理コンソールでは、キーペアを自分で生成したくない場合に、テスト目的で公開/秘密キーペアを生成できます。
2. private key JWTを生成する
公開/秘密キーペアを使用して、ドキュメント「サービスアプリでOAuth for Oktaを実装する」の手順に従って秘密キーJWTを作成します。このステップでは、手順を自動化することよりも、全体の仕組みを理解することのほうが重要です。そのため、現時点では、公開鍵と秘密鍵のペアをローカルに保存し、お使いのマシンにインストールしたツールを使用して、公開鍵を含むJWKSをテストJWTジェネレーターのWebサイトに貼り付けてください。
3. アクセストークンを要求する
任意のHTTPクライアントでHTTPリクエストを作成し、スコープを追加せずに、秘密鍵のJWTを使用してアクセストークンを要求します。適切なスコープなしでアクセストークンを使用するとエラーが発生するはずですが、エラーパスと正常パスの両方をテストすることをお勧めします。アクセストークンはいずれ有効期限が切れ、その有効期限はアクセストークンのレスポンスで確認できます。アクセストークンはレスポンスの一部です。文字列全体をアクセストークンとして使用します。
4. アクセストークンをAPIリクエストに追加する
HTTPクライアントを使用して、アクセストークンでAPIを呼び出します。Authorizationヘッダーを追加してBearerスキームを使用します。これにより、API呼び出しには、以下の形式に一致するヘッダーが含まれることになり。

APIコールを行うと、HTTPステータス403エラーが返されます。成功しました。はい、エラーケースのテストは成功です。これで、スコープの構成にエラーがある場合に、どのようなエラーが想定されるかがわかります。アクセストークンリクエストにスコープを追加して、もう一度試してみましょう。
今回は、秘密鍵JWTを使用してアクセストークンをリクエストし、API呼び出しのスコープを追加します。API呼び出しでアクセストークンを使用する。真価が問われるときです。正常な応答が返されるはずです。再度403エラーが発生した場合は、設定に誤りがあることがわかります。この問題が発生した場合は、リクエストスコープを再確認し、要求しているスコープがOAuth 2.0アプリケーションで有効になっていることを確認してください。
5. システム内にOAuth 2.0認可を追加する
サーバー間(server-to-service)の呼び出しに対するOAuth 2.0の認可を手動で正常に実行できたので、これらの手順の一部をシステムに統合できます。開発環境またはテスト環境で、アクセストークンを使用してみてください。アクセストークンを要求する手順を自動化せずにAPI呼び出しが機能するようにするには、APIを変更してBearerスキーム形式でAuthorizationヘッダーを使用し、既存の静的APIトークンを手動で生成したアクセストークンに置き換える必要があります。
APIシステムがアクセストークンを正常に処理できるようになったら、コード内からアクセストークンをリクエストするステップを追加します。お使いの技術スタックには、リクエストのステップの少なくとも一部(またはすべて)を支援するSDKが含まれている場合があります。OktaのManagement SDKを使用すると、OAuth 2.0のハンドシェイクを代行できます。Java SpringユーザーはSpring Securityのドキュメントを、.NET CoreユーザーはMicrosoft.AspNetCore.Authenticationをそれぞれ例として参照してください。作業を進めながら、ハッピーパス、エラーケース、およびアクセストークンの有効期限切れを正しく処理するなどのシナリオの両方について、必ずテストを実施してください。
本番環境に変更を展開する前に、本番環境レベルのツールを使用してJWKSを内部で生成し、秘密鍵を安全に管理していることを確認してください。
API認可の移行におけるベストプラクティス
静的トークンからの即時移行は、特に大規模な組織や、更新すべきAPIが多数ある場合には、必ずしも現実的ではありません。現在もOktaでSSWSトークンを使用している場合は、OAuth 2.0に移行するまでリスクを軽減する必要があります。ベストプラクティス:
- OAuth 2.0を使用して、新しいAPIコールまたはコードを実装する。
- 最小権限の原則に従う。例えば:
- サービスアカウントの確立に個人アカウントを使用しない。
- サービスアカウントにはカスタム管理者ロールを使用し、必要不可欠な権限のみを付与します。
- グループとグローバルセッションポリシーを使用して、サービスアカウントの対話型ログインを防止します。
OAuth 2.0でAPI呼び出しのセキュリティを確保する
静的トークンからOAuth 2.0に移行することは、単に新しいテクノロジーを導入するだけでなく、より安全で柔軟、かつ開発者に優しいエコシステムへと転換することを意味します。静的なトークンにもそれなりの役割がありましたが、将来は動的でユーザー中心のセキュアなOAuth 2.0ソリューションにあることは明らかです。
テクノロジーの進歩に伴い、常に最新情報を入手し、ベストプラクティスに適応していくことは、単に有益であるだけでなく、不可欠であることを忘れないでください。OAuth 2.0に移行して、より安全で、合理化された、効率的な開発者体験を実現しましょう。
OAuth 2.0の次のステップ
この記事が役に立ったと思われた方は、こちらの記事もあわせてご覧ください。
OktaのAPIセキュリティに関する開発者向けガイドで、OAuth 2.0への移行を始めましょう。
Demonstrating Proof-of-Possession(DPoP)を構成する
- このガイドでは、さまざまなエンドポイントでのトークンのリプレイを防止するアプリケーションレベルのメカニズムである、送信者制約付きアクセストークンを作成する方法について説明します。
- このガイドでは、スコープが限定されたOAuth 2.0アクセストークンを使用してOkta APIを操作する方法について説明します。OAuth for Okta:サービスアプリの構成
- このガイドでは、サービスアプリでスコープが限定されたOAuth 2.0アクセストークンを使用してOkta APIを操作する方法について説明します。
- Oktaを使用して認可を追加し、APIを保護します。完了すると、受信リクエストを検証するセキュアなREST APIアプリケーションが完成します。
- このガイドでは、サードパーティプロバイダーからリスクイベントを受信するようにOkta orgを構成する方法について説明します。OAuth 2.0で組織間のAPI接続のセキュリティを確保する
- このガイドでは、マルチテナントソリューションでOAuth 2.0を使用してユーザーとグループを同期するために、Oktaのハブアンドスポーク組織を安全に設定する方法について説明します。Org2Org統合アプリでOAuth 2.0クライアント認証情報フローを使用して、Okta orgのAPIアクセスをスコープ付きデータに接続します。
- このガイドでは、エンドユーザーの保証レベルを高めるために、認可リクエストにacr_valuesパラメーターを含める方法について説明します。
最新情報を見逃さないよう、Xで@oktadevをフォロー、LinkedInでOktaを検索、YouTubeチャンネルにご登録ください。
