Oracle Cloud Infrastructure (OCI) API Gateway allows to protect APIs with Authentication and Authorization. This is enforced through configuration of a deployment and optionally the route(s) on the gateway.  Usually for JWT which are at least proved for correct signature, audience and issuer. Signature test is fastest with static keys, but because of changing signatures a live URL for signature test is possible. If there is no valid JWT provided the call ends in the default configuration with a 401 unauthorized.

API Gateway supports OpenID Connect since end of 2022. This means that if a call is not authorized API Gateway can redirect the caller to the configured OIDC provider. It triggers the OpenID Connect Authorization Code Flow and requests the scopes you need for the further token processing, at least openid. As there are several options and dependencies this blog shows the configuration for IDCS/IAM domains and explains current Azure AD B2C integration. This is a common blog from Alberto Campagna and Michael Fischer.

There are many possible use cases for API Gateway, one for example is if you have material on a private object storage and want to deliver it only to authenticated and optional authorized users. 

To use this OpenID with API Gateway it is required that the OpenID Server (Authorization Server) provides an introspect API. Azure AD and Azure B2C doesn’t support Introspection as of 8/2023. Possiblities to use Azure AD and Azure B2C as authentication and optional authorization with API Gateway therefore are:

  • use an authorizer FN in API Gateway: with this you’re coding the token handling on your own
  • use IDCS/IAM token with federated login through  Azure AD or Azure B2C 

 

The current Blog contains integration with IDCS/IAM domains. Setup of Azure federation can be found in documentation or other blogs.

Setup:

Preconditions

First precondition is an existing API Gateway. For easy testing if API Gateway is accessible a deployment without authentication and a route with stock response can be used.

Second precondition is an OAuth Client defined at your OIDC server. This client is used for introspection of the token and OpenID Connect Authorization Code Flow. For this purpose the client needs the relevant authorizations to 1) do introspection on behalf and 2) Trigger the OIDC code flow. Copy the ClientID and Secret as you need it for further processing. In case you know the route(s) already add them in the redirect URL. You also can add them later. The redirect URL is needed for the code flow and required for every route. In the following sample two different clients have been used, one for introspect and one for code flow.

Introspect Client

 

 

OIDC Client

Third precondition is having an OCI Vault to store the secret of the OAuth Client from precondition 2. To create a secret in OCI Vault an OCI Vault and an OCI Vault key is needed upfront. Create them if they do not exist. Create an OCI Vault secret and copy the value in text format as you get this in both cases, IAM domains and Azure as text. Remember the secret name(s) and compartments of Vault and secret as you need to specify them in the setup.

Ensure that the OCI policies are set to allow the API GW to access the secrets. This requires creation of a dynamic group which specifies the gateway(s) and a policy with the statements to allow this group to read Vaults and Secrets. See documentation for policies:
https://docs.oracle.com/en-us/iaas/Content/APIGateway/Tasks/apigatewaycreatingpolicies.htm#unique_1978797841

Should look like this

Vault with Secrets

Steps

Step 1 Create a new deployment and set Authentication e.g. to Single Authentication; this opens further configuration

Step 2 Configure Authentication, config and values:

  • Authentication type:  OAuth 2.0 / OpenID Connect
  • Token location: Header
  • JWT Name: Authorization
  • Authentication Scheme: Bearer
  • Validation: OAuth 2.0 introspection endpoint
  • Client ID and Secret (via OCI Vault) have to be provided.
  • Discovery URL of OpenID endpoints of  provider

in case of IDCS/IAM Domains:

Discovery URL is not the generic one like
ttps://idcs-9f7xxxx.identity.oraclecloud.com/.well-known/idcs-configuration
but specific to openid (see sample). If the wrong is used you’ll get a 500 internal server error during runtime.
https://idcs-9f7xxxx.identity.oraclecloud.com/.well-known/openid-configuration
Call this URL in browser to see the issuer, if intended to specify for next config.

API GW Config1

Optional settings:

  • issuers: put in the value from discovery URL before or for IDCS “https://identity.oraclecloud.com/”
  • audiences: this will depend on the scopes provided for the flow.
  • as it accepts multiple values these can be added: instance of IAM and second entry client id
  • Claims: can be set to enforce more specific tokens

    API GW Config2

further settings:

 

  • Validation failure policy: choose  OAuth2.0 redirect client to identity provider
  • scopes: at least openid, further supported values can be seen in the introspect URL and be the ClientID
  • response type: code
  • If not using the introspect client specify the ClientID and Secret for the authorization code flow client
    It is best practice to use 2 separate clients due to least privilege

    API GW Config3

 

Step 3. Specify one or more routes, e.g. stock response

Attention: Add the full URL to the code flow client as redirect URL.

Case IDCS / IAM Domains

If you only have one route this works via UI, if more than one route use a rest client & API:
https://docs.oracle.com/en/cloud/paas/iam-domains-rest-api/op-admin-v1-apps-id-patch.html

sample for 3 routes:

curl --location --request PATCH 'https://idcs-9f7xxxx.identity.oraclecloud.com/admin/v1/Apps/af3xxx' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer eyJ4NXQxxxx' \ --data '{  "schemas": [  "urn:ietf:params:scim:api:messages:2.0:PatchOp"  ],  "Operations": [{  "op": "replace",  "path": "redirectUris",  "value": [  "https://c5axxxx.apigateway.eu-frankfurt-1.oci.customer-oci.com/test/test1",  "https://c5axxxx.apigateway.eu-frankfurt-1.oci.customer-oci.com/test/test2",  "https://c5arxxxx.apigateway.eu-frankfurt-1.oci.customer-oci.com/testx/test"  ]  }] }'

 

Step 4. Try to call the route with a fresh browser

This should redirect to IDCS/Azure login and after successful login calling the API.
In case of an error see section Troubleshooting 

 

Troubleshooting:

During Configuration:

  • Authentication Settings in deployment can not be saved
    Assumption is all mandatory values have been set
    The UI is a bit unfair, if you set values in section JWT validation (e.g. issuers, audiences) and remove them afterwards it does not allow to store. Either use API or a new deployment.
  • Secret not accessable
    in UI you get “Unable to retrieve the OpenID Connect secret using the resource principal….” Action: check policies in
    https://docs.oracle.com/en-us/iaas/Content/APIGateway/Tasks/apigatewaycreatingpolicies.htm#unique_1978797841

During Execution:

Ensure Logleve at Deployment (Setting of API logging policies) or route (Section Show Logging Policies) is set to maximum (Information level).
Enable the Access and Execution Logs at the API Gateway in the relevant deployment.

API Logs
Ensure that you have the maximum details in the log, this means level “information” in the route.
Go for the logs. Typical errors are

  • Wrong Secret/Client
    Browser message like {“code”:401,”message”:”Unauthorized”}
    It is the same error for wrong ClientID or Secret
    Access Log shows only the route with the 302
    Execution log shows  “Call to Identity Provider failed with error: invalid_client”
    Action: Check and Correct ClientID and Secret. As the RestAPI of the OIDC provider can be used with a rest Client check if a call works at all. 

     
  • Redirect Error / No successful login
    browser message like {“error”:”invalid_redirect_uri”,”error_description”:”Client 5cxxx requested an invalid redirect URL: https://c5axxxx.apigateway.eu-frankfurt-1.oci.customer-oci.com/test/1. ECID: KhU7xxxx”}
    access log shows only the 302 redirect to login
    execution log shows “Found Validation Failure Policy of type OAUTH2. Initiating OAuth2”
    Action: correct “Redirect URL” in OAuth Client, this should be the full path of API GW route.

     
  • Issuers or Audience specified and wrong:
    browser: ERR_TOO_MANY_REDIRECTS ending with {“code”:401,”message”:”Unauthorized”}
    API GW tries to get the token several times and then stops after some iterations as the token was invalid. In the end the log message is “State value mismatch during OAuth2.” The reason is in some messages before: “”Token not issued by the configured issuers.” Or in case of wrong Audience “Token not issued for the configured audience.”.
    Action: Check and Correct Issure/Audience. If not sure about the values just grab the provided JWT and check issuer/audience.

Errorlisting
 

  • {“code”:502,”message”:”Bad Gateway”}
    This states a misconfiguration in API Gateway so API Gateway is not able to execute the request.  Please check the execution logs of the gateway.

 

Links

OIDC Flows: https://openid.net/specs/openid-connect-basic-1_0.html

REST API to set IDCS/IAM Redirect URLs: https://docs.oracle.com/en/cloud/paas/iam-domains-rest-api/op-admin-v1-apps-id-patch.html