認可プロバイダ・ファンクションを使用したAPIデプロイメントへの認証および認可の追加

APIゲートウェイにデプロイするAPIへのアクセスは、認可プロバイダ・ファンクション(このトピックで説明)またはJWT (JSON Webトークン(JWT)を使用したAPIデプロイメントへの認証および認可の追加を参照)を使用して制御できます。

APIゲートウェイに認証および認可機能を追加するには、次のような「認可プロバイダ・ファンクション」を記述します:

  • リクエスト属性を処理して、アイデンティティ・プロバイダでエンド・ユーザーのアイデンティティを確認します。
  • エンド・ユーザーが実行を許可される操作を決定します。
  • 「アクセス・スコープ」のリストとして、エンド・ユーザーが実行を許可されている操作を返します(「アクセス・スコープ」は、アクセスの決定に使用される任意の文字列です)。
  • オプションで、APIデプロイメントで使用するキーと値のペアを返します。たとえば、HTTPバック・エンド定義で使用するコンテキスト変数です(ポリシーおよびHTTPバック・エンド定義へのコンテキスト変数の追加を参照)。

その後、認可プロバイダ・ファンクションをOracle Functionsにデプロイします。認可プロバイダ・ファンクションの作成を参照してください。認可プロバイダ・ファンクションの例が示された関連する開発者チュートリアルについては、ファンクション: APIゲートウェイを使用したAPIキーの検証を参照してください。

認可プロバイダ・ファンクションをデプロイした後、APIデプロイメント仕様に2種類の異なるリクエスト・ポリシーを含めることにより、APIデプロイメントに対する認証および認可を有効にします:

  • 次を指定するAPIデプロイメント全体の認証リクエスト・ポリシー:
    • 認証および認可を実行するOracle Functionsにデプロイした認可プロバイダ・ファンクションのOCID。
    • 認可プロバイダ・ファンクションに渡すリクエスト属性。
    • 認証されていないエンド・ユーザーがAPIデプロイメントのルートにアクセスできるかどうか。
  • 認可プロバイダ・ファンクションにより返されたエンド・ユーザーのアクセス・スコープに基づいてエンド・ユーザーが実行できる操作を指定する、各ルートの認可リクエスト・ポリシー。

次を実行して、認証および認可リクエスト・ポリシーをAPIデプロイメント仕様に追加できます:

  • コンソールの使用。
  • JSONファイルの編集。
ヒント

認可プロバイダ・ファンクションの問題のトラブルシューティングについては、ログ・レベルを「情報」に設定して、APIデプロイメントに実行ログを追加することを検討してください(APIデプロイメントへのロギングの追加を参照)。

認証および認可に関連するログ・ファイルの詳細を表示するには、customAuthを検索します。

認可プロバイダ・ファンクションを使用するための前提条件

認可プロバイダ・ファンクションを使用してAPIデプロイメントの認証および認可を有効化する前に:

  • アイデンティティ・プロバイダ(たとえば、Oracle Identity Cloud Service (IDCS)、Auth0)は、すでに設定されている必要があります(APIデプロイメントへのアクセスを許可されたユーザーのアクセス・スコープを含む)。詳細は、アイデンティティ・プロバイダ・ドキュメント(たとえば、Oracle Identity Cloud Service (IDCS)ドキュメントAuth0ドキュメント)を参照してください。
  • 認可プロバイダ・ファンクションは、すでにOracle Functionsにデプロイされている必要があります。適切なポリシーにより、APIゲートウェイにOracle Functionsへのアクセス権が付与されている必要があります。詳細は、認可プロバイダ・ファンクションの作成を参照してください。

コンソールを使用して(JSONファイルの編集ではなく)認証リクエスト・ポリシーを含める場合は、認可プロバイダ・ファンクションおよびそれを含むアプリケーションをリストから選択します。

(JSONファイルではなく)コンソールを使用して認証リクエスト・ポリシーを定義し、認可プロバイダ・ファンクションを指定するには、IAMポリシーによって認可プロバイダ・ファンクションへのアクセス権が付与されたグループにユーザー・アカウントが属している必要があります(ファンクションへのAPIゲートウェイ・ユーザー・アクセスを提供するポリシーの作成を参照)。

