API Security
    5/4/2026

    How API Scanners Should Handle OAuth2 & OIDC | ApyGuard

    Static tokens aren't OAuth2 support. Here's what real authentication handling looks like.

    Implementing OAuth2 and OIDC Support in an API Security Scanner: A Strategy Pattern Approach

    If an API security scanner can't authenticate as a real user, it's not testing your real API. It's testing a ghost, the public surface that attackers don't actually use to breach systems.

    Yet most scanners advertise "OAuth2 support" while accepting only a static bearer token you paste in manually. That token expires. The scan fails mid-run. Or worse: the scan completes, reports clean, and the actual authenticated attack surface, where BOLA, scope escalation, and broken authorization live, was never touched.

    This post covers how a production-grade API security scanner should handle authentication, why the Strategy design pattern is the right architecture for it, and what each of the five major authentication flows requires in practice. ApyGuard supports all five natively, here's the reasoning behind each.


    Why Authentication Is Where Most API Scanners Fail

    The fundamental problem is that many DAST tools treat "authentication" as a configuration step, not a runtime concern. You supply a token at setup. The scanner injects it as a header for every request. Done.

    This approach breaks in three common ways:

    Tokens expire. OAuth2 access tokens typically live 15 minutes to 1 hour. A scan that takes 30 minutes against a complex API will hit expired tokens mid-run, either silently skipping authenticated endpoints or generating a wall of 401 errors that obscure real findings.

    Token injection isn't the same as authentication. A scanner that accepts a static bearer token has no idea how that token was obtained, what scope it carries, or how to get a new one. Real OAuth2 support means the scanner participates in the grant flow, it knows how to authenticate, not just how to attach a credential.

    Authenticated vulnerabilities require authenticated sessions. Broken Object Level Authorization (BOLA), consistently the top vulnerability in OWASP API Top 10, is only detectable when the scanner has valid credentials for multiple user contexts. An unauthenticated scanner will never find that endpoint A allows user 1 to access user 2's resources.

    A 2025 analysis of OAuth implementations across 500 production applications found that 41% had at least one exploitable vulnerability. Almost none of those would surface in an unauthenticated or static-token scan.


    The Strategy Pattern Applied to Authentication

    The Strategy pattern is a behavioral design pattern where a family of algorithms is defined, each is encapsulated, and they're made interchangeable. The caller doesn't know which strategy it's using, it just knows it will get an authenticated request out.

    Applied to API security scanning, it looks like this:

    interface AuthStrategy {
     authenticate(): Credentials
     refresh(existing: Credentials): Credentials
     isValid(credentials: Credentials): boolean
    }
    

    Each authentication method, API key, basic auth, OAuth2 client credentials, OIDC, username/password, implements this interface. The user selects the right strategy at runtime based on the scan configuration. From the scanner's perspective, it always gets a valid credential object back. The strategy handles the complexity of obtaining and refreshing that credential.

    This architecture solves the token expiry problem: isValid() runs before each authenticated request. When it returns false, it tries to authenticate again or use refresh to extend session. The scan never sees an expired credential.

    It also makes adding new auth schemes trivial, implement the interface, register the strategy, done.

    Here's how each of the five strategies works in practice.


    The Five Authentication Strategies

    Strategy 1, Predefined Keys (API Key & Basic Auth)

    When to use: Static credentials that don't expire, API keys passed in headers or query params, and HTTP Basic Auth (Base64-encoded username:password in the Authorization header).

    How it works: These are the simplest strategies. The credential is supplied at configuration time and injected on every request. isValid() always returns true (the key doesn't expire from the client's perspective), and refresh() is a no-op.

    Authorization: Bearer sk_live_abc123xyz
    Authorization: Basic dXNlcjpwYXNzd29yZA==
    X-API-Key: sk_live_abc123xyz
    

    What to scan for when using this strategy:

    • API keys appearing in URL query parameters (logged by proxies and CDNs)
    • Basic Auth over non-TLS connections
    • Insufficient API key entropy (short keys, predictable patterns)
    • Missing key rotation mechanisms
    • Horizontal access: does the key enforce tenant isolation?

    This strategy covers a large portion of internal APIs, webhook receivers, and legacy services. Simple, but the security implications of static credentials are significant.


    Strategy 2, Username/Password with Login URL

    When to use: APIs backed by custom session-based authentication, a login endpoint that accepts credentials and returns a session cookie, JWT, or custom token. Common in older web applications that expose an API layer over a traditional session system.

    How it works: The strategy sends a POST request to the configured login URL with the supplied credentials. It captures the response, whether that's a Set-Cookie header, a JSON { token: "..." } body, or a custom X-Auth-Token header, and uses that as the credential for subsequent scan requests.

    POST /api/auth/login
    Content-Type: application/json
    
    { "email": "[email protected]", "password": "..." }
    
    → Response: { "token": "eyJhbGc...", "expires_in": 3600 }
    

    Token refresh is handled by re-running the login flow when isValid() detects expiry.

    What to scan for:

    • Credential stuffing attack surface (rate limiting, lockout policies)
    • Session fixation vulnerabilities
    • Token exposure in response body vs. secure HttpOnly cookie
    • Session token predictability
    • Missing logout invalidation (does the server-side session actually end?)

    This strategy is particularly important for testing business logic vulnerabilities in user flows, the scanner is operating as a real logged-in user.


    Strategy 3, OIDC Client Credentials

    When to use: Machine-to-machine communication where the API is protected by an OpenID Connect provider. The client (scanner) authenticates using a client_id and client_secret registered with the IdP, without any user context.

    How it works: The strategy sends a token request to the OIDC provider's token endpoint using the Client Credentials grant, then uses the returned access_token as a Bearer token.

    POST https://auth.example.com/oauth/token
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=client_credentials
    &client_id=scanner-client
    &client_secret=...
    &scope=api:read api:write
    

    The key difference from plain OAuth2 Client Credentials is that the token endpoint is discovered via the OIDC Discovery document (/.well-known/openid-configuration), and the token is a signed JWT with standard OIDC claims (iss, aud, sub, exp). The strategy can validate these claims before using the token.

    What to scan for:

    • Overly broad scopes returned by the IdP (scope creep)
    • Missing aud claim validation on the API side
    • exp claim not enforced server-side
    • Client secrets transmitted insecurely
    • Token reuse across different API contexts

    Strategy 4, OAuth2 Password Grant

    When to use: Trusted internal clients or legacy APIs where the application exchanges a user's credentials directly for an access token at the authorization server. This is the Resource Owner Password Credentials (ROPC) grant defined in RFC 6749.

    How it works:

    POST /oauth/token
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=password
    &[email protected]
    &password=...
    &client_id=scanner-client
    &client_secret=...
    &scope=read write
    

    The authorization server returns an access_token (and usually a refresh_token), which the strategy uses for subsequent requests. When the access token expires, refresh() uses the refresh token to obtain a new one without re-supplying credentials.

    Important: The ROPC grant is deprecated in OAuth 2.1 (RFC 9700). It exposes user credentials directly to the client application, the opposite of what OAuth2 was designed for. Modern APIs should use Authorization Code with PKCE instead.

    ApyGuard supports this grant for testing legacy APIs that haven't migrated, not because it's recommended. If your API still uses ROPC, that's a finding in itself.

    What to scan for:

    • Credentials transmitted in request body (log exposure risk)
    • Missing refresh token rotation
    • Refresh tokens that don't expire
    • Whether the API accepts ROPC at all (flag if the API is public-facing)
    • Insufficient scope enforcement on returned tokens

    Strategy 5, OAuth2 Client Credentials

    When to use: Server-to-server communication, CI/CD pipeline scanning, and any context where no user is involved. This is the most appropriate grant for automated security scanning and is the default for modern M2M API testing.

    How it works:

    POST /oauth/token
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=client_credentials
    &client_id=apyguard-scanner
    &client_secret=...
    &scope=api:read api:admin
    

    The authorization server returns an access_token with the requested scopes. Unlike the Password grant, no user credentials are involved, the client is authenticating on its own behalf.

    For CI/CD integration, client_id and client_secret are typically injected as environment variables rather than stored in the scan configuration file. ApyGuard reads these at runtime, ensuring credentials are never hardcoded in repositories.

    What to scan for:

    • Excessive scopes granted to service clients (principle of least privilege)
    • Tokens accepted beyond their stated expiry
    • Whether the API differentiates between user tokens and service tokens
    • BOLA: can a service-scoped token access user-owned resources it shouldn't?
    • Token introspection endpoint exposure

    What Good Auth Support Looks Like in Practice

    The five strategies above are the foundation. A production-grade scanner also needs to handle the operational realities of running authenticated scans:

    Token refresh without interruption. The scanner checks isValid() before each request sequence. If the token has expired or is within a configurable buffer (e.g., 60 seconds of expiry), refresh() runs before the next request is sent. The scan never hits a 401 mid-run.

    Session persistence across request chains. For multi-step flows, authenticate, create a resource, modify it, delete it, the scanner must maintain session context across the entire chain. Losing auth state between steps means testing individual endpoints in isolation, which misses workflow-based vulnerabilities.

    Role-based testing. Many authorization vulnerabilities only appear when comparing what different roles can access. ApyGuard can be configured with multiple credential sets (admin, regular user, read-only user) and runs cross-context tests, checking whether a regular user token can access admin endpoints, or whether user A can access user B's resources.


    What Your Scanner Should Find in Authenticated Sessions

    Authentication is the prerequisite. The point is what the scanner discovers once it's operating as an authenticated user:

    BOLA (Broken Object Level Authorization), The scanner attempts to access resources belonging to one user context using credentials from another. This is OWASP API1:2023 and the most commonly exploited API vulnerability in production.

    Scope escalation, The scanner tests whether a token with limited scope (api:read) can successfully call endpoints that should require elevated scope (api:admin). Many APIs validate authentication but not authorization.

    Token leakage, Responses are scanned for access tokens, refresh tokens, or credentials appearing in response bodies, headers, or error messages where they shouldn't.

    Broken authentication, As covered in OWASP API2:2023, the scanner tests for JWT weaknesses (algorithm confusion, weak secrets, missing expiry enforcement), missing token validation, and credential stuffing exposure.

    State parameter misuse, For APIs that initiate OAuth2 authorization code flows, the scanner checks whether the state parameter is validated on callback, and whether PKCE is enforced for public clients.


    Configuring Auth in ApyGuard

    Each scan in ApyGuard includes an Authentication section where you select the strategy and supply the relevant credentials. For OAuth2 Client Credentials and OIDC Client Credentials, the token endpoint is either specified directly or discovered automatically from the OIDC Discovery document.

    Once configured, the scanner handles the rest: token acquisition before the scan starts, refresh during the scan, and session persistence across chained requests.

    For a full walkthrough of authenticated scan configuration and what findings to expect, see our API security best practices guide or run your first authenticated scan with our free 7-day trial, no credit card required.


    Conclusion

    Most API security scanners fail at authentication not because the OAuth2 specification is complex, but because they treat auth as a one-time configuration step rather than a runtime concern. Static tokens expire. Scans fail silently. The authenticated attack surface, where most real vulnerabilities live, goes untested.

    The Strategy pattern gives a scanner the architecture to handle this correctly: each authentication method encapsulates its own token acquisition, validation, and refresh logic. The scanner operates with valid credentials throughout. And when the scan completes, it has actually tested your API the way an authenticated attacker would.

    If your current scanner requires you to manually refresh a token before each scan, that's not an OAuth2 feature, it's a workaround for a missing one.

    Start a free API security scan with ApyGuard and configure authentication in under two minutes. Or compare our plans to see what's included in each tier.


    Related reading:


    Published by Anıl Yüksel, Founder & CEO, ApyGuard | April 2026

    Subscribe to our newsletter

    Get API security tips and ApyGuard updates straight to your inbox. No spam, just useful content.

    You can unsubscribe at any time with one click.