Introduction

Role-Based Access Control (RBAC) systems validate that the authenticated user's token includes the required scope or permission for the requested resource and action. When the token does not include the necessary scope -- because the role was not assigned, the scope was not requested during authentication, or the resource has more restrictive policies -- the API returns a 403 Forbidden error.

Symptoms

  • API returns 403 Forbidden with insufficient_scope error
  • Error response includes the missing scope in the WWW-Authenticate header
  • User can access some endpoints but not others within the same API
  • Token introspection shows the user's roles do not include the required permission
  • Error message: {"error":"insufficient_scope","scope":"resource:write"}

Common Causes

  • User role not assigned the required permission for the specific resource
  • OAuth token requested without the necessary scope in the scope parameter
  • Resource-level RBAC policy added after the user's role was defined
  • Token cached with old scopes before the role was updated
  • Cross-tenant or cross-organization resource access not configured

Step-by-Step Fix

  1. 1.Check the token's current scopes: Inspect what permissions the token has.
  2. 2.```bash
  3. 3.# Decode the JWT token
  4. 4.echo "eyJhbGci..." | cut -d. -f2 | base64 -d | jq '.scope, .roles'
  5. 5.# Or introspect the token
  6. 6.curl -X POST https://auth.example.com/oauth/introspect \
  7. 7.-d "token=ACCESS_TOKEN" \
  8. 8.-H "Authorization: Basic BASE64(client:secret)"
  9. 9.`
  10. 10.Identify the required scope for the endpoint: Check the API documentation.
  11. 11.`
  12. 12.# API documentation should specify required scopes per endpoint:
  13. 13.# POST /api/resources - requires "resource:write" scope
  14. 14.# GET /api/resources - requires "resource:read" scope
  15. 15.`
  16. 16.Request a new token with the required scope: Include the missing scope.
  17. 17.```bash
  18. 18.curl -X POST https://auth.example.com/oauth/token \
  19. 19.-d "grant_type=client_credentials" \
  20. 20.-d "scope=resource:read resource:write" \
  21. 21.-d "client_id=CLIENT_ID" \
  22. 22.-d "client_secret=CLIENT_SECRET"
  23. 23.`
  24. 24.Assign the required role to the user if scope is role-based: Update RBAC.
  25. 25.```bash
  26. 26.# Via admin API
  27. 27.curl -X POST https://admin.example.com/api/users/$USER_ID/roles \
  28. 28.-H "Authorization: Bearer $ADMIN_TOKEN" \
  29. 29.-H "Content-Type: application/json" \
  30. 30.-d '{"role": "resource-admin"}'
  31. 31.`
  32. 32.Test the API request with the updated token: Verify access is granted.
  33. 33.```bash
  34. 34.curl -X POST https://api.example.com/api/resources \
  35. 35.-H "Authorization: Bearer $NEW_TOKEN" \
  36. 36.-H "Content-Type: application/json" \
  37. 37.-d '{"name": "test-resource"}'
  38. 38.# Should return 201 Created instead of 403
  39. 39.`

Prevention

  • Document required scopes for each API endpoint in the API documentation
  • Use token introspection to validate scopes before making API requests
  • Implement progressive scope requests -- start with read-only and request write scopes as needed
  • Monitor 403 error rates and correlate with missing scope types
  • Implement RBAC change management processes that include scope impact analysis
  • Use automated testing to verify that service accounts have the required scopes for their operations