認可プロバイダ・ファンクションの作成

認可プロバイダ・ファンクションを作成するには:

  1. 認証および認可を実装するコードを記述します:

    1. APIゲートウェイからの次のJSON入力を受け入れる認可プロバイダ・ファンクションのコードを記述します:

      
      {
        "type": "TOKEN",
        "token": "<token-value>"
      }

      ここでは:

      • "type": "TOKEN"は、認可プロバイダ・ファンクションに渡される値が認証トークンであることを示します。
      • "token": "<token-value>"は、認可プロバイダ・ファンクションに渡される認証トークンです。

      例:

      
      {
        "type": "TOKEN",
        "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1nHyDtTwR3SEJ3z489..."
      }
    2. アクセス・トークンが正常に検証されたときに、次のJSONをHTTP 200レスポンスとしてAPIゲートウェイに戻す認可プロバイダ・ファンクションのコードを記述します:

      {
        "active": true,
        "principal": "<user-principal>",
        "scope": ["<scopes>"],
        "clientId": "<client-id>",
        "expiresAt": "<date-time>",
        "context": {
          "<key>": "<value>", ... 
        }
      }

      ここでは:

      • "active": trueは、当初認可プロバイダ・ファンクションに渡されたアクセス・トークンが正常に検証されたことを示します。
      • "principal": "<user-principal>"は、アイデンティティ・プロバイダの認可プロバイダ・ファンクションによって取得されるユーザーまたはアプリケーションです。
      • "scope": ["<scopes>"]は、アイデンティティ・プロバイダの認可プロバイダ・ファンクションによって取得されるアクセス・スコープである文字列のカンマ区切りリストです。
      • "clientId": "<client-id>"は、オプションでリクエスタのホスト(たとえば、ホスト名またはクライアントIP)です。clientIdを戻す必要はありません。
      • "expiresAt": "<date-time>"は、ISO-8601フォーマットの日時文字列で、最初に認可プロバイダ・ファンクションに渡されるアクセス・トークンの期限を示します。この値は、認可プロバイダ・ファンクションのコール後に結果のキャッシュ期間を決定する際に使用されます。
      • "context": {"<key>": "<value>", ... }は、APIゲートウェイに戻るための、JSONフォーマットのキーと値のペアのオプションのカンマ区切りリストです。認可プロバイダ・ファンクションは、APIデプロイメントで使用する任意のキーと値のペア(たとえば、エンド・ユーザーのユーザー名や電子メール・アドレス)を返すことができます。認可プロバイダ・ファンクションによって返されるキーと値のペアでの値をHTTPバック・エンド定義のコンテキスト変数として使用する際の詳細は、ポリシーおよびHTTPバック・エンド定義へのコンテキスト変数の追加を参照してください。

      例:

      {
        "active": true,
        "principal": "https://example.com/users/jdoe",
        "scope": ["list:hello", "read:hello", "create:hello", "update:hello", "delete:hello", "someScope"],
        "clientId": "host123",
        "expiresAt": "2019-05-30T10:15:30+01:00",
        "context": {
          "email": "john.doe@example.com"
        }
      }
    3. トークン検証に失敗した場合あるいは認可プロバイダ・ファンクションまたはOracle Functionsでエラーが発生した場合に、HTTP 5xxレスポンスとしてAPIゲートウェイに次のJSONを返すコードを記述します:

      {
        "active": false,
        "wwwAuthenticate": "<directive>"
      }

      ここでは:

      • "active": falseは、最初に認可プロバイダ・ファンクションに渡されたアクセス・トークンが正常に検証されていないことを示します。
      • "wwwAuthenticate": "<directive>"は、検証が失敗した場合に認可プロバイダ・ファンクションによって戻されるWWW-Authenticateヘッダーの値で、必要な認証のタイプ(BasicやBearerなど)を示します。APIゲートウェイは、WWW-AuthenticateヘッダーをAPIクライアントへのレスポンスで返し、401ステータス・コードも返します。たとえば、"wwwAuthenticate": "Bearer realm=\"example.com\""です。詳細は、RFC 2617 HTTP Authentication: Basic and Digest Access Authenticationを参照してください。

      例:

      {
        "active": false,
        "wwwAuthenticate": "Bearer realm=\"example.com\""
      }

    認可プロバイダ・ファンクションの例が示された関連する開発者チュートリアルについては、ファンクション: APIゲートウェイを使用したAPIキーの検証を参照してください。

  2. コードからDockerイメージを作成し、DockerイメージをDockerレジストリにプッシュして、イメージに基づいてOracle Functionsで新しいファンクションを作成します。これは、様々な方法で実行できます:

    • Fn Project CLIコマンドfn deployを使用して、新しいDockerイメージを作成し、Dockerレジストリにイメージをプッシュし、イメージに基づいてOracle Functionsに新しいファンクションを作成できます。ファンクションの作成およびデプロイを参照してください。
    • Dockerコマンドを使用してイメージを作成し、Dockerレジストリにプッシュしてから、Fn Project CLIコマンドfn create function(またはCreateFunction API操作)を使用して、イメージに基づいてOracle Functionsに新しいファンクションを作成できます。既存のDockerイメージからのファンクションの作成を参照してください。
  3. Oracle Functionsに作成するファンクションのOCIDをノートにとります。たとえば、ocid1.fnfunc.oc1.phx.aaaaaaaaac2______kg6fqです
  4. まだ存在しない場合は、Oracle Cloud Infrastructureポリシーを作成し、APIゲートウェイにファンクション関連リソースへのアクセス権を付与するポリシー・ステートメントを指定します。ポリシーによって、これらのAPIゲートウェイのAPIデプロイメントで認可プロバイダ・ファンクションを起動できます。詳細は、APIゲートウェイにファンクションへのアクセス権を付与するポリシーの作成を参照してください

