CRITICAL identification failuresbearer tokens

Identification Failures with Bearer Tokens

How Identification Failures Manifests in Bearer Tokens

Identification failures in Bearer Token authentication occur when an API fails to properly validate the token's authenticity, integrity, and claims before granting access. This is a specific instance of OWASP API2:2023 (Broken Authentication) and often leads to Broken Object Property Authorization (API5:2023). The core issue is the server's trust in a token presented by the client without sufficient verification.

Common attack patterns include:

  • Token Substitution: An attacker uses a valid token from a low-privilege user (e.g., a standard user) to access resources or actions belonging to a high-privilege user (admin). This happens when the API does not validate the token's scope, roles, or custom claims against the required permission for the endpoint.
  • Expired or Revoked Token Acceptance: The API accepts tokens past their expiration (exp claim) or after they have been revoked (e.g., after logout). This often occurs when the server only checks the token's format but not its temporal validity or against a revocation list.
  • Signature Bypass: The server decodes the token (e.g., a JWT) but fails to verify its cryptographic signature. An attacker can modify the token's payload (e.g., change user_id or role) and re-encode it without a valid signature, and the server will accept the altered claims. This is akin to CVE-2020-28022 (an information disclosure in a JWT library due to signature bypass).
  • Algorithm Confusion: The server accepts tokens signed with none (unsigned) or incorrectly handles key selection (e.g., using the public key as an HMAC secret). An attacker can exploit this to forge tokens.
  • Missing Audience/Issuer Validation: The token is accepted even if its aud (audience) or iss (issuer) claims do not match the expected values for the API. This allows tokens issued for a different service or client to be reused.

In code, this often appears as:

// VULNERABLE: Express.js route that decodes but does not verify
app.get('/admin/data', (req, res) => {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) return res.status(401).send('No token');
  const decoded = jwt.decode(token); // DANGER: decode only, no verify!
  if (decoded.role === 'admin') {
    return res.json({ sensitive: 'admin data' });
  }
  res.status(403).send('Forbidden');
});

The jwt.decode() merely base64-decodes the payload without verifying the signature. Any modified token with a forged role claim will be accepted.

Bearer Tokens-Specific Detection

Detecting identification failures requires testing the API's enforcement of token validation. Since middleBrick performs black-box scanning without credentials, it probes the unauthenticated attack surface by sending crafted requests to evaluate the server's behavior.

middleBrick's Authentication and BOLA/IDOR checks (run in parallel) specifically target these failures:

  • Signature Verification Test: middleBrick sends a request with a token that has a valid structure but an invalid signature (or none algorithm). If the API returns a 200 OK instead of 401, it indicates signature verification is absent.
  • Expiration Test: A token with an expired exp claim is submitted. Acceptance suggests temporal validation is missing.
  • Privilege Escalation Probe: middleBrick attempts to use a low-privilege token (if any is discovered during scanning) to access admin-only endpoints, testing for inadequate scope/role checks.
  • Audience/Issuer Mismatch: Tokens with incorrect aud or iss values are sent to see if they are rejected.

For example, scanning an endpoint with middleBrick's CLI:

middlebrick scan https://api.example.com/v1/users

The scanner might return a finding like:

CheckSeverityFinding
AuthenticationCriticalBearer token signature not verified. Endpoint accepts tokens with alg=none.

middleBrick's OpenAPI/Swagger analysis also cross-references the specification's security schemes (e.g., type: http, scheme: bearer) with runtime behavior. If the spec defines a bearer token requirement but the runtime endpoint accepts requests without one or with invalid tokens, it flags a discrepancy.

Bearer Tokens-Specific Remediation

Remediation centers on robust, server-side token validation using the native features of your authentication library. Never trust client-provided tokens; always verify every claim.

1. Enforce Signature Verification
Use your framework's built-in verification method, not decode. For Node.js/Express with jsonwebtoken:

const jwt = require('jsonwebtoken');

app.get('/admin/data', (req, res) => {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) return res.status(401).json({ error: 'Missing token' });

  // SECURE: verify signature, expiration, audience, issuer
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET, {
      audience: 'api.example.com',
      issuer: 'auth.example.com',
      algorithms: ['RS256'] // specify expected algorithm
    });
    // Now decoded.role is trustworthy
    if (decoded.role !== 'admin') {
      return res.status(403).json({ error: 'Insufficient role' });
    }
    res.json({ sensitive: 'admin data' });
  } catch (err) {
    // Catches: TokenExpiredError, JsonWebTokenError, NotBeforeError
    return res.status(401).json({ error: 'Invalid or expired token' });
  }
});

2. Validate All Claims
Check exp (expiration), nbf (not before), iat (issued at), aud (audience), and iss (issuer). The jwt.verify method handles exp and nbf automatically; pass audience and issuer options to enforce them.

3. Use Asymmetric Keys for Public APIs
If the API is public (clients hold tokens), use RS256 (RSA) instead of HS256 (HMAC). The server holds the private key to sign; clients only have the public key to verify. This prevents token forgery if the secret is exposed.

4. Implement Token Revocation
For immediate invalidation, maintain a short-lived access token (e.g., 15 minutes) and a long-lived refresh token stored securely (HTTP-only cookie). On logout or compromise, add the token's jti (JWT ID) to a blocklist (e.g., Redis) checked during verification.

// In verification middleware
const token = req.headers.authorization?.split(' ')[1];
const decoded = jwt.decode(token, { complete: true });
if (await redis.get(`blocklist:${decoded.payload.jti}`)) {
  return res.status(401).json({ error: 'Token revoked' });
}
// Proceed with jwt.verify...

5. Scope-Based Authorization
After verifying the token, map its scope or custom roles claim to the required permission for the endpoint. Use a middleware like express-jwt or passport with strategies that enforce scopes.

middleBrick's reports will highlight missing validations and provide remediation guidance mapped to OWASP and compliance frameworks like PCI-DSS 8.3 (authenticate all access).

Frequently Asked Questions

How does middleBrick detect bearer token validation issues without valid credentials?
middleBrick sends deliberately malformed or invalid bearer tokens (e.g., with alg=none, expired exp, or wrong signature) to your API endpoints. If the API responds with a 200 OK instead of 401/403, it indicates the token validation is absent or broken. This black-box testing reveals what an unauthenticated attacker could discover.
What's the most common mistake developers make with bearer tokens?
The most critical mistake is decoding the token without verifying its signature. Using jwt.decode() (or equivalent) only reads the payload, allowing attackers to modify claims like role or user_id. Always use jwt.verify() with a secret/public key and validate all claims (exp, aud, iss). Never trust client-side data.