Technical Tip: Existing API user on FortiGate encountering the 401 error 'Bearer error="insufficient_scope"'
Description
This article describes a possible reason why an API user authentication is failing with a 401 error: 'www-authenticate: Bearer error="insufficient_scope"'.
The API user is created as follows:
config system api-user
edit "test-api"
set api-key <api_key>
set accprofile "api_acc_profile"
set cors-allow-origin "https://fndn.fortinet.net"
next
end
And the API request is as follows:
$ curl -kv -H "Accept: application/json" -H "Authorization: Bearer <api-key>" https://10.10.10.10:443/api/v2/cmdb/firewall/address
* Trying 10.10.10.10:443...
... omitted TLS authentication ...
* using HTTP/2
* h2h3 [:method: GET]
* h2h3 [:path: /api/v2/cmdb/firewall/address]
* h2h3 [:scheme: https]
* h2h3 [:authority: 10.10.10.10]
* h2h3 [user-agent: curl/7.88.1]
* h2h3 [accept: application/json]
* h2h3 [authorization: Bearer <api-key>]
* Using Stream ID: 1 (easy handle 0x56020c4bfb40)
> GET /api/v2/cmdb/firewall/address HTTP/2
> Host: 10.10.10.10
> user-agent: curl/7.88.1
> accept: application/json
> authorization: Bearer <api-key>
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
< HTTP/2 401
< x-frame-options: SAMEORIGIN
< content-security-policy: frame-ancestors 'self'
< x-xss-protection: 1; mode=block
< strict-transport-security: max-age=63072000
< access-control-allow-origin: https://fndn.fortinet.net
< access-control-allow-credentials: true
< vary: Origin
< www-authenticate: Bearer error="insufficient_scope"
Scope
FortiGate.
Solution
There are two options for resolving this:
Add the origin to the request, for example:
$ curl -skv -H "Accept: application/json" -H "Authorization: Bearer <api-key>" -H "Origin: https://fndn.fortinet.net" https://10.10.10.10:443/api/v2/cmdb/firewall/address
* Trying 10.10.10.10:443...
... omitted TLS authentication ...
* using HTTP/2
* h2h3 [:method: GET]
* h2h3 [:path: /api/v2/cmdb/firewall/address]
* h2h3 [:scheme: https]
* h2h3 [:authority: 10.10.10.10]
* h2h3 [user-agent: curl/7.88.1]
* h2h3 [accept: application/json]
* h2h3 [authorization: Bearer <api-key>]
* h2h3 [origin: https://fndn.fortinet.net]
* Using Stream ID: 1 (easy handle 0x55f0bef67b40)
> GET /api/v2/cmdb/firewall/address HTTP/2
> Host: 10.10.10.10
> user-agent: curl/7.88.1
> accept: application/json
> authorization: Bearer <api-key>
> origin: https://fndn.fortinet.net
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
< HTTP/2 200
< content-security-policy: frame-ancestors 'self'; script-src 'self'; object-src 'none';
< strict-transport-security: max-age=63072000
< date: Mon, 07 Sep 2026 08:50:30 GMT
< etag: D979F3778B9F124840C673A8CC24D2F03FD1C09F72CF2DAB74D0675BF8A1E70B
< cache-control: no-cache, must-revalidate
< content-length: 6535
< content-type: application/json
...Remove the cors-allow-origin from the API-User configuration:
config system api-user
edit "test-api"
unset cors-allow-origin
next
end
And the request is successful:
$ curl -skv -H "Accept: application/json" -H "Authorization: Bearer <api-key>" https://10.10.10.10:443/api/v2/cmdb/firewall/address
* Trying 10.10.10.10:443...
... omitted TLS authentication ...
* using HTTP/2
* h2h3 [:method: GET]
* h2h3 [:path: /api/v2/cmdb/firewall/address]
* h2h3 [:scheme: https]
* h2h3 [:authority: 10.10.10.10]
* h2h3 [user-agent: curl/7.88.1]
* h2h3 [accept: application/json]
* h2h3 [authorization: Bearer <api-key>]
* Using Stream ID: 1 (easy handle 0x557eb1024b40)
> GET /api/v2/cmdb/firewall/address HTTP/2
> Host: 10.10.10.10
> user-agent: curl/7.88.1
> accept: application/json
> authorization: Bearer <api-key>
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
< HTTP/2 200
< content-security-policy: frame-ancestors 'self'; script-src 'self'; object-src 'none';
< strict-transport-security: max-age=63072000
< date: Mon, 07 Sep 2026 08:54:26 GMT
< etag: D979F3778B9F124840C673A8CC24D2F03FD1C09F72CF2DAB74D0675BF8A1E70B
< cache-control: no-cache, must-revalidate
< content-length: 6535
< content-type: application/json
...