コンソールを使用した認証および認可リクエスト・ポリシーの追加

コンソールを使用してAPIデプロイメント仕様に認証および認可リクエスト・ポリシーを追加するには:

  1. コンソールを使用してAPIデプロイメントを作成または更新し、「最初から」オプションを選択して、「基本情報」ページで詳細を入力します。

    詳細は、APIデプロイメントの作成によるAPIゲートウェイへのAPIのデプロイおよびAPIゲートウェイおよびAPIデプロイメントの更新を参照してください。

  2. 「基本情報」ページの「APIリクエスト・ポリシー」セクションで、「認証」の横の「追加」ボタンをクリックし、次を指定します:

    • 認証タイプ: 「カスタム」を選択します。
    • <compartment-name>のアプリケーション: 認可プロバイダ・ファンクションを含むOracle Functionsのアプリケーションの名前。別のコンパートメントからアプリケーションを選択できます。
    • ファンクション名: Oracle Functionsの認可プロバイダ・ファンクションの名前。
    • 認証トークン: アクセス・トークンがリクエスト・ヘッダーに含まれるか問合せパラメータに含まれるか。
    • 認証トークンの値: アクセス・トークンがリクエスト・ヘッダーに含まれるか問合せパラメータに含まれるかに応じて、次を指定します:

      • ヘッダー名: アクセス・トークンがリクエスト・ヘッダーに含まれている場合は、ヘッダーの名前を入力します。
      • パラメータ名: アクセス・トークンが問合せパラメータに含まれる場合は、問合せパラメータの名前を入力します。
    • 匿名アクセスの有効化: 未認証(つまり、匿名)のエンド・ユーザーがAPIデプロイメント内のルートにアクセスできるかどうか。デフォルトでは、このオプションは選択されていません。匿名のユーザーがルートにアクセスできないようにする場合は、このオプションを選択しないでください。このオプションを選択した場合は、各ルートの認可ポリシーで「匿名」「認可タイプ」として選択することで、匿名アクセスを許可する各ルートを明示的に指定する必要もあります。
  3. 「変更の保存」をクリックし、「次」をクリックして、「ルート」ページのAPIデプロイメント内の個々のルートの詳細を入力します。個々のルートに適用する認可ポリシーを指定するには、「リクエスト・ポリシーのルーティングを表示」をクリックし、「認可」の横にある「追加」ボタンをクリックして、次を指定します:

    • 認可タイプ: ルートへのアクセス権を付与する方法。次を指定します:

      • 任意: 認可プロバイダ・ファンクションで「許可されるスコープ」フィールドに指定したアクセス・スコープのいずれかも戻された場合にのみ、正常に認証されたエンド・ユーザーにアクセス権を付与します。この場合、認証ポリシーの「匿名アクセスの有効化」オプションは無効です。
      • 匿名: 認可プロバイダ・ファンクションによって正常に認証されていない場合でも、すべてのエンド・ユーザーにアクセス権を付与します。この場合、認証ポリシーの「匿名アクセスの有効化」オプションを選択しておく必要があります。
      • 認証のみ: 認可プロバイダ・ファンクションによって正常に認証されたエンド・ユーザーにのみアクセス権を付与します。この場合、認証ポリシーの「匿名アクセスの有効化」オプションは無効です。
    • 許可されるスコープ: 認可タイプとして「任意」を選択した場合は、認可プロバイダ・ファンクションから返されたアクセス・スコープに対応する1つ以上の文字列のカンマ区切りリストを入力します。アクセス権は、指定したアクセス・スコープのいずれかが認可プロバイダ・ファンクションによって返された場合に、正常に認証されたエンド・ユーザーにのみ付与されます。たとえば、read:helloです
    ノート

    特定のルートの認可ポリシーを含めない場合、そのようなポリシーが存在するかのようにアクセスが付与され、「認可タイプ」「認証のみ」に設定されます。つまり、認証ポリシーの「匿名アクセスの有効化」オプションの設定に関係なく、次のようになります:

    • ルートにアクセスできるのは、認証されたエンド・ユーザーのみです
    • 認証されたすべてのエンド・ユーザーは、認可プロバイダ・ファンクションから返されたアクセス・スコープに関係なく、ルートにアクセスできます
    • 匿名のエンド・ユーザーはルートにアクセスできません
  4. 「変更の保存」をクリックし、「次」をクリックしてAPIデプロイメントに入力した詳細を確認します。
  5. APIデプロイメントを作成または更新するには、「作成」または「変更の保存」をクリックします。
  6. (オプション) コールしてAPIが正常にデプロイされていることを確認します(APIゲートウェイにデプロイされたAPIのコールを参照)。

