FortiBlox LogoFortiBlox Docs
NexusSecurity

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:

  1. API Key Validation - Is the key valid and active?
  2. Network Restrictions - Is the requested network allowed?
  3. IP Restrictions - Is the request from an allowed IP?
  4. Domain Restrictions - Is the request from an allowed domain?
  5. 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/json

FortiBlox 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

  1. Log in to the Developer Portal
  2. Navigate to API Keys
  3. Click on the API key you want to configure
  4. Scroll to Access Control section
  5. Toggle Domain Restrictions to ON

Step 2: Add Allowed Domains

https://myapp.com

Only 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.com

Add 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.com

Use * 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:3000

For 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

  1. Click Save Changes
  2. Test your application from an allowed domain
  3. Verify blocked domains receive 403 Forbidden errors

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:

  1. Domain restrictions are enabled
  2. Your domain is in the allowed list
  3. You're using https:// (not http://) 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 - Blocked

Solution: Add wildcard or specific subdomain:

https://*.myapp.com

Or add each subdomain explicitly:

https://www.myapp.com
https://api.myapp.com
https://staging.myapp.com

IP 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.45

Step 2: Enable IP Restrictions

  1. Log in to the Developer Portal
  2. Navigate to API Keys
  3. Click on the API key you want to configure
  4. Scroll to Access Control section
  5. Toggle IP Restrictions to ON

Step 3: Add Allowed IPs

203.0.113.45

Only 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.100

Add 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/24

This 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/20

Use cases:

  • Corporate networks
  • Cloud provider IP ranges
  • VPC subnets
  • Data center blocks
2001:db8::1
2001:db8::/32

IPv6 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/16

Option 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/20

Option 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/16

Option 2: All Azure IP Ranges in a Region

Download Azure IP ranges:

  1. Visit Microsoft Download Center
  2. Download "Azure IP Ranges and Service Tags – Public Cloud"
  3. Extract JSON file
  4. 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.67

Multiple Droplets

Add each droplet's IP:

159.203.45.67
165.227.89.123
178.128.234.56

Load 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/16

Testing 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 - Blocked

Solution: 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.100

CircleCI:

# CircleCI provides static IPs on paid plans
18.214.70.5
18.214.156.34

Issue: Load balancer traffic blocked

If using a load balancer, requests appear to come from the load balancer's IP, not the original client.

Solution:

  1. Add load balancer's IP to allowed list
  2. Or configure load balancer to forward original IP (X-Forwarded-For header)
  3. 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

  1. Log in to the Developer Portal
  2. Navigate to API Keys
  3. Click on the API key you want to configure
  4. Scroll to Access Control section
  5. Toggle Network Restrictions to ON

Step 2: Select Allowed Networks

Recommended configuration:

✅ Devnet
✅ Testnet
❌ Mainnet

Use 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 allowed

Recommended configuration:

❌ Devnet
❌ Testnet
✅ Mainnet

Use 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 allowed

Recommended configuration:

✅ Devnet
✅ Testnet
✅ Mainnet

Use 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 only

Result: API key only works:

  • From https://myapp.com or https://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 only

Result: 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 only

Result: 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 Allowed

Programmatic 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:

  1. Go to SettingsNotifications
  2. Enable "Blocked Request Alerts"
  3. Configure threshold (e.g., alert when >100 blocked/hour)
  4. Choose notification method (email, webhook, Discord)

Best Practices

For Web Applications

  1. Always use domain restrictions for browser-based apps
  2. Add wildcard for subdomains: https://*.myapp.com
  3. Include localhost for development: http://localhost:3000
  4. Create separate keys for dev, staging, production
  5. Remove localhost from production keys

For Server Applications

  1. Always use IP restrictions for server-to-server
  2. Use CIDR ranges for cloud deployments (more flexible)
  3. Use Elastic/Static IPs to prevent IP changes
  4. Add CI/CD IPs if running tests from pipelines
  5. Document IP ranges in your infrastructure docs

For All Applications

  1. Enable network restrictions to prevent accidents
  2. Combine multiple restrictions for defense in depth
  3. Monitor blocked requests regularly
  4. Update restrictions when infrastructure changes
  5. 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:// (not http://)?
  • 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?