diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c
index 15c3857f573..d52a7634574 100644
--- a/src/backend/libpq/auth-scram.c
+++ b/src/backend/libpq/auth-scram.c
@@ -110,6 +110,7 @@ typedef struct
 
 	const char *username;		/* username from startup packet */
 
+	char		cbind_flag;
 	bool		ssl_in_use;
 	const char *tls_finished_message;
 	size_t		tls_finished_len;
@@ -788,6 +789,7 @@ read_client_first_message(scram_state *state, char *input)
 	 * Read gs2-cbind-flag.  (For details see also RFC 5802 Section 6 "Channel
 	 * Binding".)
 	 */
+	state->cbind_flag = *input;
 	switch (*input)
 	{
 		case 'n':
@@ -1111,6 +1113,8 @@ read_client_final_message(scram_state *state, char *input)
 		char	   *b64_message;
 		int			b64_message_len;
 
+		Assert(state->cbind_flag == 'p');
+
 		/*
 		 * Fetch data appropriate for channel binding type
 		 */
@@ -1155,10 +1159,11 @@ read_client_final_message(scram_state *state, char *input)
 		/*
 		 * If we are not using channel binding, the binding data is expected
 		 * to always be "biws", which is "n,," base64-encoded, or "eSws",
-		 * which is "y,,".
+		 * which is "y,,".  We also have to check whether the flag is the same
+		 * one that the client originally sent.
 		 */
-		if (strcmp(channel_binding, "biws") != 0 &&
-			strcmp(channel_binding, "eSws") != 0)
+		if (!(strcmp(channel_binding, "biws") == 0 && state->cbind_flag == 'n') &&
+			!(strcmp(channel_binding, "eSws") == 0 && state->cbind_flag == 'y'))
 			ereport(ERROR,
 					(errcode(ERRCODE_PROTOCOL_VIOLATION),
 					 (errmsg("unexpected SCRAM channel-binding attribute in client-final-message"))));
diff --git a/src/interfaces/libpq/fe-auth-scram.c b/src/interfaces/libpq/fe-auth-scram.c
index 97db0b1faa8..5b783bc3136 100644
--- a/src/interfaces/libpq/fe-auth-scram.c
+++ b/src/interfaces/libpq/fe-auth-scram.c
@@ -437,6 +437,10 @@ build_client_final_message(fe_scram_state *state, PQExpBuffer errormessage)
 	/*
 	 * Construct client-final-message-without-proof.  We need to remember it
 	 * for verifying the server proof in the final step of authentication.
+	 *
+	 * The channel binding flag handling (p/y/n) must be consistent with
+	 * build_client_first_message(), because the server will check that it's
+	 * the same flag both times.
 	 */
 	if (strcmp(state->sasl_mechanism, SCRAM_SHA256_PLUS_NAME) == 0)
 	{