{"record":{"id":"6ca43cd6a8840595","repo":"apereo/cas","slug":"failed-status-s-with-message-s","errorCode":null,"errorMessage":"Failed: status %s with message: %s","messagePattern":"Failed: status (.+?) with message: (.+?)","errorType":"exception","errorClass":"FailedLoginException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-azuread-authentication/src/main/java/org/apereo/cas/azure/ad/authentication/AzureActiveDirectoryAuthenticationHandler.java","lineNumber":66,"sourceCode":"    }\n\n    private String getUserInfoFromGraph(final IAuthenticationResult authenticationResult, final String username) throws Exception {\n        val url = new URI(Strings.CI.appendIfMissing(properties.getResource(), \"/\") + \"v1.0/users/\" + username).toURL();\n        val conn = (HttpURLConnection) url.openConnection();\n        try {\n            conn.setRequestMethod(\"GET\");\n            conn.setRequestProperty(HttpHeaders.AUTHORIZATION, \"Bearer \" + authenticationResult.accessToken());\n            conn.setRequestProperty(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);\n\n            LOGGER.debug(\"Fetching user info from [{}] using access token [{}]\", url.toExternalForm(), authenticationResult.accessToken());\n            val httpResponseCode = conn.getResponseCode();\n            if (HttpStatus.valueOf(httpResponseCode).is2xxSuccessful()) {\n                try (val in = conn.getInputStream()) {\n                    return IOUtils.toString(in, StandardCharsets.UTF_8);\n                }\n            }\n            val msg = String.format(\"Failed: status %s with message: %s\", httpResponseCode, conn.getResponseMessage());\n            throw new FailedLoginException(msg);\n        } finally {\n            conn.disconnect();\n        }\n    }\n\n    protected IAuthenticationResult getAccessTokenFromUserCredentials(final String username, final String password) throws Exception {\n        val clientId = SpringExpressionLanguageValueResolver.getInstance().resolve(properties.getClientId());\n        val scopes = org.springframework.util.StringUtils.commaDelimitedListToSet(properties.getScope());\n        if (StringUtils.isNotBlank(properties.getClientSecret())) {\n            val clientSecret = SpringExpressionLanguageValueResolver.getInstance().resolve(properties.getClientSecret());\n            val clientCredential = ClientCredentialFactory.createFromSecret(clientSecret);\n            val context = ConfidentialClientApplication.builder(clientId, clientCredential)\n                .authority(properties.getLoginUrl())\n                .validateAuthority(true)\n                .build();\n            val resource = Strings.CI.appendIfMissing(properties.getResource(), \"/\").concat(\".default\");\n            val parameters = ClientCredentialParameters.builder(Set.of(resource))\n                .tenant(properties.getTenant())","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-azuread-authentication/src/main/java/org/apereo/cas/azure/ad/authentication/AzureActiveDirectoryAuthenticationHandler.java#L48-L84","documentation":"AzureActiveDirectoryAuthenticationHandler.getUserInfoFromGraph performs a raw HTTP GET against the Microsoft Graph user-info endpoint over HttpURLConnection. When the response status is not 2xx it formats \"Failed: status <code> with message: <reason>\" and throws FailedLoginException. This is the handler reporting that Microsoft Graph rejected or failed the user-info request during username/password authentication.","triggerScenarios":"The conn.getInputStream() path is skipped because HttpStatus.valueOf(httpResponseCode) is not 2xx — e.g. 401/403 (bad/expired access token from getAccessTokenFromUserCredentials), 404 (wrong tenant or graph URL), or 429/5xx from Graph.","commonSituations":"Wrong tenant name / graph base URL in cas.authn.azuread[0] configuration; client credentials lacking permission to call Graph (admin consent not granted); ROPC flow denied by conditional access policies; network proxy or Azure AD outage producing 5xx.","solutions":["Read the logged status code: 401/403 → fix the Azure AD app registration (grant admin consent for the required Graph permissions); 404 → correct the tenant/graph endpoint configuration.","Verify cas.authn.azuread[0] settings (tenant, client-id, client-secret, base URL) are correct and the credentials are still valid — rotate expired client secrets.","Test the same Graph call manually (curl with a token from the OAuth2 token endpoint) to confirm the app can reach the user-info endpoint.","Check conditional-access / MFA policies: the ROPC-style resource-owner credential flow fails for users where Azure requires interactive auth, producing non-2xx here.","Retry on 429/5xx and monitor Azure AD service health if the status indicates throttling or transient server errors."],"exampleFix":"// before (log: Failed: status 401 with message: Unauthorized)\ncas.authn.azuread[0].client-id=old-app-id\ncas.authn.azuread[0].client-secret=expired-secret\n\n// after: fix app registration / secret\ncas.authn.azuread[0].client-id=<correct-app-id>\ncas.authn.azuread[0].client-secret=<new-secret>  # + admin-consented Graph permissions","handlingStrategy":"try-catch","validationCode":"// pre-flight: verify Graph reachability and app credentials\nHttpURLConnection c = (HttpURLConnection) new URL(graphUserInfoUrl).openConnection();\nif (c.getResponseCode() >= 400) LOGGER.warn(\"Graph endpoint returned {}\", c.getResponseCode());","typeGuard":null,"tryCatchPattern":"try {\n    return azureAdHandler.authenticate(credential);\n} catch (FailedLoginException e) {\n    if (e.getMessage().contains(\"status 4\")) {\n        LOGGER.error(\"Graph auth/client error — check Azure AD app registration: {}\", e.getMessage());\n    }\n    throw e;\n}","preventionTips":["Grant and renew admin consent for Graph permissions on the app registration.","Rotate client secrets before expiry and keep tenant/base-URL settings correct.","Monitor Graph status codes (429/5xx) and add backoff retry for transient failures.","Test with curl + a manually obtained token before deploying config changes."],"tags":["azure-ad","microsoft-graph","http","authentication"],"backgroundTag":"http-error-response","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}