Access Control
Configure domain, IP, and network restrictions for your FortiBlox Nexus API keys
Access Control
FortiBlox Nexus provides multiple layers of access control to protect your API keys from unauthorized usage. Configure domain restrictions for web applications, IP restrictions for server applications, and network restrictions to limit which X1 Blockchain networks can be accessed.
Overview
Access control restrictions are evaluated in the following order:
- API Key Validation - Is the key valid and active?
- Network Restrictions - Is the requested network allowed?
- IP Restrictions - Is the request from an allowed IP?
- Domain Restrictions - Is the request from an allowed domain?
- Rate Limits - Is the request within rate limits?
If any check fails, the request is rejected with a 403 Forbidden response.
Domain Restrictions
Domain restrictions allow you to whitelist specific domains that can use your API key. This is ideal for web applications where you want to prevent unauthorized domains from using your key.
When to Use Domain Restrictions
- ✅ Browser-based web applications
- ✅ Single-page applications (SPAs)
- ✅ Progressive web apps (PWAs)
- ✅ Localhost development (e.g.,
localhost:3000) - ❌ Server-to-server applications (use IP restrictions instead)
- ❌ Mobile applications (API keys should not be in mobile apps)
How It Works
When a browser makes a request to FortiBlox, it automatically includes an Origin or Referer header:
POST /rpc?api-key=fbx_... HTTP/1.1
Host: api.fortiblox.com
Origin: https://myapp.com
Content-Type: application/jsonFortiBlox checks if https://myapp.com is in your allowed domains list. If not, the request is rejected.
Configuring Domain Restrictions
Step 1: Enable Domain Restrictions
- Log in to the Developer Portal
- Navigate to API Keys
- Click on the API key you want to configure
- Scroll to Access Control section
- Toggle Domain Restrictions to ON
Step 2: Add Allowed Domains
https://myapp.comOnly requests from https://myapp.com will be allowed.
Example:
- ✅
https://myapp.com- Allowed - ✅
https://myapp.com/dashboard- Allowed - ❌
https://www.myapp.com- Blocked (subdomain not included) - ❌
http://myapp.com- Blocked (HTTP not HTTPS)
https://myapp.com
https://www.myapp.com
https://staging.myapp.comAdd one domain per line. Requests from any of these domains will be allowed.
Example:
- ✅
https://myapp.com- Allowed - ✅
https://www.myapp.com- Allowed - ✅
https://staging.myapp.com- Allowed - ❌
https://dev.myapp.com- Blocked (not in list)
https://*.myapp.com
https://myapp.comUse * to match any subdomain.
Example:
- ✅
https://www.myapp.com- Allowed - ✅
https://api.myapp.com- Allowed - ✅
https://staging.myapp.com- Allowed - ✅
https://anything.myapp.com- Allowed - ✅
https://myapp.com- Allowed (explicitly listed) - ❌
https://myapp.co- Blocked (different domain)
Note: *.myapp.com does NOT match myapp.com itself. Always add both if you want to allow the root domain.
http://localhost:3000
http://localhost:8080
http://127.0.0.1:3000For local development, add localhost URLs with specific ports.
Example:
- ✅
http://localhost:3000- Allowed - ✅
http://127.0.0.1:3000- Allowed - ❌
http://localhost:4000- Blocked (port 4000 not allowed)
Security: Remove localhost domains from production keys! Create separate API keys for development.
Step 3: Save and Test
- Click Save Changes
- Test your application from an allowed domain
- Verify blocked domains receive
403 Forbiddenerrors
Testing Domain Restrictions
# From allowed domain (should succeed)
curl https://nexus.fortiblox.com/rpc?api-key=fbx_... \
-X POST \
-H "Origin: https://myapp.com" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"getHealth","id":1}'
# Response: {"jsonrpc":"2.0","result":"ok","id":1}
# From blocked domain (should fail)
curl https://nexus.fortiblox.com/rpc?api-key=fbx_... \
-X POST \
-H "Origin: https://attacker.com" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"getHealth","id":1}'
# Response:
# {
# "success": false,
# "error": "Request origin not in allowed domains list",
# "error_code": "DOMAIN_NOT_ALLOWED",
# "allowed_domains": ["https://myapp.com"]
# }Common Issues
Issue: CORS errors in browser
Access to fetch at 'https://nexus.fortiblox.com/rpc' from origin 'https://myapp.com'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present.Solution: This is normal browser behavior. FortiBlox handles CORS automatically. Make sure:
- Domain restrictions are enabled
- Your domain is in the allowed list
- You're using
https://(nothttp://) for production domains
Issue: Postman/cURL tests fail
Domain restrictions only work with browser requests. For API testing tools:
- Use IP restrictions instead
- Or temporarily disable domain restrictions during testing
Issue: Subdomain not working
❌ https://www.myapp.com - BlockedSolution: Add wildcard or specific subdomain:
https://*.myapp.comOr add each subdomain explicitly:
https://www.myapp.com
https://api.myapp.com
https://staging.myapp.comIP Address Restrictions
IP restrictions allow you to whitelist specific IP addresses or CIDR ranges that can use your API key. This is ideal for server-to-server applications.
When to Use IP Restrictions
- ✅ Server-to-server applications
- ✅ Backend APIs and microservices
- ✅ CI/CD pipelines
- ✅ Cron jobs and scheduled tasks
- ✅ Cloud infrastructure (AWS, GCP, Azure)
- ❌ Browser-based applications (use domain restrictions)
- ❌ Mobile applications (users have dynamic IPs)
Configuring IP Restrictions
Step 1: Find Your Server's IP Address
# From your server, run:
curl ifconfig.me
# Or
curl ipinfo.io/ip
# Example output: 203.0.113.45Step 2: Enable IP Restrictions
- Log in to the Developer Portal
- Navigate to API Keys
- Click on the API key you want to configure
- Scroll to Access Control section
- Toggle IP Restrictions to ON
Step 3: Add Allowed IPs
203.0.113.45Only requests from this specific IP will be allowed.
Example:
- ✅
203.0.113.45- Allowed - ❌
203.0.113.46- Blocked
Use cases:
- Single server
- Dedicated instance
- Static home/office IP
203.0.113.45
198.51.100.12
192.0.2.100Add one IP per line. Requests from any of these IPs will be allowed.
Example:
- ✅
203.0.113.45- Allowed - ✅
198.51.100.12- Allowed - ✅
192.0.2.100- Allowed - ❌
203.0.113.46- Blocked
Use cases:
- Multiple servers
- Load-balanced instances
- Development + production servers
203.0.113.0/24This allows IPs from 203.0.113.0 to 203.0.113.255 (256 addresses).
Common CIDR ranges:
/32- Single IP (203.0.113.45/32 = just 203.0.113.45)/24- 256 IPs (203.0.113.0/24 = 203.0.113.0 to 203.0.113.255)/20- 4,096 IPs (203.0.112.0/20)/16- 65,536 IPs (203.0.0.0/16)
CIDR Calculator: Use cidr.xyz to calculate ranges.
Example:
# Corporate network
10.0.0.0/16
# AWS VPC
172.31.0.0/16
# Google Cloud
10.128.0.0/20Use cases:
- Corporate networks
- Cloud provider IP ranges
- VPC subnets
- Data center blocks
2001:db8::1
2001:db8::/32IPv6 addresses and ranges are fully supported.
Example:
- ✅
2001:db8::1- Allowed (exact match) - ✅
2001:db8::2- Allowed (in range 2001:db8::/32) - ❌
2001:db9::1- Blocked (outside range)
Use cases:
- IPv6-only infrastructure
- Modern cloud deployments
- Future-proofing your setup
Cloud Provider IP Ranges
Option 1: Specific VPC Range
# Your VPC CIDR
172.31.0.0/16Option 2: All AWS IP Ranges in a Region
Download AWS IP ranges:
curl https://ip-ranges.amazonaws.com/ip-ranges.json | \
jq -r '.prefixes[] | select(.region=="us-east-1" and .service=="EC2") | .ip_prefix'Example output:
3.208.0.0/12
18.208.0.0/13
34.192.0.0/12
...Add these ranges to your allowed IPs list.
Security: Using all AWS IPs is less secure. Prefer specific VPC ranges when possible.
Option 1: Specific VPC Range
# Your VPC CIDR
10.128.0.0/20Option 2: All GCP IP Ranges
Download GCP IP ranges:
curl https://www.gstatic.com/ipranges/cloud.json | \
jq -r '.prefixes[] | select(.scope=="us-central1") | .ipv4Prefix'Example output:
34.66.0.0/16
35.184.0.0/13
35.192.0.0/14
...Option 1: Specific VNet Range
# Your VNet CIDR
10.0.0.0/16Option 2: All Azure IP Ranges in a Region
Download Azure IP ranges:
- Visit Microsoft Download Center
- Download "Azure IP Ranges and Service Tags – Public Cloud"
- Extract JSON file
- Find your region's IP ranges
# Example: US East
cat ServiceTags_Public.json | \
jq -r '.values[] | select(.name=="AzureCloud.EastUS") | .properties.addressPrefixes[]'DigitalOcean Droplets
Find your droplet's IP in the DO dashboard, then add it:
159.203.45.67Multiple Droplets
Add each droplet's IP:
159.203.45.67
165.227.89.123
178.128.234.56Load Balanced Droplets
Use the load balancer's IP:
# Load balancer IP
104.131.180.200
# Or allow the entire droplet range (less secure)
159.203.0.0/16Testing IP Restrictions
# From allowed IP (should succeed)
curl https://nexus.fortiblox.com/rpc?api-key=fbx_... \
-X POST \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"getHealth","id":1}'
# Response: {"jsonrpc":"2.0","result":"ok","id":1}
# From blocked IP (should fail)
# Response:
# {
# "success": false,
# "error": "Request IP not in allowed list",
# "error_code": "IP_NOT_ALLOWED",
# "request_ip": "198.51.100.99",
# "allowed_ips": ["203.0.113.0/24"]
# }Common Issues
Issue: My server's IP changed
Cloud providers may change IPs when you restart instances.
Solution:
- Use Elastic IPs (AWS), Static IPs (GCP), or Reserved IPs (DigitalOcean)
- Or use a CIDR range for your VPC
- Or use DNS-based allowlisting (contact support for enterprise feature)
Issue: Requests from CI/CD pipeline fail
GitHub Actions IP: 185.199.108.153 - BlockedSolution: Add CI/CD provider IP ranges:
GitHub Actions:
# Get GitHub's IP ranges
curl https://api.github.com/meta | jq -r '.actions[]'GitLab CI:
# Add GitLab runner's IP
203.0.113.100CircleCI:
# CircleCI provides static IPs on paid plans
18.214.70.5
18.214.156.34Issue: Load balancer traffic blocked
If using a load balancer, requests appear to come from the load balancer's IP, not the original client.
Solution:
- Add load balancer's IP to allowed list
- Or configure load balancer to forward original IP (X-Forwarded-For header)
- Contact support to enable X-Forwarded-For IP checking
Network Restrictions
Network restrictions allow you to limit which X1 Blockchain networks (mainnet, devnet, testnet) an API key can access.
When to Use Network Restrictions
- ✅ Prevent accidental mainnet usage with dev keys
- ✅ Separate billing for different networks
- ✅ Enforce development best practices
- ✅ Prevent costly mistakes (e.g., airdrops on mainnet)
Configuring Network Restrictions
Step 1: Enable Network Restrictions
- Log in to the Developer Portal
- Navigate to API Keys
- Click on the API key you want to configure
- Scroll to Access Control section
- Toggle Network Restrictions to ON
Step 2: Select Allowed Networks
Recommended configuration:
✅ Devnet
✅ Testnet
❌ MainnetUse case: Development and testing environments.
Benefits:
- Prevents accidental mainnet transactions
- Free devnet SOL from faucets
- No risk of losing real funds
Example:
// This works
const devnetConnection = new Connection(
`https://nexus.fortiblox.com/rpc?api-key=${DEV_KEY}&network=devnet`
);
// This is blocked
const mainnetConnection = new Connection(
`https://nexus.fortiblox.com/rpc?api-key=${DEV_KEY}&network=mainnet`
);
// Error: 403 Forbidden - Network not allowedRecommended configuration:
❌ Devnet
❌ Testnet
✅ MainnetUse case: Production applications only.
Benefits:
- Prevents accidental devnet usage in production
- Clean separation of environments
- Accurate production metrics
Example:
// This works
const mainnetConnection = new Connection(
`https://nexus.fortiblox.com/rpc?api-key=${PROD_KEY}&network=mainnet`
);
// This is blocked
const devnetConnection = new Connection(
`https://nexus.fortiblox.com/rpc?api-key=${PROD_KEY}&network=devnet`
);
// Error: 403 Forbidden - Network not allowedRecommended configuration:
✅ Devnet
✅ Testnet
✅ MainnetUse case: Integration testing, CI/CD pipelines.
Benefits:
- Test against multiple networks
- Verify mainnet compatibility without production key
- Comprehensive testing
Example:
// All networks work with testing key
const networks = ['mainnet', 'devnet', 'testnet'];
for (const network of networks) {
const connection = new Connection(
`https://nexus.fortiblox.com/rpc?api-key=${TEST_KEY}&network=${network}`
);
await runTests(connection, network);
}Testing Network Restrictions
# Test allowed network (should succeed)
curl https://nexus.fortiblox.com/rpc?api-key=fbx_test_...&network=devnet \
-X POST \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"getHealth","id":1}'
# Response: {"jsonrpc":"2.0","result":"ok","id":1}
# Test blocked network (should fail)
curl https://nexus.fortiblox.com/rpc?api-key=fbx_test_...&network=mainnet \
-X POST \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"getHealth","id":1}'
# Response:
# {
# "success": false,
# "error": "Network not allowed for this API key",
# "error_code": "NETWORK_NOT_ALLOWED",
# "requested_network": "mainnet",
# "allowed_networks": ["devnet", "testnet"]
# }Combining Multiple Restrictions
You can enable multiple access controls simultaneously for defense in depth.
Example: Production Web Application
API Key: fbx_xyz...
Domain Restrictions: ✅ Enabled
- https://myapp.com
- https://www.myapp.com
IP Restrictions: ❌ Disabled
(Not needed for web app)
Network Restrictions: ✅ Enabled
- Mainnet onlyResult: API key only works:
- From
https://myapp.comorhttps://www.myapp.com - On mainnet network only
Example: Production Backend API
API Key: fbx_api...
Domain Restrictions: ❌ Disabled
(Server-to-server doesn't use Origin header)
IP Restrictions: ✅ Enabled
- 203.0.113.0/24 (Production VPC)
- 198.51.100.0/24 (Backup data center)
Network Restrictions: ✅ Enabled
- Mainnet onlyResult: API key only works:
- From IPs in specified ranges
- On mainnet network only
Example: Development Environment
API Key: fbx_test_xyz...
Domain Restrictions: ✅ Enabled
- http://localhost:3000
- https://dev.myapp.com
IP Restrictions: ✅ Enabled
- 203.0.113.100 (Developer workstation)
- 10.0.0.0/16 (Office network)
Network Restrictions: ✅ Enabled
- Devnet only
- Testnet onlyResult: API key only works:
- From localhost or dev domain
- From developer's IP or office network
- On devnet/testnet only (prevents mainnet accidents)
Access Control Priority
When multiple restrictions are enabled, they are evaluated in order:
1. API Key Valid? ───❌──→ 401 Unauthorized
│
✅
2. Network Allowed? ─❌──→ 403 Network Not Allowed
│
✅
3. IP Allowed? ──────❌──→ 403 IP Not Allowed
│
✅
4. Domain Allowed? ──❌──→ 403 Domain Not Allowed
│
✅
5. Rate Limit OK? ───❌──→ 429 Rate Limit Exceeded
│
✅
✅ Request AllowedProgrammatic Management
Manage access controls via the FortiBlox API (coming soon):
// Update access controls via API
const response = await fetch('https://nexus.fortiblox.com/v1/api-keys/12345/access-control', {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${ADMIN_TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
domain_restrictions: {
enabled: true,
allowed_domains: [
'https://myapp.com',
'https://*.myapp.com'
]
},
ip_restrictions: {
enabled: true,
allowed_ips: [
'203.0.113.0/24',
'198.51.100.0/24'
]
},
network_restrictions: {
enabled: true,
allowed_networks: ['mainnet']
}
})
});Monitoring & Alerts
Track blocked requests in real-time:
Developer Portal → Analytics → Blocked Requests
View:
- Total blocked requests (last 24 hours)
- Blocked by reason (domain, IP, network)
- Top blocked IPs
- Top blocked domains
- Blocked request timeline
Set up alerts:
- Go to Settings → Notifications
- Enable "Blocked Request Alerts"
- Configure threshold (e.g., alert when >100 blocked/hour)
- Choose notification method (email, webhook, Discord)
Best Practices
For Web Applications
- Always use domain restrictions for browser-based apps
- Add wildcard for subdomains:
https://*.myapp.com - Include localhost for development:
http://localhost:3000 - Create separate keys for dev, staging, production
- Remove localhost from production keys
For Server Applications
- Always use IP restrictions for server-to-server
- Use CIDR ranges for cloud deployments (more flexible)
- Use Elastic/Static IPs to prevent IP changes
- Add CI/CD IPs if running tests from pipelines
- Document IP ranges in your infrastructure docs
For All Applications
- Enable network restrictions to prevent accidents
- Combine multiple restrictions for defense in depth
- Monitor blocked requests regularly
- Update restrictions when infrastructure changes
- Test thoroughly after enabling restrictions
Troubleshooting
"Domain Not Allowed" Error
{
"error": "Request origin not in allowed domains list",
"error_code": "DOMAIN_NOT_ALLOWED"
}Checklist:
- Is domain restrictions enabled?
- Is your domain in the allowed list?
- Did you include
https://(nothttp://)? - For subdomains, did you add wildcard or specific subdomain?
- Are you testing from a browser (not Postman/cURL)?
"IP Not Allowed" Error
{
"error": "Request IP not in allowed list",
"error_code": "IP_NOT_ALLOWED",
"request_ip": "198.51.100.99"
}Checklist:
- Is IP restrictions enabled?
- Is your IP in the allowed list?
- Did your server's IP change recently?
- If using a load balancer, did you add its IP?
- If using CIDR, is the range correct?
Check your current IP:
curl ifconfig.me"Network Not Allowed" Error
{
"error": "Network not allowed for this API key",
"error_code": "NETWORK_NOT_ALLOWED",
"requested_network": "mainnet"
}Checklist:
- Is network restrictions enabled?
- Is the requested network in the allowed list?
- Are you using the correct API key for this environment?
- Did you specify the network in the URL?
&network=mainnet
Support
Need help with access control?
- Documentation: You're reading it!
- Discord: discord.gg/fortiblox
- Email: [email protected]
- Live Chat: Available in Developer Portal (Business+ tiers)