apereo/cas · error · BadRestRequestException
No credentials are provided or extracted to authenticate…
Error message
No credentials are provided or extracted to authenticate the REST request
What it means
Thrown as BadRestRequestException when the renew=true path of the REST service-ticket endpoint cannot extract any credential from the request. With renew enabled, CAS requires fresh credentials in the request body (username/password or similar); if credentialFactory.fromRequest returns null or an empty collection the request is rejected.
Solutions
- Include valid credentials in the request body (e.g. username=...&password=... form data) when using renew=true.
- Remove the renew parameter if re-authentication is not actually required (the existing TGT authentication will be reused).
- Ensure Content-Type is application/x-www-form-urlencoded (or as expected by the configured credential factory) so the body is parsed.
- Verify a REST credential factory bean is registered that supports the credential type being sent.
Example fix
// before curl -X POST 'https://cas/v1/tickets/TGT-1-abc/service?renew=true' -d 'service=https://app' // after curl -X POST 'https://cas/v1/tickets/TGT-1-abc/service?renew=true' -d 'service=https://app' -d 'username=casuser' -d 'password=mypassword'
Defensive patterns
Strategy: validation
Validate before calling
// Before sending a renew=true request, ensure credentials are attached:
if (renew && (username == null || username.isBlank() || password == null || password.isBlank())) {
throw new IllegalArgumentException("renew=true requires username/password in the request body");
} Try / catch
try { requestServiceTicket(tgtId, service, renew, creds); }
catch (BadRestRequestException e) {
// fall back to non-renew path or surface a clear credential-required error
requestServiceTicket(tgtId, service, false, null);
} Prevention
- Only add renew=true when fresh credentials will also be supplied.
- Send form-encoded bodies (application/x-www-form-urlencoded) the REST credential factory can parse.
- Keep a configured credential factory that supports the credential type used.
- Document required body parameters for renew flows in the client SDK.
When it happens
Trigger: Calling /v1/tickets/{tgtId}?renew=true (or PARAMETER_RENEW parameter) without supplying credentials in the request body; sending the body with wrong Content-Type so the credential factory cannot parse it; credential factory not configured to recognize the provided credential type.
Common situations: Developer adds renew=true to force re-authentication but reuses the old TGT-only request without body; client sends JSON instead of the form-encoded MultiValueMap the factory expects; custom credential factory missing from the REST configuration.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- No credentials can be extracted to authenticate the REST…
- Unable to extract credentials for multifactor authentication
- Unable to authenticate request to register service
- [ ] Caused by: [ ]
- Resolved credentials for this transaction are empty
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/9f3d0d7f5dd6c7d6.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/ServiceTicketResource.java:103
@Parameter(name = "tgtId", required = true, in = ParameterIn.PATH, description = "Ticket-granting ticket id"),
@Parameter(name = "requestBody", required = false, description = "Request body containing credentials")
})
public ResponseEntity<String> createServiceTicket(
final HttpServletRequest httpServletRequest,
@RequestBody(required = false)
final MultiValueMap<String, String> requestBody,
@PathVariable final String tgtId) {
try {
val authn = ticketRegistrySupport.getAuthenticationFrom(StringEscapeUtils.escapeHtml4(tgtId));
if (authn == null) {
throw new InvalidTicketException(tgtId);
}
val service = Objects.requireNonNull(argumentExtractor.extractService(httpServletRequest),
"Target service/application is unspecified or unrecognized in the request");
if (BooleanUtils.toBoolean(httpServletRequest.getParameter(CasProtocolConstants.PARAMETER_RENEW))) {
val credential = credentialFactory.fromRequest(httpServletRequest, requestBody);
if (credential == null || credential.isEmpty()) {
throw new BadRestRequestException("No credentials are provided or extracted to authenticate the REST request");
}
val authenticationResult = authenticationSystemSupport.finalizeAuthenticationTransaction(service, credential);
return serviceTicketResourceEntityResponseFactory.build(tgtId, service, Objects.requireNonNull(authenticationResult));
}
val builder = authenticationSystemSupport.getAuthenticationResultBuilderFactory().newBuilder();
val authenticationResult = builder.collect(authn).build(service);
return serviceTicketResourceEntityResponseFactory.build(tgtId, service, Objects.requireNonNull(authenticationResult));
} catch (final InvalidTicketException e) {
return new ResponseEntity<>(StringEscapeUtils.escapeHtml4(tgtId) + " could not be found or is considered invalid", HttpStatus.NOT_FOUND);
} catch (final AuthenticationException e) {
return RestResourceUtils.createResponseEntityForAuthnFailure(e, httpServletRequest, applicationContext);
} catch (final BadRestRequestException e) {
LoggingUtils.error(LOGGER, e);
return new ResponseEntity<>(StringEscapeUtils.escapeHtml4(e.getMessage()), HttpStatus.BAD_REQUEST);
} catch (final UnauthorizedServiceException e) {
LoggingUtils.error(LOGGER, e);
return new ResponseEntity<>(StringEscapeUtils.escapeHtml4(e.getMessage()), HttpStatus.FORBIDDEN);
} catch (final Throwable e) {View on GitHub (pinned to e7288fc434)