JSONファイルの編集による認証および認可リクエスト・ポリシーの追加

JSONファイルのAPIデプロイメント仕様に認証および認可リクエスト・ポリシーを追加するには:

  1. 任意のJSONエディタを使用して、認証および認可機能を追加する既存のAPIデプロイメント仕様を編集するか、新しいAPIデプロイメント仕様を作成します(APIデプロイメント仕様の作成を参照)。

    APIデプロイメント仕様には、少なくとも次の内容を含むroutesセクションが含まれます:

    • パス。たとえば、/helloです
    • 1つ以上のメソッド。たとえば、GETです
    • バック・エンドの定義。たとえば、URLまたはOracle Functions内のファンクションのOCIDです。

    たとえば、次の基本的なAPIデプロイメント仕様では、単純なOracle FunctionsのHello Worldサーバーレス・ファンクションを単一のバック・エンドとして定義しています:

    {
      "routes": [
        {
          "path": "/hello",
          "methods": ["GET"],
          "backend": {
            "type": "ORACLE_FUNCTIONS_BACKEND",
            "functionId": "ocid1.fnfunc.oc1.phx.aaaaaaaaab______xmq"
          }
        }
      ]
    }
  2. APIデプロイメント仕様のすべてのルートに適用するauthenticationリクエスト・ポリシーを追加します:

    1. routesセクションの前にrequestPoliciesセクションを挿入します(まだ存在しない場合)。例:

      
      {
        "requestPolicies": {},
        "routes": [
          {
            "path": "/hello",
            "methods": ["GET"],
            "backend": {
               "type": "ORACLE_FUNCTIONS_BACKEND",
               "functionId": "ocid1.fnfunc.oc1.phx.aaaaaaaaab______xmq"
            }
          }
        ]
      }
    2. 次のauthenticationポリシーを新しいrequestPoliciesセクションに追加します。

      {
        "requestPolicies": {
          "authentication": {
            "type": "<type-value>",
            "isAnonymousAccessAllowed": <true|false>,
            "functionId": "<function-ocid>",
            <"tokenHeader"|"tokenQueryParam">: <"<token-header-name>"|"<token-query-param-name>">
          }
        },
        "routes": [
          {
            "path": "/hello",
            "methods": ["GET"],
            "backend": {
              "type": "ORACLE_FUNCTIONS_BACKEND",
              "functionId": "ocid1.fnfunc.oc1.phx.aaaaaaaaab______xmq"
            }
          }
        ]
      }

      ここでは:

      • <type-value>は認証タイプです。認証に認可プロバイダ・ファンクションを使用するには、CUSTOM_AUTHENTICATIONを指定します。
      • "isAnonymousAccessAllowed": <true|false>は、オプションで、未証(つまり、匿名)のエンド・ユーザーがAPIデプロイメント仕様のルートにアクセスできるかどうかを示します。匿名のエンド・ユーザーがルートにアクセスできないようにする場合は、このプロパティをfalseに設定します。このプロパティをauthenticationポリシーに含めない場合、デフォルトのfalseが使用されます。このプロパティを使用してtrueに設定する場合は、各ルートのauthorizationポリシーでtypeプロパティを"ANONYMOUS"に設定することで、匿名アクセスが許可されているすべてのルートを明示的に指定する必要もあります。
      • <function-ocid>は、Oracle Functionsにデプロイされた認可プロバイダ・ファンクションのOCIDです。
      • <"tokenHeader"|"tokenQueryParam">: <"<token-header-name>"|"<token-query-param-name>">は、アクセス・トークンを含むリクエスト・ヘッダーであるか(そうであれば、ヘッダーの名前)またはアクセス・トークンを含む問合せパラメータであるか(そうであれば、問合せパラメータの名前)を示します。"tokenHeader": "<token-header-name>"または"tokenQueryParam": "<token-query-param-name>">のいずれかを指定できますが、両方を指定することはできません。

      たとえば、次のauthenticationポリシーでは、認可リクエスト・ヘッダーのアクセス・トークンを検証するOCIファンクションを指定します:

      {
        "requestPolicies": {
          "authentication": {
            "type": "CUSTOM_AUTHENTICATION",
            "isAnonymousAccessAllowed": false,
            "functionId": "ocid1.fnfunc.oc1.phx.aaaaaaaaac2______kg6fq",
            "tokenHeader": "Authorization"
          }
        },
        "routes": [
          {
            "path": "/hello",
            "methods": ["GET"],
            "backend": {
              "type": "ORACLE_FUNCTIONS_BACKEND",
              "functionId": "ocid1.fnfunc.oc1.phx.aaaaaaaaab______xmq"
            }
          }
        ]
      }
  3. APIデプロイメント仕様の各ルートに、authorizationリクエスト・ポリシーを追加します:

    1. 最初のルートのbackendセクションの後にrequestPoliciesセクションを挿入します(まだ存在しない場合)。例:

      
      {
        "requestPolicies": {
          "authentication": {
            "type": "CUSTOM_AUTHENTICATION",
            "isAnonymousAccessAllowed": false,
            "functionId": "ocid1.fnfunc.oc1.phx.aaaaaaaaac2______kg6fq",
            "tokenHeader": "Authorization"
          }
        },
        "routes": [
          {
            "path": "/hello",
            "methods": ["GET"],
            "backend": {
               "type": "ORACLE_FUNCTIONS_BACKEND",
               "functionId": "ocid1.fnfunc.oc1.phx.aaaaaaaaab______xmq"
            },
            "requestPolicies": {}
          }
        ]
      }
    2. 次のauthorizationポリシーをrequestPoliciesセクションに追加します:

      {
        "requestPolicies": {
          "authentication": {
            "type": "CUSTOM_AUTHENTICATION",
            "isAnonymousAccessAllowed": false,
            "functionId": "ocid1.fnfunc.oc1.phx.aaaaaaaaac2______kg6fq",
            "tokenHeader": "Authorization"
          }
        },
        "routes": [
          {
            "path": "/hello",
            "methods": ["GET"],
            "backend": {
              "type": "ORACLE_FUNCTIONS_BACKEND",
              "functionId": "ocid1.fnfunc.oc1.phx.aaaaaaaaab______xmq"
            },
            "requestPolicies": {
              "authorization": {
                "type": <"AUTHENTICATION_ONLY"|"ANY_OF"|"ANONYMOUS">, 
                "allowedScope": [ "<scope>" ]
              }
            }
          }
        ]
      }

      ここでは:

      • "type": <"AUTHENTICATION_ONLY"|"ANY_OF"|"ANONYMOUS">は、ルートへのアクセス権を付与する方法を示します:

        • "AUTHENTICATION_ONLY": 正常に認証されたエンド・ユーザーにのみアクセス権を付与します。この場合、APIデプロイメント仕様のauthenticationポリシーの"isAnonymousAccessAllowed"プロパティは無効です。
        • "ANY_OF": 認可プロバイダ・ファンクションによって、allowedScopeプロパティで指定したアクセス・スコープのいずれかも戻された場合に、正常に認証されたエンド・ユーザーにのみアクセス権を付与します。この場合、APIデプロイメント仕様のauthenticationポリシーの"isAnonymousAccessAllowed"プロパティは無効です。
        • "ANONYMOUS": 正常に認証されていない場合でも、すべてのエンド・ユーザーにアクセス権を付与します。この場合、APIデプロイメント仕様のauthenticationポリシーで"isAnonymousAccessAllowed"プロパティを明示的にtrueに設定する必要があります。
      • "allowedScope": [ "<scope>" ]は、認可プロバイダ・ファンクションによって戻されるアクセス・スコープに対応する1つ以上の文字列のカンマ区切りリストです。この場合、typeプロパティを"ANY_OF"に設定する必要があります(typeプロパティが"AUTHENTICATION_ONLY"または"ANONYMOUS"に設定されている場合、"allowedScope"プロパティは無視されます)。また、複数のスコープを指定した場合、指定したスコープのいずれかが認可プロバイダ・ファンクションによって戻されると、ルートへのアクセス権が付与されることにも注意してください。

      たとえば、次のリクエスト・ポリシーは、read:helloスコープを持つ認証されたエンド・ユーザーのみにアクセスを許可する/helloルートを定義します:

      {
        "requestPolicies": {
          "authentication": {
            "type": "CUSTOM_AUTHENTICATION",
            "isAnonymousAccessAllowed": false,
            "functionId": "ocid1.fnfunc.oc1.phx.aaaaaaaaac2______kg6fq",
            "tokenHeader": "Authorization"
          }
        },
        "routes": [
          {
            "path": "/hello",
            "methods": ["GET"],
            "backend": {
              "type": "ORACLE_FUNCTIONS_BACKEND",
              "functionId": "ocid1.fnfunc.oc1.phx.aaaaaaaaab______xmq"
            },
            "requestPolicies": {
              "authorization": {
                "type": "ANY_OF",
                "allowedScope": [ "read:hello" ]
              }
            }
          }
        ]
      }
    3. APIデプロイメント仕様内の残りのすべてのルートに、authorizationリクエスト・ポリシーを追加します。
    ノート

    特定のルートのauthorizationポリシーを含めない場合、そのようなポリシーが存在し、typeプロパティが"AUTHENTICATION_ONLY"に設定されているかのように、アクセス権が付与されます。つまり、APIデプロイメント仕様のauthenticationポリシーでのisAnonymousAccessAllowedプロパティの設定に関係なく、次のようになります:

    • ルートにアクセスできるのは、認証されたエンド・ユーザーのみです
    • 認証されたすべてのエンド・ユーザーは、認可プロバイダ・ファンクションから返されたアクセス・スコープに関係なく、ルートにアクセスできます
    • 匿名のエンド・ユーザーはルートにアクセスできません
  4. APIデプロイメント仕様を含むJSONファイルを保存します。
  5. APIデプロイメント仕様は、次の方法でAPIデプロイメントを作成または更新するときに使用します:

    • 「既存のAPIのアップロード」オプションを選択して、コンソールでJSONファイルを指定します
    • APIゲートウェイREST APIへのリクエストでJSONファイルを指定します

    詳細は、APIデプロイメントの作成によるAPIゲートウェイへのAPIのデプロイおよびAPIゲートウェイおよびAPIデプロイメントの更新を参照してください。

  6. (オプション) コールしてAPIが正常にデプロイされていることを確認します(APIゲートウェイにデプロイされたAPIのコールを参照)。