Authentication with OAuth 2

You can use an OAuth 2 access token to issue REST APIs on Oracle Fusion Cloud EPM to satisfy the requirement of avoiding the use of passwords in your environment.

Setting Up Authentication with OAuth 2

In order to access Cloud EPM REST APIs with OAuth 2, a Cloud EPM Service Administrator has to request the Domain Administrator to set up an OAuth 2 client and provide the Identity Domain Cloud Service (IDCS) URL and Client ID.

Overview of the steps:

  • Step 1. Register an OAuth client. This is a one-time setup step that requires user interaction with IDCS Administrator privileges.

  • Step 2. Obtain and securely store the first refresh token. This step requires user interaction. It is a one-time step for each user that needs to invoke REST APIs with OAuth 2.

  • Step 3. Obtain an access token from the refresh token. This step is easily automated. Once automation has been implemented, it can run without user interaction.

About Copying Code Samples

Do not copy code samples from the PDF version of this document. To avoid line breaks and footer information that will render code unusable, Oracle recommends that you copy code samples from the HTML version of the examples in this guide.

The following sections provide detailed information about each step.

Step 1: Register an OAuth Client

Registering an OAuth client is a one-time process. The first step is to update the service provider configuration to authorize requests from the REST client application. As a security measure, any client application that accesses Oracle Cloud resources must be authorized to do so. An IDCS Administrator enables this authorization by registering a client and providing the appropriate registration information to the client's users.

A client application in IDCS is used to obtain an access token. A valid access token (also called a Bearer token) is sufficient authorization to invoke a REST API.

Oracle Fusion Cloud Enterprise Performance Management uses a role-based access control mechanism to permit only authorized users access to the service. For details, see About User and Role Management. This requires that any OAuth 2 access token used to access Cloud EPM REST APIs contains a user context.

A grant type is a standard method to obtain an access token. There are a few different Grant Types as listed here that could be used to obtain an access token. An access token obtained by any of the supported grant types is acceptable as long as the access token is in the context of the user that would be invoking the REST APIs.

In this document, we describe the use of the Device Code Grant Type. EPM Automate has built-in support for the Device Code Grant type.

While the Device Code Grant Type would work in a majority of environments, it might not be right for every implementation. Any of the Grant Types that allow creating an access token with a user context would be suitable for Cloud EPM REST APIs. In addition to the Device Code Grant Type, the following Grant Types support access tokens in the context of an end user:

The next section highlights the steps to create a sample OAuth 2 client using the Device Code Grant Type to request an access token. It also demonstrates how to use the access token to invoke the Get Daily Maintenance Window REST API.

Refer to the Oracle Identity Cloud Service documentation for more details on the Supported Access Grant Types.

The Identity Cloud Service Administrator follows the steps in this topic to create a public client using the Identity Cloud Service Administrator console. The IDCS Administrator then shares the Identity Cloud Service tenant URLand client ID with the Cloud EPM Service Administrator.

Follow the instructions in Detailed Information for Using Oracle Cloud Console to Register an OAuth 2 Client.

Detailed Information for Using Oracle Cloud Console to Register an OAuth 2 Client

  1. Log in to your account at https://cloud.oracle.com/

  2. Click the hamburger menu on the top left and choose Identity and Security and then click Domains on the dialog box.

  3. From the Domains table, choose the appropriate domain (OracleIdentityCloudService by default). This brings you to the Domain Overview page.

  4. Note the Domain URL in the Domain Information section of the page. This is the tenant-base-URL that will be required to request a token.

  5. To create an OAuth 2 client, click Applications in the Identity Domain.

  6. Click the Add application button,

  7. Choose Mobile Application on the pop-up menu and then click the Launch Workflow button.

  8. Enter a name and a description to document the use of this OAuth 2 client.

  9. Click the Next button on the bottom left.

  10. On the Client configuration step, in the Authorization section, select Refresh token and Device code and unselect Implicit.

  11. In the Token Issuance policy section:

    1. Enable Add app roles.

    2. Click the Add roles button.

    3. Choose Identity Domain Administrator on the slide-in dialog box.

    4. Click the Add button to close the slide-in dialog box.

  12. Click Finish to complete the configuration and Activate to activate the application.

  13. Note the Client ID value in the General Information section of the OAuth Configuration.

The IDCS Administrator provides the IDCS URL and client ID to the Cloud EPM Service Administrator.

Step 2. Obtain and securely store the first refresh token

After the Domain Administrator has registered the REST client and provided the IDCS URL and client ID, a Cloud EPM user executes the following steps to get a valid refresh token.

  1. Issue the following unauthenticated request to the Identity Cloud Service URL:

    Linux

    curl --location --request POST 'https://tenant-base-url/oauth2/v1/device' \
    --header 'Content-Type: application/x-www-form-urlencoded;charset=utf-8' \
    --data-urlencode 'response_type=device_code' \
    --data-urlencode 'scope=urn:opc:idm:__myscopes__  offline_access' \
    --data-urlencode 'client_id=<CLIENT ID OF OAUTH2 APPLICATION>'

    Windows Powershell

    curl --location --request POST 'https://tenant-base-url/oauth2/v1/device' `
    --header 'Content-Type: application/x-www-form-urlencoded;charset=utf-8' `
    --data-urlencode 'response_type=device_code' `
    --data-urlencode 'scope=urn:opc:idm:__myscopes__  offline_access' `
    --data-urlencode 'client_id=<CLIENT ID OF OAUTH2 APPLICATION>'

    Windows Command Prompt

    curl --location --request POST "https://tenant-base-url/oauth2/v1/device" ^
    --header "Content-Type: application/x-www-form-urlencoded;charset=utf-8" ^
    --data-urlencode "response_type=device_code" ^
    --data-urlencode "scope=urn:opc:idm:__myscopes__  offline_access" ^
    --data-urlencode "client_id=<CLIENT ID OF OAUTH2 APPLICATION>"

    Here, the value of tenant-base-url is the IDCS URL provided by the Domain Administrator or the Domain URL from the IAM console. It is of the form idcs-<alphanumericvalue>.identity.oraclecloud.com. Similarly, the value for the CLIENT ID OF THE OAUTH2 APPLICATION is also provided by the Domain Administrator or retrieved from the Application's General Information section in IAM. It is an alphanumeric value.

    A valid response contains a device code, user code, and verification URI:

    {
      "expires_in": 300,
      "device_code": "4d03f7bc-f7a5-4795-819a-5748c4801d35",
      "user_code": "SDFGHJKL",
      "verification_uri": "https://tenant-base-url/ui/v1/device"
    }

    The user_code from the response is needed in the second step below, while device_code from the response is needed in the third step below.

    Note: Steps 2 and 3 are time-sensitive because the user code and device code expire 300 seconds (5 minutes) after creation. If the codes expire before these steps can be completed, redo the first step of this section to issue an unauthenticated request to the IDCS URL to receive a new pair of user and device codes.

  2. Open the verification_uri in a supported web browser.

    At this stage, it is important to know that if a user already has an active browser session, the user will not be prompted for re-authentication. If the token is to be generated in context of the currently signed-in user, then proceed with 2b. However, if the token is to be generated in the context of a different user, please sign-out of the current session and navigate to the verification_uri and continue with 2a.

    1. When prompted for credentials, authenticate the user who will be invoking the REST API. These credentials could be credentials for a SAML 2.0 compliant Identity Provider or a native IDCS credential.
    2. When prompted for a code in the browser session, enter the user_code from the response payload.
    3. When the Successful message is displayed, it is recommended to log out of the browser session and close the browser window.
  3. Within 5 minutes of executing the first step of this section and after executing the second step, issue the following request to the Identity Cloud Service URL:

    Linux

    curl --location --request POST 'https://tenant-base-url/oauth2/v1/token' \
    --header 'Content-Type: application/x-www-form-urlencoded;charset=utf-8' \
    --data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:device_code' \
    --data-urlencode 'device_code=<DEVICE CODE FROM THE PAYLOAD OF RESPONSE IN FIRST STEP>' \
    --data-urlencode 'client_id=<CLIENT ID OF THE OAUTH2 APPLICATION>'

    Windows Powershell

    curl --location --request POST 'https://tenant-base-url/oauth2/v1/token' `
    --header 'Content-Type: application/x-www-form-urlencoded;charset=utf-8' `
    --data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:device_code' `
    --data-urlencode 'device_code=<DEVICE CODE FROM THE PAYLOAD OF RESPONSE IN FIRST STEP>' `
    --data-urlencode 'client_id=<CLIENT ID OF THE OAUTH2 APPLICATION>'

    Windows Command Prompt

    curl --location --request POST "https://tenant-base-url/oauth2/v1/token" ^
    --header "Content-Type: application/x-www-form-urlencoded;charset=utf-8" ^
    --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:device_code" ^
    --data-urlencode "device_code=<DEVICE CODE FROM THE PAYLOAD OF RESPONSE IN FIRST STEP>" ^
    --data-urlencode "client_id=<CLIENT ID OF THE OAUTH2 APPLICATION>"

    Here the value of tenant-base-url is the IDCS URL provided by the Domain Administrator, the device_code value is obtained from the response in Step 1, and client_id is the same client_id used in the first step of this section.

    The response contains the first refresh token:

    {
        "access_token": "eyJ4NXQjUzI.........evRJChXTRfzn6WlCw",
        "token_type": "Bearer",
        "expires_in": 3600,
        "refresh_token": "AQIDBAWF1.....RVkxNCB7djF9NCA="
    }

Secure and Protect the Tokens and Client ID

With OAuth 2, tokens are used instead of user credentials to access resources on Cloud EPM. A refresh token and client ID are used to get a new access token and a new refresh token. Thus, to ensure security of Cloud EPM, it is important to securely encrypt and store the client_id and any tokens. The REST client must securely store the refresh token and client_id.

For EPM Automate, use the encrypt command to create an epw file for OAuth 2.

Step 3: Obtain an Access Token from the Refresh Token

This step is required every time a new access token is required. The REST client uses the latest refresh token and client id to get an access token. It uses the access token as authorization to invoke REST APIs. It also ensures that the latest refresh token and client ID are stored securely.

The REST client uses the Refresh Token Grant type to get a new access token and a new refresh token. As mentioned above, this step can be automated. Once automated, it does not require user interaction.

To obtain a valid access token with this Grant Type, the REST client issues the following request to the IDCS URL:

Linux

curl --location --request POST 'https://tenant-base-url/oauth2/v1/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'client_id=<DECRYPTED CLIENT ID OF OAUTH2 APPLICATION FROM SECURE STORE>' \
--data-urlencode 'refresh_token=<DECRYPTED REFRESH TOKEN FROM SECURE STORE>'

Windows Powershell

curl --location --request POST 'https://tenant-base-url/oauth2/v1/token' `
--header 'Content-Type: application/x-www-form-urlencoded' `
--data-urlencode 'grant_type=refresh_token' `
--data-urlencode 'client_id=<DECRYPTED CLIENT ID OF OAUTH2 APPLICATION FROM SECURE STORE>' `
--data-urlencode 'refresh_token=<DECRYPTED REFRESH TOKEN FROM SECURE STORE>'

Windows Command Prompt

curl --location --request POST "https://tenant-base-url/oauth2/v1/token" ^
--header "Content-Type: application/x-www-form-urlencoded" ^
--data-urlencode "grant_type=refresh_token" ^
--data-urlencode "client_id=<DECRYPTED CLIENT ID OF OAUTH2 APPLICATION FROM SECURE STORE>" ^
--data-urlencode "refresh_token=<DECRYPTED REFRESH TOKEN FROM SECURE STORE>"

Here, the value of tenant-base-url is the IDCS URL provided by the Domain Administrator, and the refresh_token and client_id are obtained from the secure store where there were previously stored.

Note: While the client_id and refresh_token are stored securely, it is important that both refresh_token and client_id are decrypted to use in any request. All requests to Oracle IDCS and Cloud EPM are securely transmitted using the https protocol.

Example response:

{
"access_token": "eyJj5M4QjUkI.........abSjZaa86PlseS4lrt7R2",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "AAyyilYBAWD4....FVkxefd8kjoJr6HJPA="
}

The REST client saves the new refresh token for future use (see Secure and Protect the Token and Client ID) and uses the access token as authorization while invoking the REST API (see Use the Access Token).

Use the Access Token

In order to invoke a Cloud EPM REST API, the REST client must provide the access token (obtained in the previous step) in the authorization header as follows:

Authorization: Bearer <access token>

For example, to get the Automated Maintenance Window start time, the client application submits a GET request to this Cloud EPM endpoint /interop/rest/v1/services/dailymaintenance using the access token in the authorization header.

Linux

curl --location --request GET 'https://epm-host/interop/rest/v1/services/dailymaintenance' \
--header 'Authorization: Bearer eyJ5M4QjUkI...abSjZaa86PlseS4lrt7R2'

Windows Powershell

curl --location --request GET 'https://epm-host/interop/rest/v1/services/dailymaintenance' `
--header 'Authorization: Bearer eyJ5M4QjUkI...abSjZaa86PlseS4lrt7R2'

