{"record":{"id":"3017e2076ff94dee","repo":"apereo/cas","slug":"invalid-proxy-callback","errorCode":"INVALID_PROXY_CALLBACK","errorMessage":"Failed to authenticate service credential [{}]","messagePattern":"Failed to authenticate service credential \\[(.+?)\\]","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"support/cas-server-support-validation-core/src/main/java/org/apereo/cas/web/AbstractServiceValidateController.java","lineNumber":170,"sourceCode":"    protected void initBinder(final HttpServletRequest request, final ServletRequestDataBinder binder) {\n        if (serviceValidateConfigurationContext.getCasProperties().getSso().isRenewAuthnEnabled()) {\n            binder.setRequiredFields(CasProtocolConstants.PARAMETER_RENEW);\n        }\n    }\n\n    protected void prepareForTicketValidation(final HttpServletRequest request, final WebApplicationService service, final String serviceTicketId) {\n    }\n\n    protected ModelAndView handleTicketValidation(final HttpServletRequest request,\n                                                  final HttpServletResponse response,\n                                                  final WebApplicationService service, final String serviceTicketId) throws Throwable {\n        var proxyGrantingTicket = (Ticket) null;\n        val serviceCredential = getServiceCredentialsFromRequest(service, request);\n        if (serviceCredential != null) {\n            try {\n                proxyGrantingTicket = handleProxyGrantingTicketDelivery(serviceTicketId, serviceCredential);\n            } catch (final AuthenticationException e) {\n                LOGGER.warn(\"Failed to authenticate service credential [{}]\", serviceCredential);\n                val description = getTicketValidationErrorDescription(CasProtocolConstants.ERROR_CODE_INVALID_PROXY_CALLBACK,\n                    new Object[]{serviceCredential.getId()}, request);\n                return generateErrorView(CasProtocolConstants.ERROR_CODE_INVALID_PROXY_CALLBACK, description, request, service);\n            } catch (final InvalidTicketException e) {\n                LOGGER.error(\"Failed to create proxy granting ticket due to an invalid ticket for [{}]\", serviceCredential);\n                LoggingUtils.error(LOGGER, e);\n                val description = getTicketValidationErrorDescription(e.getCode(), new Object[]{serviceTicketId}, request);\n                return generateErrorView(e.getCode(), description, request, service);\n            } catch (final AbstractTicketException e) {\n                LOGGER.error(\"Failed to create proxy granting ticket for [{}]\", serviceCredential);\n                LoggingUtils.error(LOGGER, e);\n                val description = getTicketValidationErrorDescription(e.getCode(), new Object[]{serviceCredential.getId()}, request);\n                return generateErrorView(e.getCode(), description, request, service);\n            }\n        }\n        val assertion = validateServiceTicket(service, serviceTicketId);\n        if (!validateAssertion(request, serviceTicketId, assertion, service)) {\n            val description = getTicketValidationErrorDescription(CasProtocolConstants.ERROR_CODE_INVALID_TICKET, new Object[]{serviceTicketId}, request);","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-validation-core/src/main/java/org/apereo/cas/web/AbstractServiceValidateController.java#L152-L188","documentation":"During proxy ticket validation, CAS extracted a service credential (e.g. a PGT callback's proxy credentials) from the request but failed to authenticate it, so handleTicketValidation catches AuthenticationException and returns an INVALID_PROXY_CALLBACK error view. The proxy callback chain could not be completed.","triggerScenarios":"handleTicketValidation calls getServiceCredentialsFromRequest (with pgtUrl callback processing enabled), gets a non-null credential, then handleProxyGrantingTicketDelivery authenticates it; the thrown AuthenticationException triggers the warn and the INVALID_PROXY_CALLBACK error response.","commonSituations":"pgtUrl points to an endpoint whose client certificate/credentials fail authentication; custom credential-to-handler setup mismatched; proxy callback URL unreachable or returning unexpected content causing the auth flow to fail.","solutions":["Verify the pgtUrl/proxy callback endpoint is reachable over HTTPS and presents valid credentials; test the callback URL manually.","Check the CAS log for the underlying AuthenticationException detail to identify which authentication handler rejected the service credential.","Remove the pgtUrl parameter if proxy authentication is not actually needed, so no service credential is extracted and authenticated."],"exampleFix":"// before\nGET /p3/proxyValidate?ticket=PT-1-abc&pgtUrl=https://myapp.example.org/callback-bad\n\n// after (valid, reachable callback or none)\nGET /p3/proxyValidate?ticket=PT-1-abc&pgtUrl=https://myapp.example.org/pgtCallback","handlingStrategy":"try-catch","validationCode":"// before requesting proxy tickets, verify pgtUrl is reachable and TLS-valid\nconst resp = await fetch(pgtUrl, { method: 'HEAD' });\nif (!resp.ok) throw new Error('pgtUrl callback is not reachable: ' + pgtUrl);","typeGuard":null,"tryCatchPattern":"try {\n    proxyGrantingTicket = handleProxyGrantingTicketDelivery(serviceTicketId, credential);\n} catch (AuthenticationException e) {\n    // INVALID_PROXY_CALLBACK: fix/verify pgtUrl credentials and reachability\n}","preventionTips":["Use HTTPS pgtUrls with valid certificates that CAS trusts.","Test the proxy callback endpoint independently before wiring it into ticket validation.","Omit pgtUrl when proxy authentication is not required."],"tags":["proxy-authentication","cas-protocol","credentials","ticket-validation"],"backgroundTag":"authentication-required","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"}