apereo/cas · error · BadRestRequestException
No credentials can be extracted to authenticate the REST…
Error message
No credentials can be extracted to authenticate the REST request
What it means
The REST authentication endpoint could not produce any Credential from the incoming request. Credential extractors configured in the REST credential factory found nothing in the request body or headers, so no authentication transaction can start and BadRestRequestException is thrown (typically surfacing as HTTP 400).
Solutions
- Send credentials as application/x-www-form-urlencoded with 'username' and 'password' fields to POST /cas/v1/tickets.
- Verify the Content-Type header matches what the configured credential extractor expects.
- If using header-based auth (basic/bearer/token), confirm the corresponding CAS REST support module and extractor are on the classpath and enabled.
- Check the factory configuration for custom RestCredentialFactory beans and confirm the parameter names it expects match the client's payload.
- Inspect cas-server logs at debug level to see which extractors ran and rejected the body.
Example fix
// before: JSON body not understood by form extractor
curl -X POST https://cas/cas/v1/tickets -H 'Content-Type: application/json' -d '{"username":"u","password":"p"}'
// after: form-encoded credentials
curl -X POST https://cas/cas/v1/tickets -H 'Content-Type: application/x-www-form-urlencoded' -d 'username=u&password=p' Defensive patterns
Strategy: validation
Validate before calling
if (body == null || body.isEmpty() ||
!body.containsKey("username") || !body.containsKey("password")) {
// fix payload before calling authenticate
} Try / catch
try {
Optional<AuthenticationResult> r = restAuthenticationService.authenticate(body, req, res);
} catch (BadRestRequestException e) {
// return HTTP 400 with e.getMessage()
} Prevention
- Always POST form-encoded username/password (or the extractor's expected fields) to /v1/tickets.
- Set Content-Type explicitly in REST clients.
- Confirm the credential-extractor modules you rely on are on the classpath.
- Log the outbound payload once during integration to verify field names.
When it happens
Trigger: POSTing to /v1/tickets (or the REST authentication API) with a body that no registered RestCredentialFactory understands — e.g. missing 'username'/'password' form fields, wrong Content-Type (JSON instead of application/x-www-form-urlencoded when only form extraction is configured), empty body, or missing bearer/basic header for header-based extraction.
Common situations: Clients sending JSON to an endpoint that only parses form parameters; forgetting to add a credential extractor module (e.g. custom token extractor) so the factory returns an empty list; typos in parameter names (user vs username); proxies consuming the body before CAS sees it.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Unable to accept response status
- Unable to extract credentials for multifactor authentication
- No credentials are provided or extracted to authenticate…
- [ ] Caused by: [ ]
- Resolved credentials for this transaction are empty
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/7d579facbcb55791.
Report an issue: GitHub.
Appendix: source
Thrown at core/cas-server-core-rest-api/src/main/java/org/apereo/cas/rest/authentication/DefaultRestAuthenticationService.java:57
private final ServiceFactory<WebApplicationService> serviceFactory;
private final MultifactorAuthenticationTriggerSelectionStrategy multifactorTriggerSelectionStrategy;
private final ServicesManager servicesManager;
private final RequestedAuthenticationContextValidator requestedContextValidator;
private final AuthenticationPolicy restAuthenticationPolicy;
private final ConfigurableApplicationContext applicationContext;
@Override
public Optional<AuthenticationResult> authenticate(final MultiValueMap<String, String> requestBody,
final HttpServletRequest request, final HttpServletResponse response) throws Throwable {
val credentials = credentialFactory.fromRequest(request, requestBody);
if (credentials == null || credentials.isEmpty()) {
throw new BadRestRequestException("No credentials can be extracted to authenticate the REST request");
}
val service = serviceFactory.createService(request);
val registeredService = servicesManager.findServiceBy(service);
val authResult = Optional.ofNullable(
authenticationSystemSupport.handleInitialAuthenticationTransaction(service, credentials.toArray(Credential[]::new)));
return authResult
.map(result -> result.getInitialAuthentication()
.filter(Unchecked.predicate(authn -> restAuthenticationPolicy.isSatisfiedBy(authn, applicationContext).isSuccess()))
.filter(Unchecked.predicate(authn -> {
val validationResult = requestedContextValidator.validateAuthenticationContext(request, response, registeredService, authn, service);
return !validationResult.isSuccess();
}))
.map(Unchecked.function(authn -> multifactorTriggerSelectionStrategy.resolve(request, response, registeredService, authn, service)
.map(Unchecked.function(provider -> {
LOGGER.debug("Extracting credentials for multifactor authentication via [{}]", provider);
val authnCredentials = credentialFactory.fromAuthentication(request, requestBody, authn, provider);
if (authnCredentials == null || authnCredentials.isEmpty()) {View on GitHub (pinned to e7288fc434)