Windows Command Prompt

curl --location --request GET "https://epm-host/interop/rest/v1/services/dailymaintenance" ^
--header "Authorization: Bearer eyJ5M4QjUkI...abSjZaa86PlseS4lrt7R2"

Frequently Asked Questions

OAuth 2 was set up following the documentation before Cloud EPM Release 23.07. Is that configuration still valid?

Yes, the existing configuration will continue to work with existing OAuth 2 support for REST APIs and EPM Automate. However, it is highly recommended to use the updated procedure as it provides greater clarity and might be required for future updates.

How do I change my existing configuration created before Cloud EPM Release 23.07 to be consistent with the current procedure?

The following steps will bring your existing configuration in line with the documented configuration:

  1. For the Oracle Cloud Services, on the Configuration tab under Resources, unselect the Is Refresh Token Allowed checkbox.

  2. For the OAuth 2 client application, under Token Issuance Policy, remove the Resource or Resources selected and add the Identity Administrator Role to the Client as described in Step 11 for Oracle Cloud console.

  3. Follow the steps described in Step 2. Obtain and securely store the first refresh token to request a new refresh token using the scope urn:opc:idm:__myscopes__ offline_access. After getting the refresh token, save it securely.

    For EPM Automate, create a new epw file using the updated instructions in EPM Automate Commands, and then save the new refresh token and client id and use it to authorize access.

How can the expiry time of an access token be modified?

The default expiry time for an access token is 3600 seconds (1 hour).

To request a different expiry time for the access token, you can add urn:opc:resource:expiry=<seconds> to the value of the scope parameter while requesting the refresh token.

For example, the following cURL command requests an access token with the default expiry time of 3600 seconds (1 hour). Note the value of the scope parameter, urn:opc:idm:__myscopes__ offline_access.

curl --location --request POST 'https://tenant-base-url/oauth2/v1/device' 
   --header 'Content-Type: application/x-www-form-urlencoded;charset=utf-8' 
   --data-urlencode 'response_type=device_code' 
   --data-urlencode 'scope=urn:opc:idm:__myscopes__  offline_access' 
   --data-urlencode 'client_id='<DECRYPTED CLIENT ID OF OAUTH2 APPLICATION FROM SECURE STORE>'

To request an access token with an expiry time of 2 hours (that is, 2 hours x 60 mins/hour x 60 seconds/min = 7200 seconds), use the following value for the scope parameter:

urn:opc:idm:__myscopes__ urn:opc:resource:expiry=7200 offline_access

For additional details, see Token Expiry.

The table has 3 columns: Setting Name, Default Value, and Description. Under the Setting Name column, look for the row for OAuth Access Token Expiry. In that row, look under the Description column for the item Custom Expiry Time, sub-item 4.

