{"record":{"id":"c1a331fe8ce47a7f","repo":"apereo/cas","slug":"private-key-jwt-authentication-method-is-not-enabl","errorCode":null,"errorMessage":"Private key JWT authentication method is not enabled for CAS, or is not supported for service [{}]","messagePattern":"Private key JWT authentication method is not enabled for CAS, or is not supported for service \\[(.+?)\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/authn/OidcJwtAuthenticator.java","lineNumber":118,"sourceCode":"        return null;\n    }\n\n\n    @Override\n    public Optional<Credentials> validate(final CallContext callContext, final Credentials creds) {\n        return FunctionUtils.doAndHandle(() -> {\n            val registeredService = getOidcRegisteredService(callContext);\n            RegisteredServiceAccessStrategyUtils.ensureServiceAccessIsAllowed(registeredService);\n            Objects.requireNonNull(registeredService, \"regisetered service is null\");\n\n            if (OAuth20Utils.isAccessTokenRequest(callContext.webContext())) {\n                val authMethodDisabled = oidcServerDiscoverySettings.getTokenEndpointAuthMethodsSupported()\n                    .stream()\n                    .map(OAuth20ClientAuthenticationMethods::parse)\n                    .noneMatch(method -> method == OAuth20ClientAuthenticationMethods.CLIENT_SECRET_JWT || method == OAuth20ClientAuthenticationMethods.PRIVATE_KEY_JWT);\n                if (authMethodDisabled || !OAuth20Utils.isTokenAuthenticationMethodSupportedFor(callContext, registeredService,\n                    OAuth20ClientAuthenticationMethods.CLIENT_SECRET_JWT, OAuth20ClientAuthenticationMethods.PRIVATE_KEY_JWT)) {\n                    LOGGER.warn(\"Private key JWT authentication method is not enabled for CAS, or is not supported for service [{}]\", registeredService.getName());\n                    return Optional.<Credentials>empty();\n                }\n            }\n\n            val credentials = (UsernamePasswordCredentials) creds;\n            val jwt = verifyCredentials(credentials, callContext.webContext());\n            if (jwt == null) {\n                LOGGER.warn(\"Unable to verify credentials\");\n                return Optional.<Credentials>empty();\n            }\n\n            val keys = new JsonWebKeySet();\n            clientJwksRegistrationStore.ifAvailable(Unchecked.consumer(store -> {\n                if (jwt instanceof final SignedJWT signedJWT) {\n                    val jwk = signedJWT.getHeader().getJWK();\n                    val kid = signedJWT.getHeader().getKeyID();\n                    val jkt = jwk != null ? jwk.computeThumbprint().toString() : StringUtils.EMPTY;\n                    store.findBy(registeredService.getClientId(), jkt)","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/authn/OidcJwtAuthenticator.java#L100-L136","documentation":"CAS's OIDC JWT authenticator (used for client authentication at the token endpoint via client_secret_jwt / private_key_jwt) first checks that the server discovery document advertises these JWT auth methods and that the specific registered service allows one of them. If either fails, it refuses the credentials and returns empty, logging this warning.","triggerScenarios":"A client authenticates to the OIDC token endpoint using client_secret_jwt or private_key_jwt while either cas.authn.oidc.discovery.tokenEndpointAuthMethodsSupported excludes both JWT methods, or the registered service's tokenEndpointAuthenticationMethod is set to something else so OAuth20Utils.isTokenAuthenticationMethodSupportedFor fails.","commonSituations":"Client SDK defaults to private_key_jwt but the service registration says client_secret_basic; deployment overrode the discovery supported-auth-methods list; service JSON copied from another client with a different authentication method.","solutions":["Set the registered service's tokenEndpointAuthenticationMethod to client_secret_jwt or private_key_json (private_key_jwt) for that client.","Ensure cas.authn.oidc.discovery.token-endpoint-auth-methods-supported includes client_secret_jwt and/or private_key_jwt.","If JWT auth is intentionally disabled, switch the client SDK to client_secret_basic or client_secret_post instead.","Reload/restart after changing service registration so ServicesManager picks up the new auth method."],"exampleFix":"// before (service JSON)\n\"tokenEndpointAuthenticationMethod\": \"client_secret_basic\"\n// after\n\"tokenEndpointAuthenticationMethod\": \"private_key_json\"","handlingStrategy":"validation","validationCode":"// fetch discovery and check supported auth methods before using JWT auth\nconst disco = await fetch(`${issuer}/.well-known/openid-configuration`).then(r => r.json());\nif (!disco.token_endpoint_auth_methods_supported?.some(m => m.endsWith('_jwt')))\n  throw new Error('JWT client auth not supported by this CAS deployment');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Align the service registration's tokenEndpointAuthenticationMethod with the client SDK's setting.","Check discovery metadata when configuring clients.","Keep discovery tokenEndpointAuthMethodsSupported defaults unless intentionally restricting."],"tags":["oidc","jwt","client-authentication","configuration"],"backgroundTag":"feature-not-enabled","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"}