Note:

Integrate OCI Streaming with Other Authorization Methods Using OCI API Gateway

Introduction

We often need our applications to consume Oracle Cloud Infrastructure (OCI) REST services. There are several ways to guarantee security between components, ensuring that the application can authenticate securely to the backend service.

Most of the time, this task is native within Oracle Cloud, as there are several ways to secure the network and access to existing services. Just a few settings and you are done. However, there are cases where the application may offer additional security and connectivity requirements. The use case of this tutorial meets a very common need in the hybrid or multicloud scenario (on-premises connected to Oracle Cloud, or Oracle Cloud connected to another cloud).

Let’s present the following scenario:

Therefore, the tutorial provides the following solution:

Note: The OCI Functions code can be downloaded here: OAuthOCIService-fn.zip.

Objectives

Prerequisites

Task 1: Configure OAuth2 with Oracle Identity Cloud Service

  1. Obtain the OCI API Gateway Parameters: Let’s start to configure the OAuth2 mechanism. We need to integrate your OCI API Gateway instance into an identity provider by configuring the Oracle Identity Cloud Service from Oracle Cloud to be the identity provider.

    • Go to the OCI API Gateway instance and copy Hostname. This information will be used in your Oracle Identity Cloud Service resource server configuration in the next step.

      img.png

  2. Create a Resource Application: We need to create an OAuth2 authorizer for your application. We can do it with the Oracle Identity Cloud Service in Oracle Cloud.

    1. In the OCI Console, go to Identity & Security and select Federation.

      img.png

    2. Click OracleIdentityCloudSevice.

      img.png

    3. Click the Oracle Identity Cloud Service Console link for your Oracle Identity Cloud Service instance.

      img.png

    4. We will create two applications. Click Applications and Services.

      img.png

    5. In the Applications, click Add.

      img.png

    6. Select Confidential Application to start configuring your resource server.

      img.png

    7. We will configure the first application. Enter a Name in your resource server application and click Next.

      img.png

    8. Click Skip for later. We need to configure the resource only.

      img.png

    9. Enter your API Gateway hostname obtained in Step 1.

      img.png

    10. Click Add Scope and enter the scope information.

      img.png

    11. Review your scope information, click Next two times and click Finish.

      img.png

    12. Click Activate to activate your application.

      img.png

  3. Create a Client Application.

    1. In Applications, click Add.

      img.png

    2. Select Confidential Application to start configuring your resource server.

      img.png

    3. Enter a Name for your application and click Next.

      img_1.png

    4. Select Configure the application as a client now to enable the configurations for your client application. Select Client Credentials, JWT Assertion and On behalf of.

      img.png

      Note: If you want to validate OAuth2 in your function code, you MUST set the Introspect flag. This will enable the /oauth2/v1/introspect Oracle Identity Cloud Service REST API service.

      img_10.png

    5. Scroll down and click Add Scope.

      img.png

    6. Find your resource application created before (oauth_resource_server) and click Add.

      img.png

    7. You can see your scope added to your application. Click Next.

      img.png

      Note: Note the scope value, you will need to use it to request a token.

    8. Skip the Resources and the Web Tier Policy window. In Authorization, select Enforce Grants as Authorization and click Finish.

      img.png

    9. Note the Client ID and the Client Secret information. You will need this to obtain your token.

      img.png

    10. Click Activate to activate the application and your OAuth2 authorizer is ready to test.

      img_1.png

  4. Get a Token: Now we can test the OAuth2 authorizer to obtain the token.

    1. Compose the URL for the authorizer. You can obtain this by getting your Oracle Identity Cloud Service URL in the browser. In the Oracle Identity Cloud Service URL, you can see something like this: https://idcs-xxxxxxxxxxxxx.identity.oraclecloud.com/ui/v1/adminconsole.

    2. You will need the URL link until the oraclecloud.com, which is the root endpoint. For example, https://idcs-xxxxxxxxxxxxx.identity.oraclecloud.com.

    3. We need to add the oAuth authentication path. This URL will be executed as a POST REST request. For example, https://idcs-xxxxxxxxxxxxx.identity.oraclecloud.com/oauth2/v1/token. You will need to enter some parameters to request the token.

    4. Enter the credentials as Basic Authentication, Client ID and Client Secret.

      img.png

    5. In the Body content, enter the grant_type and scope values. Remember, the scope was captured in the Oracle Identity Cloud Service configuration.

      img.png

    6. Click Send and execute the POST request and view the token.

      img_2.png

