diff --git a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/GoogleAuthUtils.java b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/GoogleAuthUtils.java index d82548a082fd..ac1da958cbca 100644 --- a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/GoogleAuthUtils.java +++ b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/GoogleAuthUtils.java @@ -70,7 +70,11 @@ static final File getWellKnownCredentialsFile(DefaultCredentialsProvider provide if (envPath != null) { cloudConfigPath = new File(envPath); } else if (provider.getOsName().indexOf("windows") >= 0) { - File appDataPath = new File(provider.getEnv("APPDATA")); + String appData = provider.getEnv("APPDATA"); + if (appData == null) { + return null; + } + File appDataPath = new File(appData); cloudConfigPath = new File(appDataPath, provider.CLOUDSDK_CONFIG_DIRECTORY); } else { File configPath = new File(provider.getProperty("user.home", ""), ".config"); diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/DefaultCredentialsProviderTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/DefaultCredentialsProviderTest.java index d0447871b01a..60c8d34c9af6 100644 --- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/DefaultCredentialsProviderTest.java +++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/DefaultCredentialsProviderTest.java @@ -115,6 +115,21 @@ void getDefaultCredentials_noCredentials_throws() { assertEquals(DefaultCredentialsProvider.CLOUDSDK_MISSING_CREDENTIALS, message); } + @Test + void getDefaultCredentials_windowsMissingAppData_throwsOrFallback() { + // When APPDATA is unset on Windows, the ADC resolution should fail gracefully + // with a structured missing credentials exception, rather than crashing with an NPE. + // This matches the expected behavior seen in Node.js and Python implementations. + MockHttpTransportFactory transportFactory = new MockHttpTransportFactory(); + TestDefaultCredentialsProvider testProvider = new TestDefaultCredentialsProvider(); + testProvider.setProperty("os.name", "windows"); + testProvider.setEnv("APPDATA", null); + + IOException e = + assertThrows(IOException.class, () -> testProvider.getDefaultCredentials(transportFactory)); + assertEquals(DefaultCredentialsProvider.CLOUDSDK_MISSING_CREDENTIALS, e.getMessage()); + } + @Test void getDefaultCredentials_noCredentialsSandbox_throwsNonSecurity() { MockHttpTransportFactory transportFactory = new MockHttpTransportFactory();