@Override
    public byte[] evaluateResponse(byte[] response) throws SaslException, SaslAuthenticationException {
        try {
            switch (state) {
                case RECEIVE_CLIENT_FIRST_MESSAGE:
                    this.clientFirstMessage = new ClientFirstMessage(response);
                    this.scramExtensions = clientFirstMessage.extensions();
                    if (!SUPPORTED_EXTENSIONS.containsAll(scramExtensions.map().keySet())) {
                        log.debug("Unsupported extensions will be ignored, supported {}, provided {}",
                                SUPPORTED_EXTENSIONS, scramExtensions.map().keySet());
                    }
                    String serverNonce = formatter.secureRandomString();
                    try {
                        String saslName = clientFirstMessage.saslName();
                        String username = ScramFormatter.username(saslName);
                        NameCallback nameCallback = new NameCallback("username", username);
                        ScramCredentialCallback credentialCallback;
                        if (scramExtensions.tokenAuthenticated()) {
                            DelegationTokenCredentialCallback tokenCallback = new DelegationTokenCredentialCallback();
                            credentialCallback = tokenCallback;
                            callbackHandler.handle(new Callback[]{nameCallback, tokenCallback});
                            if (tokenCallback.tokenOwner() == null)
                                throw new SaslException("Token Authentication failed: Invalid tokenId : " + username);
                            this.authorizationId = tokenCallback.tokenOwner();
                            this.tokenExpiryTimestamp = tokenCallback.tokenExpiryTimestamp();
                        } else {
                            credentialCallback = new ScramCredentialCallback();
                            callbackHandler.handle(new Callback[]{nameCallback, credentialCallback});
                            this.authorizationId = username;
                            this.tokenExpiryTimestamp = null;
                        }
                        this.scramCredential = credentialCallback.scramCredential();
                        if (scramCredential == null)
                            throw new SaslException("Authentication failed: Invalid user credentials");
                        String authorizationIdFromClient = clientFirstMessage.authorizationId();
                        if (!authorizationIdFromClient.isEmpty() && !authorizationIdFromClient.equals(username))
                            throw new SaslAuthenticationException("Authentication failed: Client requested an authorization id that is different from username");

                        if (scramCredential.iterations() < mechanism.minIterations())
                            throw new SaslException("Iterations " + scramCredential.iterations() +  " is less than the minimum " + mechanism.minIterations() + " for " + mechanism);
                        this.serverFirstMessage = new ServerFirstMessage(clientFirstMessage.nonce(),
                                serverNonce,
                                scramCredential.salt(),
                                scramCredential.iterations());
                        setState(State.RECEIVE_CLIENT_FINAL_MESSAGE);
                        return serverFirstMessage.toBytes();
                    } catch (SaslException | AuthenticationException e) {
                        throw e;
                    } catch (Throwable e) {
                        throw new SaslException("Authentication failed: Credentials could not be obtained", e);
                    }

                case RECEIVE_CLIENT_FINAL_MESSAGE:
                    try {
                        ClientFinalMessage clientFinalMessage = new ClientFinalMessage(response);
                        verifyClientProof(clientFinalMessage);
                        byte[] serverKey = scramCredential.serverKey();
                        byte[] serverSignature = formatter.serverSignature(serverKey, clientFirstMessage, serverFirstMessage, clientFinalMessage);
                        ServerFinalMessage serverFinalMessage = new ServerFinalMessage(null, serverSignature);
                        clearCredentials();
                        setState(State.COMPLETE);
                        return serverFinalMessage.toBytes();
                    } catch (InvalidKeyException e) {
                        throw new SaslException("Authentication failed: Invalid client final message", e);
                    }

                default:
                    throw new IllegalSaslStateException("Unexpected challenge in Sasl server state " + state);
            }
        } catch (SaslException | AuthenticationException e) {
            clearCredentials();
            setState(State.FAILED);
            throw e;
        }
    }
@throws SaslAuthenticationException if the requested authorization id is not the same as username.
<p>
<b>Note:</b> This method may throw {@link SaslAuthenticationException} to provide custom error messages
to clients. But care should be taken to avoid including any information in the exception message that
should not be leaked to unauthenticated clients. It may be safer to throw {@link SaslException} in
most cases so that a standard error message is returned to clients.
</p>
clients/src/main/java/org/apache/kafka/common/security/scram/internals/ScramSaslServer.java