@Override
    protected void validateCredentials(final UsernamePasswordCredentials credentials,
                                       final OAuthRegisteredService registeredService,
                                       final CallContext callContext) {
        val token = credentials.getPassword();
        LOGGER.trace("Received refresh token [{}] for authentication", token);

        val refreshToken = FunctionUtils.doAndHandle(() -> {
            val state = getTicketRegistry().getTicket(token, OAuth20RefreshToken.class);
            return state == null || state.isExpired() ? null : state;
        });
        val clientId = credentials.getUsername();
        if (refreshToken == null || refreshToken.isExpired() || !StringUtils.equals(refreshToken.getClientId(), clientId)) {
            LOGGER.error("Refresh token [{}] is either not found in the ticket registry, has expired or does not belong to the client [{}]", token, clientId);
            throw new CredentialsException("Invalid token: " + token);
        }
    }
This is {@link OAuth20RefreshTokenAuthenticator}.
<p>
{@link OAuth20RefreshTokenAuthenticator} can only be used for a refresh token request of a "public" client.
An OAuth "public" client is one that does not define a secret like a mobile application.

@author Julien Huon
@since 6.2.0
support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/authenticator/OAuth20RefreshTokenAuthenticator.java