Task 2: Configure OCI Functions to call your OCI SDK API

  1. Understand the OCI Functions and OCI API Gateway: It is a best practice to expose your services through an OCI API Gateway. Authentication can be done bypassing the credentials from OCI API Gateway to the backend services, but if the backend authentication was not the appropriate method for your client application, we can do some configuration in the OCI API Gateway level.

    In this step, let’s understand how OCI API Gateway can help us to integrate the OAuth2 authentication and the request for any OCI service, like OCI Streaming through the OCI Functions.

    OCI Functions can do the job to produce the correct authentication/authorization and pass to the OCI service without the necessity of passing user credentials or private keys to the consumer applications. Some services in the OCI service cannot authenticate using OAuth2 method, so we can do it with OCI Functions. To create and deploy OCI Functions, see OCI Functions Quickstart.

    In this example, the OCI Streaming service can authenticate by the OCI private key in OCI IAM through draft-cavage-http-signatures-08 method and consumers can authenticate by OAuth2.

  2. Understand the Code: This code will be used with OCI API Gateway. In your API deployment, we will configure the OCI Streaming endpoint in the OCI API Gateway and it will be passed as a HEADER authorization parameter. So you can use this function for many services in each OCI API Gateway deployment you need.

    img_12.png

    • This function in Python will create a date and time in format for the authentication. This date and time needs to be generated one time and used in two points. To the header Date on the OCI Streaming request and the Signature cryptographed HEADER.

      img_1.png

    • This is the function for signature encryption. The assembly consists of using the OCI IAM user’s private key with SHA-256 and then in base64.

      img_2.png

    • The signature encryption will be used on the complete Authorization HEADER.

      img_3.png

    • This is the Oracle Identity Cloud Service OAUTH2 token validation code. You need to configure the config.json file with your Oracle Identity Cloud Service application parameters.

      img_13.png

    • This is the beginning of the function and initializes some information from OCI IAM security and OCI Streaming variables created for this API deployment (streaming_host and oci_region).

      img_4.png

    • This is the main part of this function, there are two parts.

      In the first part, we obtain the token passed in the API Gateway request. After this, we call the auth_idcs() function to validate the token in Oracle Identity Cloud Service. Before generating the draft-cavage-http-signatures-08 string, we validate the Oracle Identity Cloud Service token. If it is not a valid token, the response will give a 401 unauthorized error.

      In the second part, we will create two values. The date (d) with the date format will be used in the creation of the signature (a). The rdata will construct the response for the function with the authorization and date values that will be used by OCI API Gateway to authenticate on OCI Streaming.

      img_15.png

    • Here we can generate a log in the OCI Observability and this step is optional. Enter the Oracle Cloud Identifier (OCID) for the log. You need to create a Custom Log previously.

      Note: To create a custom log in OCI Observability, see Use OCI API Gateway, Functions and Observability to Validate JSON Content and Monitor API Headers and Body.

      img_6.png

    • This is the final step and returns with a valid authentication.

      img_7.png

    This is the requirements.txt libraries that will need to be loaded in this function (fn).

    requirements.txt
    ---------------------
    fdk>=0.1.54
    requests
    oci
    cryptography
    six
    PyJWT
    py3_lru_cache
    simplejson
    

    This is the config.json file.

    img_14.png

    And this is the OCI config file. You can copy this file from your OCI CLI installation but it is important to modify the key_file section and remove the path of your OCI CLI installation. This will be used in the Python code to generate the draft-cavage-http-signatures-08 cryptographic string.

    img_16.png

    Before deploying the function, create two variables and fill with the OCI Streaming OCID and OCI region values like this.

    fn config app <function-app> streaming_host ocid1.stream.oc1.iad.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxqhgw275qp7a
    fn config app <function-app> oci_region us-ashburn-1
    

    Deploy your function and let’s configure it in the OCI API Gateway.

Task 3: Configure an API Gateway Deployment

Note: Develop a function and call it in OCI API Gateway, see OCI Functions: Validate an API Key with API Gateway.

  1. Configure your OCI API Gateway service. In this example, we will configure an OCI Streaming service. In basic information, enter the Path prefix as /20180418/streams/ plus the OCID of your streaming instance.

    For example: /20180418/streams/ocid1.stream.oc1.iad.xxxxxxxxxxxxxxxxxxxxxxxxxxxx

    img.png

  2. In the Authentication, select Single Authentication and Authorizer Function. Select the compartment and Oracle Function as get-authorization.

    img.png

  3. Configure your request HEADERs parameters.

    Header Parameter 1
    Context table=request.headers
    Header name=Date
    Argument name=Date
    
    Header Parameter 2
    Context table=request.headers
    Header name=token
    Argument name=token
    
  4. To configure the HEADER for Oracle Identity Cloud Service parameters, you need to click Show route request policies.

    img.png

  5. In the HEADER transformations, click Edit and enter Behavior to Overwrite in both parameters, Header name as Authorization, Date and Values as ${request.auth[authorization]} and ${request.auth[date]} respectively. The ${request.auth[authorization]} and ${request.auth[date]} are the values returned by the function Python code and will be passed as the HEADERs for the backend service.

    img.png

Task 4: Configure the OCI Group and Policies

To configure the policies for OCI Streaming, see OCI Streaming Policies and you can use common policies, see Common Policies.

Task 5: Test the API

Let’s simulate your application OAuth2 request for your Model Deployment Service in OCI Streaming.

  1. Obtain the token and pass the Client ID and Client Secret to your Oracle Identity Cloud Service provider.

    Verb: POST
    URL: https://idcs-xxxxxxxxxxxxxxxxxxxxxxx.identity.oraclecloud.com/oauth2/v1/token
    BODY (x-www-form-urlencoded):
    scope: xxxxxxxxxxxxxxxxxxx.apigateway.us-ashburn-1.oci.customer-oci.com/super-scope
    grant_type: client_credentials
    HEADER
    Authorization: clientID:clientSecret\*
    
    - convert your clientID:clientSecret to a base64 value
    

    img_2.png

  2. Test the request to OCI API Gateway. Enter your API Gateway deployment endpoint and select POST to your REST request. You need to declare six HEADERs in the BODY of your request.

    Content-Type: application/json
    access-control-allow-origin: *
    access-control-allow-method: POST,PUT,GET,HEAD,DELETE,OPTIONS
    access-control-allow-credentials: true
    Date: put an actual date in this format -> Thu, 21 Dec 2023 13:53:59 GMT
    token: put your <access_token> here*
    
    * Remember that your token have 1 hour duration.
    

    img_9.png

    And here is the result.

    img_11.png

    In the Logs, you can see the payloads for your custom code authorization logic.

    img_8.png

Acknowledgments

More Learning Resources

Explore other labs on docs.oracle.com/learn or access more free learning content on the Oracle Learning YouTube channel. Additionally, visit education.oracle.com/learning-explorer to become an Oracle Learning Explorer.

For product documentation, visit Oracle Help Center.