A Valid Token Is Not a Permission: The OAuth Scope Nobody Checked

I recently came across an application that used OAuth very carelessly. The client had implemented a complete Authorization Code flow and on the surface everything looked perfectly fine. What they had missed was scope management. The server received an access token from the identity provider and relied on it blindly, without ever verifying which scopes had actually been issued to the user.

The result was simple. The moment I held a token with a basic scope such as read_profile, I could use it against an internal endpoint that was only supposed to accept tokens carrying admin_write. In practice no check was performed on the server at all – anyone with a valid token, whatever its scope, got access to a sensitive API.

The request looked like this:

GET /api/admin/createUser HTTP/1.1
Host: VICTIM_WEB_SITE
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

No additional validation of the claims took place. So in practice I was able to create new users in the system with full privileges, even though my own user was nowhere near supposed to have that capability.

From an attacker’s point of view this is a classic privilege escalation. It is enough to steal or otherwise obtain some access token – through phishing, or through a mistake in the client – and then use it to perform administrative actions that were meant to be out of reach.

What the right solution looks like

  • Always validate the scope declared in the token, on the server. Verifying that the signature is correct is not enough; you also have to verify that the scope includes the permissions appropriate to the specific action.
  • Do not build business logic on the existence of an access token alone. The token is a means of identification, not the source of truth.
  • When a user performs a permission-sensitive action, check again against an internal authorization store and confirm they genuinely hold the matching permission.
  • Monitor unusual use of administrative endpoints by tokens that carry only basic scopes.

This is a case that illustrates just how quickly a small gap in understanding the OAuth model turns into a significant security hole with real business impact.


I first shared a version of this as a LinkedIn post on 2025-09-24. It is republished here, lightly edited, so it is easier to find and reference. — Erez Metula