Can the expiry time of a refresh token be modified?

Note that the default expiry period of a refresh token is 604800 seconds, which is 7 days. The refresh token expiry time is not modifiable with the urn:opc:idm:__scopes__ offline_access scope.

What error is returned when the refresh token has expired?

Executing a refresh token grant flow with an expired refresh token results in a 400 Bad Request response and the following payload:

{  "error": "invalid_grant",
    "error_description": "Token is expired for client : <CLIENT_ID>",
    "ecid": "UsbMB0KCV00000000"
}

What error is returned when the refresh token is invalid?

Executing a refresh token grant flow with an invalid refresh token results in a 400 Bad Request response and the following payload:

{  "error": "invalid_grant",
    "error_description": "The given token in the request is invalid",
    "ecid": "UsbMB0KCV00000000"
}

What errors are returned for other issues?

A 400 Bad Request response with the following payloads are returned when there is an error:

Invalid request (for example, not all request parameters are supplied):

{
    "error": "invalid_request",
    "error_description": "The request contains invalid parameters or values"
}

Invalid grant (for example, using a token that has already been used) :

{
    "error": "invalid_grant",
    "error_description": "The token has already been consumed"
}

Invalid scope (for example, providing invalid scope):

{
    "error": "invalid_scope",
    "error_description": "Invalid scope"
}

What error is returned when an invalid or expired access token is provided?

When an invalid or expired access token is provided in a request, the server responds with a 401 Unauthorized response with the following HTML in the payload:

<html>
<head><title>401 Authorization Required</title></head>
<body>
<center><h1>401 Authorization Required</h1></center>
<hr>
</body>
</html>

Can a token be requested with multiple scopes?

Multiple scopes across different resources (Cloud EPM environments) are not supported by Identity Cloud Service. Each token request can support only one resource. Requests for multiple scopes within the same resource are supported with space delimited scopes. Requesting multiple scopes across different resources results in a 400 Bad Request response with the following payload:

{
"error": "invalid_scope",
"error_description": "Invalid scope"
}

Can a valid token received for one Cloud EPM environment be used to access all Cloud EPM environments in the same IDCS domain?

The Cloud EPM Service Administrator for an environment provisions each user with predefined and application roles and specific access for that environment. The same user may be provisioned with different privileges on different environments in the same IDCS domain. The functionality that a user is able to perform on any Cloud EPM environment is dependent on the roles and access the user has on that environment. Thus, a valid, unexpired bearer token received for one Cloud EPM environment can be used across all Cloud EPM environments in the same IDCS domain for authentication purposes. However, the authorization of what a particular user can do on a particular Cloud EPM environment is dependent on the roles the user has on that environment.

What information is logged in the access log with OAuth?

The access log shows the user name, just as it does with basic authorization. The client ID and access token are not logged.

When using multiple scripts to run EPM REST APIs, the refresh token grant type seems to fail randomly with a message that the token is already consumed. What is the resolution?

Each refresh token is a single use token. After first use, the same token cannot be reused. Trying to use a particular token after it has already been used results in the message, The token is already consumed.

The right way is to set up each script with its own refresh token. To do that, execute the procedure to obtain and save the first refresh token once for each script requiring a refresh token, and then set up each script to use its own refresh token. All scripts can still use the same clientID.