If you are exposing REST endpoints using Oracle REST Data Services (ORDS), securing them properly is critical — especially for integrations, SaaS platforms, and enterprise APIs.
In this guide, we’ll walk through how to:
Create a REST module in ORDS 25.4
Protect it using ORDS Roles and Privileges
Enable OAuth client_credentials authentication
Generate tokens using curl
Call the secured API endpoint
This example uses safe placeholder values (no real credentials).
If you are running Oracle APEX in production, make sure your environment is professionally secured and managed — see our managed hosting options here:
Architecture Overview
We will create:
Module:
myapiEndpoint:
POST https://api.example.com/ords/myapi/helloORDS Role:
MYAPI_ROLEORDS Privilege:
MYAPI_PRIVOAuth client:
myapi_clientGrant type:
client_credentials
Step 1 – Enable the Schema for ORDS
begin
ords.enable_schema(
p_enabled => true,
p_schema => 'MYAPI',
p_url_mapping_type => 'BASE_PATH',
p_url_mapping_pattern => 'myapi',
p_auto_rest_auth => false
);
commit;
end;
/
Step 2 – Create the ORDS Module
begin
ords.define_module(
p_module_name => 'myapi',
p_base_path => '/myapi/',
p_items_per_page => 25,
p_status => 'PUBLISHED'
);
commit;
end;
/
Step 3 – Create Template and POST Handler
begin
ords.define_template(
p_module_name => 'myapi',
p_pattern => 'hello'
);
ords.define_handler(
p_module_name => 'myapi',
p_pattern => 'hello',
p_method => 'POST',
p_source_type => ords.source_type_plsql,
p_source => q'[
begin
owa_util.mime_header('application/json', false);
owa_util.http_header_close;
htp.p('{"message":"Secure Hello World"}');
end;
]'
);
commit;
end;
/
At this point, the endpoint works but it is not protected.
Step 4 – Protect the API with Role and Privilege
Create a role:
begin
ords.create_role(p_role_name => 'MYAPI_ROLE');
commit;
end;
/
Create privilege:
begin
ords.create_privilege(
p_name => 'MYAPI_PRIV',
p_role_name => 'MYAPI_ROLE',
p_label => 'My API Access'
);
commit;
end;
/
Map privilege to URL:
begin
ords.create_privilege_mapping(
p_privilege_name => 'MYAPI_PRIV',
p_pattern => '/myapi/*'
);
commit;
end;
/
Attach privilege to module:
begin
ords.set_module_privilege(
p_module_name => 'myapi',
p_privilege_name => 'MYAPI_PRIV'
);
commit;
end;
/
Now, calling the endpoint without authentication returns: HTTP/1.1 401 Unauthorized
Step 5 – Enable OAuth Client Credentials
Your DBA must grant:
grant execute on ords_metadata.oauth_admin to MYAPI;
grant execute on ords_metadata.oauth to MYAPI;
Then create OAuth client:
begin
ords_metadata.oauth_admin.create_client(
p_schema => 'MYAPI',
p_name => 'myapi_client',
p_grant_type => 'client_credentials',
p_owner => 'MYAPI',
p_description => 'Client credentials for My API',
p_origins_allowed => null,
p_redirect_uri => null,
p_support_email => 'support@example.com',
p_support_uri => 'https://example.com',
p_privilege_names => 'MYAPI_PRIV'
);
commit;
end;
/
Grant role to the OAuth client:
begin
ords_metadata.oauth_admin.grant_client_role(
p_schema => 'MYAPI',
p_client_name => 'myapi_client',
p_role_name => 'MYAPI_ROLE'
);
commit;
end;
/
Retrieve client_id and client_secret:
select name, client_id, client_secret
from ords_metadata.user_ords_clients
where upper(name) = 'MYAPI_CLIENT';
Step 6 – Get OAuth Token Using curl
curl -s -u ':' \
-d 'grant_type=client_credentials' \
"https://api.example.com/ords/myapi/oauth/token"
Example response:
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "bearer",
"expires_in": 3600
}
Step 7 – Call the Secured Endpoint
TOKEN=""
curl -i -X POST \
-H "Authorization: Bearer $TOKEN" \
"https://api.example.com/ords/myapi/hello"
Expected response:
HTTP/1.1 200
Content-Type: application/json
{"message":"Secure Hello World"}
Why Use OAuth Client Credentials for ORDS APIs?
- No database password exposure
- Token expiration control
- Clean integration model for SaaS
- Easy secret rotation
- Industry-standard OAuth 2.0
Best Practices for Production ORDS Security
- Always use HTTPS
- Protect modules with privilege mapping
- Rotate client secrets regularly
- Avoid exposing raw database schemas
- Use a managed ORDS + APEX hosting provider
If you’re running Oracle APEX or ORDS in production and want enterprise-grade security, monitoring, patching, and cloud hardening: