はじめに
OAuth (Open Authorization) 認証プロトコルを使用すると、ユーザーは、ログイン資格情報を公開せずに、サードパーティ アプリケーションにプライベートリソースへのアクセスを許可できます。また、アクセスできる情報の量を制限することもできます。
OAuthは、ユーザー ロール (別名 リソース所有者) を従来のクライアントサーバー認証モデルに導入します。従来のクライアントサーバー認証モデルでは、クライアントはサーバーでホストされているリソースに直接アクセスします。OAuth モデルでは、クライアントはサーバーからリソースにアクセスする前に、まずリソース所有者から許可を取得する必要があります。この許可は、トークンと一致する共有秘密鍵の形式で表されます。
OAuth 2.0 と 1.0a は異なる実装であり、互換性がありません。詳細については、OAuth の Web サイトを参照してください: https://oauth.net/2/
サンプル シナリオ
ユーザー (リソース所有者) が、写真共有サービス (サーバー) に保存されている自分のプライベート写真へのアクセスを印刷サービス (クライアント) に許可したいとします。ユーザーのログイン資格情報を印刷サービスに公開する代わりに、ユーザーは OAuth 認証を実行して、印刷サービスに自分のプライベート写真にアクセスするためのアクセス許可を付与できます。これは 3 つの段階で発生します。
- 印刷サービスは、写真共有サービスに一時的な資格情報を要求します。
- 印刷サービスは資格情報を受け取ると、ユーザーを写真共有サービスの OAuth 認証 URL にリダイレクトし、ユーザーはログイン資格情報を提供します。このステップでは、印刷サービスはユーザーのログイン資格情報を認識できないことに注意してください。ユーザーが印刷サービスにプライベート写真へのアクセスを許可することを決定すると、検証コードが生成されます。
- 次に、印刷サービスは、一時的な資格情報と検証コードをアクセス トークンと交換します。印刷サービスがアクセス トークンを取得すると、写真共有サービスからユーザーのプライベート写真を取得して印刷できます。
OAuth に対する Parasoft のサポート
Parasoft は、Web サーバー フローとクライアント資格情報フローの OAuth 1.0a および 2.0 セキュリティ プロトコルをサポートします (2 本足シナリオ)。OAuth 1.0a および OAuth 2.0 を使用した認証の構成については、以下で説明します。
OAuth 2.0
OAuth 2.0 RFC は、認証にさまざまな「フロー」または「許可タイプ」を指定しています。このドキュメントでは、最も一般的な 3 つのフローを SOAtest で使用する方法について説明します。PKCE があるまたはない Web サーバー (認証コード) フローとクライアントの資格情報フローです。
OAuth 2.0 フローの詳細については https://oauth.net/2/grant-types/ を参照してください。
Web サーバー (認証コード) フロー
この許可タイプは、アクセス トークンの認証コードを交換するために confidential クライアントと public クライアントによって使用されます。ユーザーがリダイレクト URL を介してクライアントに戻った後、アプリケーションは URL から認証コードを取得し、それを使用してアクセス トークンを要求します。このフローの詳細については、OAuth 2.0 Framework のドキュメントを参照してください: https://tools.ietf.org/html/rfc6749#section-4.1
SOAtest でこれをセットアップするには、まず、ログイン スイートとして使用する認証コードを取得するテスト シナリオを作成する必要があります。このログイン スイートは、トークンを必要とするテスト シナリオによって呼び出されます。認証コードを Proof Key for Code Exchange (PKCE) で使用するかどうかにかかわらず、手順は同じです。ただし、PKCE を使用する場合は、設定が必要な追加の変数がいくつか存在します。
ログイン テスト スイートを作成する
- プロジェクト フォルダーを右クリックし、[新規追加] > [テスト (.tst) ファイル] を選択します。
- テストの名前を指定し、[Web] > [Web シナリオの記録] を選択します。
- [次へ] をクリックし、[新規 Web シナリオの記録] を選択します。
- [次から記録を開始] フィールドに認証エンドポイント URL の URL を入力し、[次へ] をクリックします。
テスト対象アプリケーション (AUT) の URL は使用しないでください。これは、認証エンドポイント (つまりログイン ページ) に自動的にリダイレクトされます。認証エンドポイント自体の URL を使用する必要があります。そうしないと、テストでトークンを使用する前にテスト対象アプリケーションがトークンを消費します。
- [既存の環境に URL 変数を追加] を有効にして、[終了] をクリックします。アプリケーションのログイン ページが開きます。
- アプリケーションにログインします。承認されると、サービス プロバイダーは、URL パラメーターの一部としてコードを使用してコールバック URL にリダイレクトします。
- ブラウザーを閉じて記録を完了します。
- テストを 1 回実行して、テストにトラフィックを入力します。
- ログイン アクションを含むテスト ノード (これはログイン手順によって異なりますが、通常は記録されたシナリオの最後のテストです) を右クリックし、[出力の追加] を選択し、HTTP トラフィック を有効にします。
- [次へ] をクリックし、アクセス コードを含むリダイレクトされた URL を選択します。
リクエスト URL は、使用するアプリケーションによって異なります。たとえば、Azure AD の場合、リクエスト URL は https://login.microsoftonline.com/kmsi のように始まりますが、Keycloak の場合、リクエスト URL は https://localhost:8443/auth/realms/my-realm/login-actions/authenticate のようになります。いずれの場合も、URL には
?code=
パラメーターとそれに続くアクセス コードが含まれます。
- [次へ] をクリックし、[レスポンス] を選択します。コードを抽出するには、[ヘッダー] > [Text Data Bank] をクリックします。
- [終了] をクリックしてテストを再度実行し、Text Data Bank に入力します。
- Text Data Bank を開き、[テキスト コンテンツ] で、コードを含むリダイレクトの場所を見つけます (通常は Location ヘッダーにあります)。その URL に認証コードがあるはずです ("code=" パラメーターが前に付いています)。そのコードを選択し、[選択対象からデータ抽出を作成] をクリックします。
OAUTH2_AUTHORIZATION_CODE
という名前を付けて、[OK] をクリックします。 - 推奨: 認証エンドポイントをパラメータライズします。ログイン スイートで認証エンドポイントのパラメーターを設定すると、OAuth 2.0 共有認証機能を使用した多くのテストで参照される汎用ログイン スイートとしての適応性が高まります。操作手順:
- 記録されたシナリオで認証エンドポイントに移動するテストを開き (通常、これは最初のテストです)、[ユーザー アクション] タブを選択します。
[URL] フィールドで、必要に応じて、次のパラメーターを静的な値から指定されたテスト スイート変数に変更します (該当する場合):
パラメーター 変数 client_id ${OAUTH2_CLIENT_ID}
redirect_id ${OAUTH2_REDIRECT_URI}
scope ${OAUTH2_SCOPE}
audience ${OAUTH2_AUDIENCE}
- 付与タイプとして
Authorization Code with PKCE
を選択した場合は、追加のパラメータライズ要件について次の手順を参照してください。
- 付与タイプとして
- 変更を保存します。
- PKCE ありの認証コードを使用している場合、認証エンドポイントは、
code_challenge
およびcode_challenge_method
パラメーターの変数を受け入れるように設定する必要があります。そのためには:- 記録されたシナリオで認証エンドポイントに移動するテストを開き (通常、これは最初のテストです)、[ユーザー アクション] タブを選択します。
[URL] フィールドで、次のパラメーターを静的な値から指定されたテスト スイート変数に変更します。
パラメーター 変数 code_challenge ${OAUTH2_CODE_CHALLENGE}
code_challenge_method ${OAUTH2_CODE_CHALLENGE_METHOD}
- 変更を保存します。
上記の変数の 1 つ以上を設定して認証エンドポイントをパラメータライズしたが、それでも Web シナリオを個別に実行できるようにしたい場合は、[変数] タブでパラメータライズされた値のデフォルト値を設定できます。詳細については、テスト スイートのプロパティ設定 (テスト フロー ロジック、 変数など) ページの「変数の定義」を参照してください。
テスト スイートの共有 OAuth 2.0 認証を設定する
- テスト スイートを右クリックし、[新規追加] > [グローバル プロパティ] を選択します。
- [認証] リストを展開し、[OAuth 2.0] を選択して [次へ] をクリックします。
- 付与タイプを
Authorization Code
またはAuthorization Code with PKCE
に適宜設定し、[終了] をクリックします。OAuth 2.0 認証の設定画面が開きます。 - [名前] フィールドにわかりやすい名前を入力します。
- 以下の説明に従って、残りの設定を構成します。ログイン スイートで認証エンドポイントをパラメータライズすることを選択した場合、これらの設定は適切な OAuth 2.0 トークンを取得するために使用されます。認証エンドポイントをパラメータライズしていない (またはその一部のみをパラメータライズした) 場合は、パラメータライズされていない設定が認証エンドポイント URL の設定と正確に一致していることを確認してください。
- Login Suite: [ワークスペース] をクリックし、上記で作成したログイン スイートを選択します。
- Redirect URI: OAuth 2.0 トークンを使用しないリダイレクト URI を入力します。この URI は、認証サーバーのリダイレクト URI のホワイトリストにある必要があります。
- Token URI: OAuth 2.0 認証サーバーのアクセス トークン エンドポイントを入力します。
- Client ID: 認証サーバーでの認証に必要なクライアント ID を入力します。
- Client Secret: 認可サーバーでの認証に必要なクライアント シークレットを入力します。
- Scope: このパラメーターは、アプリケーションへの制限付きアクセスを要求するためにクライアントによって使用されます。認証サーバーに固有の値のカンマ区切りリストを入力できます。詳細については https://oauth.net/2/scope/ を参照してください。スコープが指定されていない場合、デフォルトのスコープが返されることがあります。
- Audience: リソース サーバーの URI を入力します。
- Code Verifier (Authorization Code with PKCE のみ): コード ベリファイアを生成する方法を選択します。デフォルトでは、これは自動的に行われます。この方法が推奨されています。自動生成されたコード ベリファイアは OAuth 2.0 標準に準拠し、文字 A ~ Z、a ~ z、0 ~ 9、および - . _ ~ (ハイフン、ピリオド、アンダースコア、チルダ) を使用した暗号的にランダムな文字列であり、長さは 43 から 128 文字です。別の方法を選択する場合は、結果が同じ基準を満たしていることを確認してください。そうしないと、トークン リクエストが拒否される可能性があります。
- Challenge Method (Authorization Code with PKCE のみ): コード チャレンジがプレーン テキスト バージョンのコード ベリファイアであるか、SHA-256 バージョンのコード ベリファイアであるかを選択します。
- ヘッダーを使用してアクセス トークンを送信するか、クエリ パラメーターを使用して送信するかを選択します。
- 構成を保存します。
テスト シナリオを作成する
テスト シナリオを作成するプロジェクトを右クリックし、[新規追加] > [テスト (.tst) ファイル] を選択します。アプリケーションとテストのニーズに合わせて、このシナリオの作成を完了します。使用するシナリオが既にある場合は、この手順を省略できます。
負荷テスト
このシナリオの負荷テストを行う場合は、テストをグループとして実行するようにテスト スイートを構成する必要があります (テスト スイートを開き、[実行オプション] > [テスト実行] タブに移動します)。テスト スイートが [個別にテストを実行可能] オプションを有効にして構成されている場合、OAuth 2.0 アクセス トークンを再利用することなく各仮想ユーザーはスイート内のテストの 1 つを分離して実行します。そして Load Test は新しいアクセス トークンを取得するためにログイン スイートを繰り返し実行する必要があります。
- テスト シナリオを右クリックし、[新規追加] > [テスト] をクリックします。メソッドを GET に、URL を AUT に設定して、テスト シナリオで新しい REST クライアントを作成します。
- 以前に作成した共有認証がこのテスト スイート用に作成された唯一のものである場合、それが自動的に使用されます。それ以外の場合は、[セキュリティ] の下の [認証] をクリックし、[認証] ペインの最初のドロップダウン メニューから [カスタム] を選択します。
- シナリオを実行し、OAuth 2.0 トークンが取得されて正常に使用されたことを確認します。
クライアント資格情報フロー
この許可タイプは、ユーザーのコンテキスト外でアクセス トークンを取得するためにクライアントによって使用されます。これは通常、ユーザーのリソースにアクセスするためではなく、クライアント アプリケーションによって自身に関するリソースにアクセスするために使用されます。このフローの詳細については、OAuth 2.0 Framework のドキュメントを参照してください: https://tools.ietf.org/html/rfc6749#section-4.4
テスト スイートの共有 OAuth 2.0 認証を設定する
- テスト スイートを右クリックし、[新規追加] > [グローバル プロパティ] を選択します。
- [認証] リストを展開し、[OAuth 2.0] を選択して [次へ] をクリックします。
- 付与タイプを
クライアント認証情報
に設定し、[終了 ]をクリックします。OAuth 2.0 認証の設定画面が開きます。 - [名前] フィールドにわかりやすい名前を入力します。
- 残りの設定を行います:
- Token URI: OAuth 2.0 認証サーバーのアクセス トークン エンドポイントを入力します。
- Client ID: 認証サーバーでの認証に必要なクライアント ID を入力します。
- Client Secret: 認可サーバーでの認証に必要なクライアント シークレットを入力します。
- Scope: (オプション) アクセス トークンのスコープを指定します。複数のパラメーターが必要な場合は、カンマで区切ります。詳細については https://oauth.net/2/scope/ を参照してください。スコープが指定されていない場合、デフォルトのスコープが返されることがあります。
- Audience: (オプション) リソース サーバーの URI を入力します。
- ヘッダーを使用してアクセス トークンを送信するか、クエリ パラメーターを使用して送信するかを選択します。
- 構成を保存します。
テスト シナリオを作成する
- テスト スイートを右クリックし、[新規追加] > [テスト] をクリックします。テスト スイートに新しい REST クライアントを作成します。
- [HTTP オプション] タブをクリックし、[トランスポート] メニューから HTTP 1.0 または HTTP 1.1 を選択します。
- 以前に作成した共有認証がこのテスト スイート用に作成された唯一のものである場合、それが自動的に使用されます。それ以外の場合は、[セキュリティ] の下の [認証] をクリックし、[認証] ペインの最初のドロップダウン メニューから [カスタム] を選択します。
- [リソース] タブをクリックし、必要なパラメーターを含めて、REST 呼び出しメソッドとエンドポイントを指定します。
- OAuth 2.0 アクセス トークンが自動的に挿入されます。
- シナリオを実行し、送信されたと予想される HTTP リクエスト ヘッダーを確認します。認証ヘッダーの例:
Authorization: Bearer 2YotnFZFEjr1zCsicMWpAA
負荷テストに関する考慮事項
シナリオのロード テストを行う場合は、その親テスト スイート ([実行オプション] > [テスト実行] タブにあります) で [グループとしてテストを実行] を有効にする必要があります。このオプションでは、各仮想ユーザー (VU) がシナリオ全体を実行できるため、各 VU は独自の OAuth 2.0 アクセス トークンを取得して再利用できます。代わりに [個別にテストを実行可能] を有効にすると、各 VU はスイートから 1 つのテストを分離して実行します。このとき、アクセストークンは再利用せず、各テストが独自のトークンを取得します。その結果、新しいアクセストークンを取得するためにログインスイートが繰り返し実行されます。
トラブルシューティング
OAuth 2.0 に関連するエラーは、通常、OAuth 2.0 認証コードを取得する際のエラーとアクセス トークンを取得する際のエラーの 2 つのタイプに分類できます。トラブルシューティングを開始する前に、[品質タスク] ビューでエラーを確認して、発生している問題の種類を特定してください。
認証コードの取得に問題がある場合:
- ログイン スイートを直接実行して、期待どおりに動作することを確認してください。
- ログイン スイートで認証エンドポイントをパラメータライズした場合でも、[変数] タブでパラメータライズされた値のデフォルト値を設定することで、独立して実行できます。詳細については、「テスト スイートのプロパティ設定 (テスト フロー ロジック、 変数など)」の「変数の定義」を参照してください。
- テストの実行中にコンソール ビューでメッセージを確認します。
問題がアクセス トークンの取得にある場合:
- [品質タスク] ビューで OAuth 2.0 エラーに関連するトラフィックを右クリックし、[関連するトラフィックの表示] を選択して、関連するトラフィックを確認します。
OAuth 1.0a
OAuth 1.0a に対する認証には、次の一般的な手順が含まれます。
- サービス プロバイダーからリクエスト トークンを取得して承認します。
- リクエスト トークンをアクセス トークンと交換します。
- 保護されたリソースにアクセスするための OAuth リクエストに署名します。
次の例では、REST Client を使用してリクエスト メッセージをサーバーに送信します。または、同じ方法で Messaging Client を使用することもできます。
サービス プロバイダーからリクエスト トークンを取得して承認
- 新しい REST Client を作成し、リクエスト トークンを取得する場所の設定を構成します。
- [HTTP オプション] タブをクリックし、[トランスポート] メニューから HTTP 1.0 または HTTP 1.1 を選択します。
- [セキュリティ] の下の [認証] をクリックします。
- [認証] ペインの最初のドロップダウン メニューから [カスタム] を選択します。
- リクエスト トークンを取得するように構成された OAuth 1.0 共有認証がテスト スイートに設定されている場合 (「テスト スイートのプロパティ設定 (テスト フロー ロジック、 変数など)」の「クライアント オプションの指定」を参照)、2 番目のドロップダウン メニューからそれを選択し、手順 11 にスキップできます。
- [新規] をクリックし、[OAuth 1.0] を選択して [終了] をクリックします。テスト スイートの認証ノードに OAuth 1.0 認証が追加されます (これがテスト スイートに追加された最初のカスタム認証である場合、認証ノードは自動的に作成されます)。
- [名前] フィールドにわかりやすい名前を入力します。
- [コンシューマー キー] フィールドと [コンシューマー シークレット] フィールドに、コンシューマ キーとコンシューマ シークレットを入力します。
- [モード] メニューから [リクエスト トークンの取得] を選択します。
- (オプション) [スコープ] フィールドでスコープを指定します。
- (オプション) [パラメーター] の下に追加の OAuth パラメーターを追加します。
- Text Data Bank を REST Client の Response Traffic に接続し、リクエスト トークンとリクエスト トークン シークレットを抽出します。トークンは通常、
oauth_token
として示されます。 - メイン メニューから [ファイル] > [新規作成] > [テスト ファイル (.tst)] を選択し、プロジェクトを選択します。
- ファイルの名前を入力し、[次へ] をクリックします。
- [Web] > [Web シナリオの記録] を選択し、[次へ] をクリックします。
- [新規 Web シナリオの記録] を選択し、[次へ] をクリックします。
- [次から記録を開始] フィールドに、検証コードを取得するための URL を入力します。
oauth_token
パラメーターを追加し、手順 10 で取得したリクエスト トークンの値を指定します。
ブラウザーが起動すると、保護されたリソースをホストしているサーバーのログイン ページが表示されます。 - ユーザーのログイン資格情報(ユーザー名/パスワード)を入力してサインインします。承認されると、ブラウザーは検証コードを含む新しいページにリダイレクトします。
- 検証コードが表示されたら、ブラウザーを閉じて記録を終了します。
- Browser Data Bank を Browser Contents(レンダリングされたHTML)に添付し、検証コードの値を抽出します。
- Browser Playback ツールを開き、リテラルの Request Token 文字列を、Text Data Bank によって生成された Request Token データ ソース列に置き換えます (ステップ 10)。以下に示すように、
${varName}
構文を使用します。
リクエスト トークンをアクセス トークンと交換する
- 新しい REST Client を作成し、リクエスト トークンをアクセス トークンと交換する場所の設定を構成します。
- [HTTP オプション] をクリックし、[トランスポート] メニューから HTTP 1.0 または HTTP 1.1 を選択します。
- [セキュリティ] の下の [認証] をクリックします。
- [認証] ペインの最初のドロップダウン メニューから [カスタム] を選択します。
- リクエスト トークンをアクセス トークンと交換するように構成された OAuth 1.0 共有認証がテスト スイートに設定されている場合 (「テスト スイートのプロパティ設定 (テスト フロー ロジック、 変数など)」の「クライアント オプションの指定」を参照)、2 番目のドロップダウン メニューからそれを選択して手順 10 に進むことができます。
- [新規] をクリックし、[OAuth 1.0] を選択して [終了] をクリックします。テスト スイートの認証ノードに OAuth 1.0 認証が追加されます (これがテスト スイートに追加された最初のカスタム認証である場合、認証ノードは自動的に作成されます)。
- [コンシューマー キー] フィールドと [コンシューマー シークレット] フィールドに、コンシューマ キーとコンシューマ シークレットを入力します。
- [モード] メニューから [リクエスト トークンとアクセス トークンの交換] を選択します。
- Text Data Bank の抽出からの Request Token フィールドと Request Token Secret フィールドをパラメータライズします。
- Browser Data Bank. の [検証コード] フィールド をパラメータライズします。
- Text Data Bank を REST Client の Response Traffic に連結し、アクセストークン (通常 oauth_token) とアクセス トークン シークレット (通常 oauth_token_secret) を抽出します。
OAuth リクエストに署名して保護されたリソースにアクセスする
- 新しい REST Client を作成し、リクエスト トークンをアクセス トークンと交換する場所の設定を構成します。
- [HTTP オプション] をクリックし、[トランスポート] メニューから HTTP 1.0 または HTTP 1.1 を選択します。
- [セキュリティ] の下の [認証] をクリックします。
- [認証] ペインの最初のドロップダウン メニューから [カスタム] を選択します。
- OAuth 認証のリクエストに署名するように構成された OAuth 1.0 共有認証がテスト スイートに設定されている場合 (「テスト スイートのプロパティ設定 (テスト フロー ロジック、 変数など)」の「クライアント オプションの指定」を参照)、2 番目のドロップダウン メニューからそれを選択し、手順 9 に進むことができます。
- [新規] をクリックし、[OAuth 1.0] を選択して [終了] をクリックします。テスト スイートの認証ノードに OAuth 1.0 認証が追加されます (これがテスト スイートに追加された最初のカスタム認証である場合、認証ノードは自動的に作成されます)。
- [コンシューマー キー] フィールドと [コンシューマー シークレット] フィールドに、コンシューマ キーとコンシューマ シークレットを入力します。
- [モード] メニューから [OAuth 認証のリクエストに署名] を選択します。
- Text Data Bank の抽出からの Access Token フィールドと Access Token Secret フィールドをパラメータライズします。
- ユーザーのプライベート リソースを要求します。これは、アクセス トークンが取得されているために可能であるはずです。