@Override
    public Optional<Credentials> validate(final CallContext callContext, final Credentials credentials) {
        return FunctionUtils.doUnchecked(() -> {
            LOGGER.debug("Authenticating credential [{}]", credentials);
            val upc = (UsernamePasswordCredentials) credentials;
            val id = upc.getUsername();
            val registeredService = OAuth20Utils.getRegisteredOAuthServiceByClientId(servicesManager, id);
            val audit = AuditableContext.builder()
                .registeredService(registeredService)
                .build();
            val accessResult = registeredServiceAccessStrategyEnforcer.execute(audit);
            val proceed = !accessResult.isExecutionFailure() && canAuthenticate(callContext);
            if (!proceed) {
                val name = getClass().getSimpleName();
                LOGGER.debug("Skipping authenticator [{}]; service access is rejected for [{}] or the authentication request is not supported", name, registeredService);
                return Optional.empty();
            }

            val requiredAuthnMethod = CredentialSource.FORM.name().equalsIgnoreCase(upc.getSource())
                ? OAuth20ClientAuthenticationMethods.CLIENT_SECRET_POST
                : OAuth20ClientAuthenticationMethods.CLIENT_SECRET_BASIC;
            if (!isAuthenticationMethodSupported(callContext, registeredService, requiredAuthnMethod)) {
                LOGGER.warn("Client authentication method [{}] is not supported for service [{}]", requiredAuthnMethod, registeredService.getName());
                return Optional.empty();
            }

            validateCredentials(upc, registeredService, callContext);

            val credential = new OAuth20ClientIdClientSecretCredential(upc.getUsername(), upc.getPassword());
            val resolvedPrincipal = principalResolver.resolve(credential);

            val service = webApplicationServiceServiceFactory.createService(registeredService.getServiceId());
            val profile = new CommonProfile();
            if (resolvedPrincipal instanceof NullPrincipal) {
                LOGGER.debug("No principal was resolved. Falling back to the username [{}] from the credentials.", id);
                profile.setId(id);
            } else {
                val usernameContext = RegisteredServiceUsernameProviderContext.builder()
                    .registeredService(registeredService)
                    .service(service)
                    .principal(resolvedPrincipal)
                    .applicationContext(applicationContext)
                    .build();
                val username = registeredService.getUsernameAttributeProvider().resolveUsername(usernameContext);
                profile.setId(username);
            }
            profile.addAttribute(OAuth20Constants.CLIENT_ID, id);
            LOGGER.debug("Created profile id [{}]", profile.getId());

            val principal = buildAuthenticatedPrincipal(resolvedPrincipal, registeredService, service, callContext);
            profile.addAttributes((Map) principal.getAttributes());

            LOGGER.debug("Authenticated user profile [{}]", profile);
            credentials.setUserProfile(profile);
            return Optional.of(credentials);
        });
    }
Authenticator for client credentials authentication.

@author Jerome Leleu
@since 5.0.0
support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/authenticator/OAuth20ClientIdClientSecretAuthenticator.java