Skip to main content

Command Palette

Search for a command to run...

Generating a bearer token with Curl using Oracle ORDS and the OAuth 2.0 Client Credentials flow

The manual step-by-step process

Updated
•6 min read
Generating a bearer token with Curl using Oracle ORDS and the OAuth 2.0 Client Credentials flow

In this blog I cover the manual steps to resolve a valid bearer token from the OAuth Authentication Server that comes out-of-the-box with Oracle ORDS, a.k.a. Oracle REST Data Services. Nevertheless, the curl steps are almost identical to any OAuth 2.0 Authentication Server, although some value specifics might be a little different.

After the bearer token - or access token - has been generated by ORDS, it can be used in subsequent REST API requests using the same ORDS Authentication server.

šŸ’”
For installation or configuration of Oracle ORDS, take a look at oracle-base.com for a comprehensive guide.

Create an OAuth 2.0 client

For the purpose of this blog you generate an OAuth 2.0 client that uses the Client Credentials flow. Most parameters int the example below are free-text values and you can fill in any value you like, however, parameter p_grant_type and p_privilege_names should be set accordingly as shown below, to guarantee correct results for this demo.

begin
  oauth.create_client(
    p_name            => 'OAuth 2.0 Client Name',
    p_grant_type      => 'client_credentials',
    p_owner           => 'Your company name',
    p_description     => 'An OAuth 2.0 client for demonstration',
    p_support_email   => 'user@email.com',
    p_privilege_names => null
  );
end;
/

commit
/

Run the next query to validate that the OAuth 2.0 client has been created, you can see the client_id - in this example abc - and client_secret - in this example def - in the results. In this blog I use abc and def, but in reality these are generated values by ORDS.

select name, client_id, client_secret
from   user_ords_clients;


NAME                     CLIENT_ID    CLIENT_SECRET
------------------------ ------------ ----------------
OAuth 2.0 Client Name    abc          def

Alright, now that the client has been created, we can continue to execute a request to resolve an access token.

Basic Authorization Header

To execute a request to an OAuth Authentication Server, a basic authorization header is needed.

šŸ’”
While I describe an alternative later in this blog, I recommended this method for sending credentials using OAuth 2.0.

The basic authentication header must contain a base64 encoded string, where the client_id and client_secret must be separated by a colon (:) and encoded using the base64 encoding mechanism.

  • Client ID: abc

  • Client Secret: def

  • Base64 encode: utl_encode.base64_encode()

  • RAW casting: The function utl_encode.base64_encode() uses RAW datatypes as input and output parameters, so we need to cast the source string to and from RAW - before and after encoding.

select utl_raw.cast_to_varchar2(
         utl_encode.base64_encode(
           utl_raw.cast_to_raw( 'abc:def')
         )
       ) as encoded_string
from dual
/


ENCODED_STRING
_________________
YWJjOmRlZg==

Now that we have the base64 encoded string containing the client id and client secret, we must place it in the curl command as shown below.

  • Location: refers to the Oracle ORDS authentication server.

  • Header Content-Type: specifies the mimetype of the data we are submitting.

  • Header Authorization: specifies the Basic authentication type followed by the base64 encoded string.

  • Data: specifies that we want to use the OAuth Client Credentials flow to authenticate.

curl \
 --locationĀ 'https://<ords_server>/ords/<schema_alias>/oauth/token'Ā \
 --headerĀ 'Content-Type:Ā application/x-www-form-urlencoded'Ā \
 --headerĀ 'Authorization:Ā BasicĀ YWJjOmRlZg=='Ā \
 --data-urlencodeĀ 'grant_type=client_credentials'

When the curl command above is executed, it basically asks the token authentication server: ā€œHello Authorization Server, I am client abc, I’m authenticating using my client credentials (using secret def). If valid and authorized, please issue me an access token for use in subsequent API requests.ā€

ā—
Now that you know how the client_id and client_secret end-up in your request, you should notice how vulnerable your credentials are when sending these requests using HTTP, instead of HTTPS. Each and every system involved - or in between - the requestor and the target server can read the request, decode the base64 encoded string and see your plain credentials if not sent using HTTPS!

If everything is correct, a response with the access token will be received by the issuer. It contains the access token itself, the token type and the duration in seconds that the access token is valid.

{
  "access_token" : "bQ4z6urrNEbpk7-85M0nix",
  "token_type"   : "bearer",
  "expires_in"   : 3600
}

Send credentials with --user flag

Although sending credentials by the Authorization Basic header is highly recommended, if base64 encoding is too complex or isn't possible at the environment, an alternative solution can be to send the client:secret credentials with the --user flag.

curl \
--locationĀ 'https://<ords_server>/ords/<schema_alias>/oauth/token'Ā \
--headerĀ 'Content-Type:Ā application/x-www-form-urlencoded'Ā \
--user "abc:def" \
--data-urlencodeĀ 'grant_type=client_credentials'

In that case there is no manual base64 encoding necessary as Curl now automatically handles the base64 encoding for you, while sending the credentials in the Authorization: Basic header as many OAuth providers require.

Send credentials in the body

Another alternative is to send the credentials in the body as can be seen in the example below.

curl \
--location 'https://<ords_server>/ords/<schema_alias>/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_id=abc' \
--data-urlencode 'client_secret=def'

but this fails when Oracle ORDS is used as the authorization server, since ORDS doesn't support sending credentials in the body (yet?).

401 Unauthorized

If your credentials are not correct, the token request itself will result in a 401 Unauthorized response.

{
  "code" : "Unauthorized",
  "message" : "Unauthorized",
  "type" : "tag:oracle.com,2020:error/Unauthorized",
  "instance" : "tag:oracle.com,2020:ecid/Trx2zrNWzWt3S9op4Vu5kg"
}

Benefits

By using curl for the authentication part of the web request, the authentication step is separated from the actual data request and will now reveal errors or configuration mismatches during that specific phase. What happens under-the-hood is now visible, which makes debugging your REST call or OAuth2 authentication request way simpler than without.

More information on failures

To see more information about the cause of a failure, add --verbose or --trace-ascii . to the Curl command and it will show you the detailed information you are looking for to solve your issue.

* Host <ords_server>:443 was resolved.
* IPv6: (none)
* IPv4: 192.168.0.1
* Trying 192.168.0.1:443...
* schannel: disabled automatic use of client certificate
* ALPN: curl offers http/1.1
* ALPN: server accepted http/1.1
* Established connection to <ords_server> (192.168.0.1 port 443) from 192.168.0.2 port 58040
* using HTTP/1.x
> POST /ords/<schema_alias>/oauth/token
> HTTP/1.1
> Host: <ords_server>
> User-Agent: curl/8.18.0
> Accept: /
> Content-Type: application/x-www-form-urlencoded
> Content-Length: 103
* upload completely sent off: 103 bytes
* schannel: server close notification received (close_notify)
< HTTP/1.1 401 
< Date: Mon, 23 Mar 2026 12:00:00 GMT 
< Server: Apache/2.4.37 (Oracle Linux Server) OpenSSL/1.1.1k 
< Content-Type: application/problem+json 
< Content-Length: 182 
< Connection: close 
<
{
  "code": "Unauthorized",
  "message": "Unauthorized",
  "type": "tag:oracle.com,2020:error/Unauthorized",
  "instance": "tag:oracle.com,2020:ecid/U2paxJBT4Moj06mu1-uQNQ"
}
* shutting down connection #0

Documentation

RFC Editor: RFC 6749: The OAuth 2.0 Authorization Framework

Datatracker: RFC 6749 - The OAuth 2.0 Authorization Framework

Oracle UTL_ENCODE

OAuth 2 Simplified • Aaron Parecki