v0.14 is out: a mobile auth pack for Swift/iOS and Android, catching insecure token storage, cleartext traffic, and OAuth in embedded WebViews. Read more →
MEDIUM AI PREVALENCE: MEDIUM auth.java.oauth.hardcoded-client-secret

An OAuth 2.0 client secret is hard-coded as a string literal in a Spring Security ClientRegistration builder (.clientSecret("...")).

Why AI tools produce this: AI coding tools produce this regularly, typically when prompted for a shortcut or a quick fix.

Why this matters

The client secret authenticates your application to the authorization server's token endpoint; committed to source control it is one search away from compromise, letting an attacker impersonate your client to redeem authorization codes and mint access tokens (CWE-798). This is a common AI-generated mistake: a literal secret is inlined to make the OAuth sample "just work" and never externalized.

Load the secret from outside the source: a @Value("${...}")-injected property, System.getenv(...), Environment.getProperty(...), or a secret manager (Vault, AWS Secrets Manager). In Spring Boot, prefer spring.security.oauth2.client.registration.<id>.client-secret bound from an environment variable. Rotate any secret already checked in.

VULNERABLE
vulnerable.java
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.config.oauth2.client.CommonOAuth2Provider;
import org.springframework.security.oauth2.core.AuthorizationGrantType;

class OAuthClients {

    // Manual ClientRegistration with an inlined literal client secret.
    ClientRegistration google() {
        // ruleid: auth.java.oauth.hardcoded-client-secret
        return ClientRegistration.withRegistrationId("google")
                .clientId("google-client-id")
                .clientSecret("Kd8s0-h4rdC0ded-cl1ent-secret")
                .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
                .redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
                .build();
    }

    // CommonOAuth2Provider builder with a literal secret.
    ClientRegistration github() {
        // ruleid: auth.java.oauth.hardcoded-client-secret
        return CommonOAuth2Provider.GITHUB.getBuilder("github")
                .clientId("github-client-id")
                .clientSecret("gh0-literal-oauth-app-secret")
                .build();
    }
}
SAFE
safe.java
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.security.oauth2.client.registration.ClientRegistration;

class OAuthClients {

    @Value("${google.client-secret}")
    private String googleSecret;

    // Secret injected from a configuration property.
    ClientRegistration fromInjectedProperty() {
        // ok: auth.java.oauth.hardcoded-client-secret
        return ClientRegistration.withRegistrationId("google")
                .clientId("google-client-id")
                .clientSecret(googleSecret)
                .build();
    }

    // Secret read from the environment at build time.
    ClientRegistration fromEnv() {
        // ok: auth.java.oauth.hardcoded-client-secret
        return ClientRegistration.withRegistrationId("google")
                .clientId("google-client-id")
                .clientSecret(System.getenv("GOOGLE_CLIENT_SECRET"))
                .build();
    }

    // Secret resolved from a property placeholder / Environment.
    ClientRegistration fromEnvironment(Environment env) {
        // ok: auth.java.oauth.hardcoded-client-secret
        return ClientRegistration.withRegistrationId("google")
                .clientSecret(env.getProperty("google.client-secret"))
                .build();
    }
}

Suppressing this rule

If a finding is a genuine false positive, scope the suppression to the exact line and leave a reason, never disable the rule project-wide. Disable directives are line-scoped by design.

// oauthlint-disable-next-line auth.java.oauth.hardcoded-client-secret -- <reason>

References

https://docs.spring.io/spring-security/reference/servlet/oauth2/client/core.html ↗https://cwe.mitre.org/data/definitions/798.html ↗https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html ↗