diff --git a/CHANGES b/CHANGES
index 67ba406e8e71022758f08c87ecefcd5354e538a8..07879f88732da2c6a5c51d1e10865fcd27cc6b88 100644
--- a/CHANGES
+++ b/CHANGES
@@ -28,6 +28,7 @@ OpenLDAP 2.4.22 Engineering
 	Fixed slapo-accesslog to not replicate internal purges (ITS#6519)
 	Fixed slapd-bdb contextCSN updates from updatedn (ITS#6469)
 	Fixed slapd-bdb lockobj zeroing (ITS#6501)
+	Fixed slapd-ldap/meta control criticality (ITS#6523)
 	Fixed slapd-ldap/meta with ordered values (ITS#6516)
 	Fixed slapo-collect REP_ENTRY flag handling (ITS#5340,ITS#6423)
 	Fixed slapo-dds with NULL backend (ITS#6490)
diff --git a/doc/man/man5/slapd-ldap.5 b/doc/man/man5/slapd-ldap.5
index 1168e542dae3dcbae39e4aab8f29adb4212481a5..db77e7733d6a025aa7441a16a57d9833f540411e 100644
--- a/doc/man/man5/slapd-ldap.5
+++ b/doc/man/man5/slapd-ldap.5
@@ -341,7 +341,7 @@ useful when the asserted identities do not exist on the remote server.
 
 Flags can be
 
-\fBoverride,[non\-]prescriptive\fP
+\fBoverride,[non\-]prescriptive,proxy\-authz\-[non\-]critical\fP
 
 When the 
 .B override
@@ -365,6 +365,13 @@ whose assertion is not allowed by the
 .B idassert\-authzFrom
 patterns.
 
+When the
+.B proxy\-authz\-non\-critical
+flag is used (the default), the proxyAuthz control is not marked as critical,
+in violation of RFC 4370.  Use of
+.B proxy\-authz\-critical
+is recommended.
+
 The TLS settings default to the same as the main slapd TLS settings,
 except for
 .B tls_reqcert
diff --git a/doc/man/man5/slapd-meta.5 b/doc/man/man5/slapd-meta.5
index b15c9652d38812480f5597dc52bef30079653a63..92a694ea72c059fb6b658545bd90d4487354afbf 100644
--- a/doc/man/man5/slapd-meta.5
+++ b/doc/man/man5/slapd-meta.5
@@ -464,7 +464,7 @@ useful when the asserted identities do not exist on the remote server.
 
 Flags can be
 
-\fBoverride,[non\-]prescriptive\fP
+\fBoverride,[non\-]prescriptive,proxy\-authz\-[non\-]critical\fP
 
 When the 
 .B override
@@ -488,6 +488,13 @@ whose assertion is not allowed by the
 .B idassert\-authzFrom
 patterns.
 
+When the
+.B proxy\-authz\-non\-critical
+flag is used (the default), the proxyAuthz control is not marked as critical,
+in violation of RFC 4370.  Use of
+.B proxy\-authz\-critical
+is recommended.
+
 The TLS settings default to the same as the main slapd TLS settings,
 except for
 .B tls_reqcert
diff --git a/servers/slapd/back-ldap/back-ldap.h b/servers/slapd/back-ldap/back-ldap.h
index 21760bfbfe537d0f113f9081939e4ba63b16c21f..244e5e8e811ab966e0c721381e1e91d20bcce821 100644
--- a/servers/slapd/back-ldap/back-ldap.h
+++ b/servers/slapd/back-ldap/back-ldap.h
@@ -234,6 +234,7 @@ typedef struct slap_idassert_t {
 #define	LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ		(0x08U)
 #define	LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND	(0x10U)
 #define	LDAP_BACK_AUTH_AUTHZ_ALL			(0x20U)
+#define	LDAP_BACK_AUTH_PROXYAUTHZ_CRITICAL		(0x40U)
 #define	li_idassert_flags	li_idassert.si_flags
 
 	BerVarray	si_authz;
diff --git a/servers/slapd/back-ldap/bind.c b/servers/slapd/back-ldap/bind.c
index 916c0c6820b240bf54ae8a7a4b7ae44951f1d25b..36f3caf1236300ee066129f802e21871fbaec22f 100644
--- a/servers/slapd/back-ldap/bind.c
+++ b/servers/slapd/back-ldap/bind.c
@@ -1298,6 +1298,7 @@ ldap_back_dobind_int(
 	ber_int_t	msgid;
 	ber_tag_t	o_tag = op->o_tag;
 	slap_callback cb = {0};
+	char		*tmp_dn;
 
 	assert( lcp != NULL );
 	assert( retries >= 0 );
@@ -1462,8 +1463,18 @@ retry_lock:;
 #endif /* HAVE_CYRUS_SASL */
 
 retry:;
+	if ( BER_BVISNULL( &lc->lc_cred ) ) {
+		tmp_dn = "";
+		if ( !BER_BVISNULL( &lc->lc_bound_ndn ) && !BER_BVISEMPTY( &lc->lc_bound_ndn ) ) {
+			Debug( LDAP_DEBUG_ANY, "%s ldap_back_dobind_int: DN=\"%s\" without creds, binding anonymously",
+				op->o_log_prefix, lc->lc_bound_ndn.bv_val, 0 );
+		}
+
+	} else {
+		tmp_dn = lc->lc_bound_ndn.bv_val;
+	}
 	rs->sr_err = ldap_sasl_bind( lc->lc_ld,
-			BER_BVISNULL( &lc->lc_cred ) ? "" : lc->lc_bound_ndn.bv_val,
+			tmp_dn,
 			LDAP_SASL_SIMPLE, &lc->lc_cred,
 			NULL, NULL, &msgid );
 
@@ -2487,6 +2498,7 @@ ldap_back_proxy_authz_ctrl(
 	}
 
 	ctrl->ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
+	ctrl->ldctl_iscritical = ( ( si->si_flags & LDAP_BACK_AUTH_PROXYAUTHZ_CRITICAL ) == LDAP_BACK_AUTH_PROXYAUTHZ_CRITICAL );
 
 	switch ( si->si_mode ) {
 	/* already in u:ID or dn:DN form */
diff --git a/servers/slapd/back-ldap/config.c b/servers/slapd/back-ldap/config.c
index 502ea27b6341695e38d80fd0fb44a46e45d0c14b..7b5cb291f134f8768501112831a71a001dc7e5f2 100644
--- a/servers/slapd/back-ldap/config.c
+++ b/servers/slapd/back-ldap/config.c
@@ -863,6 +863,12 @@ slap_idassert_parse( ConfigArgs *c, slap_idassert_t *si )
 						si->si_flags |= LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND;
 					}
 
+				} else if ( strcasecmp( flags[ j ], "proxy-authz-critical" ) == 0 ) {
+					si->si_flags |= LDAP_BACK_AUTH_PROXYAUTHZ_CRITICAL;
+
+				} else if ( strcasecmp( flags[ j ], "proxy-authz-non-critical" ) == 0 ) {
+					si->si_flags &= ~LDAP_BACK_AUTH_PROXYAUTHZ_CRITICAL;
+
 				} else {
 					snprintf( c->cr_msg, sizeof( c->cr_msg ),
 						"\"idassert-bind <args>\": "
@@ -1137,7 +1143,7 @@ ldap_back_cf_gen( ConfigArgs *c )
 					(void)lutil_strcopy( ptr, "authz=native" );
 				}
 
-				len = bv.bv_len + STRLENOF( "flags=non-prescriptive,override,obsolete-encoding-workaround" );
+				len = bv.bv_len + STRLENOF( "flags=non-prescriptive,override,obsolete-encoding-workaround,proxy-authz-non-critical" );
 				/* flags */
 				if ( !BER_BVISEMPTY( &bv ) ) {
 					len += STRLENOF( " " );
@@ -1170,6 +1176,13 @@ ldap_back_cf_gen( ConfigArgs *c )
 					ptr = lutil_strcopy( ptr, ",obsolete-encoding-workaround" );
 				}
 
+				if ( li->li_idassert_flags & LDAP_BACK_AUTH_PROXYAUTHZ_CRITICAL ) {
+					ptr = lutil_strcopy( ptr, ",proxy-authz-critical" );
+
+				} else {
+					ptr = lutil_strcopy( ptr, ",proxy-authz-non-critical" );
+				}
+
 				bv.bv_len = ( ptr - bv.bv_val );
 				/* end-of-flags */
 			}
@@ -1452,6 +1465,7 @@ ldap_back_cf_gen( ConfigArgs *c )
 
 		case LDAP_BACK_CFG_IDASSERT_BIND:
 			bindconf_free( &li->li_idassert.si_bc );
+			memset( &li->li_idassert, 0, sizeof( slap_idassert_t ) );
 			break;
 
 		case LDAP_BACK_CFG_REBIND: