diff --git includes/core/actions.php includes/core/actions.php
index b6046e4..b79814e 100644
--- includes/core/actions.php
+++ includes/core/actions.php
@@ -246,7 +246,7 @@ add_action( 'make_ham_user',  'bbp_make_ham_user'  );
 add_action( 'make_spam_user', 'bbp_make_spam_user' );
 
 // User role
-add_action( 'bbp_profile_update', 'bbp_profile_update_role' );
+add_action( 'bbp_profile_update', 'bbp_profile_update_role', 10, 2 );
 
 // Hook WordPress admin actions to bbPress profiles on save
 add_action( 'bbp_user_edit_after', 'bbp_user_edit_after' );
@@ -303,4 +303,4 @@ add_action( 'bbp_get_request', 'bbp_search_results_redirect',     10 );
 // Maybe convert the users password
 add_action( 'bbp_login_form_login', 'bbp_user_maybe_convert_pass' );
 
-add_action( 'bbp_activation', 'bbp_add_activation_redirect' );
\ No newline at end of file
+add_action( 'bbp_activation', 'bbp_add_activation_redirect' );
diff --git includes/users/capabilities.php includes/users/capabilities.php
index 77c5e41..2cb116a 100644
--- includes/users/capabilities.php
+++ includes/users/capabilities.php
@@ -50,12 +50,17 @@ function bbp_map_primary_meta_caps( $caps = array(), $cap = '', $user_id = 0, $a
  * @since bbPress (r3860)
  *
  * @param int $user_id
+ * @param string $new_role
+ * @param string $old_role
  * @uses bbp_get_user_id() To get the user id
  * @uses get_userdata() To get the user data
  * @uses apply_filters() Calls 'bbp_set_user_role' with the role and user id
  * @return string
  */
-function bbp_set_user_role( $user_id = 0, $new_role = '' ) {
+function bbp_set_user_role( $user_id = 0, $new_role = '', $old_role = '' ) {
+
+	$forum_role = bbp_get_user_role( $user_id );
+	$old_role = $forum_role ?: $old_role;
 
 	// Validate user id
 	$user_id = bbp_get_user_id( $user_id, false, false );
@@ -64,19 +69,28 @@ function bbp_set_user_role( $user_id = 0, $new_role = '' ) {
 	// User exists
 	if ( !empty( $user ) ) {
 
-		// Get users forum role
-		$role = bbp_get_user_role( $user_id );
+		$blocked_role = bbp_get_blocked_role();
+
+		// Prevent blocked users from logging in, which also invalidates their sessions
+		if ( $blocked_role === $new_role ) {
+			bbp_break_password( $user_id, $user->data->user_pass );
+			// Allow a previously blocked user to login
+		} elseif ( $blocked_role === $old_role ) {
+			bbp_fix_password( $user_id, $user->data->user_pass );
+		}
+
+		// When a user is edited, Wordpress removes the custom role. If no change was
+		// made to the role, we'll re-add it
+		if ( $new_role === $old_role ) {
 
-		// User already has this role so no new role is set
-		if ( $new_role === $role ) {
-			$new_role = false;
+			$user->add_role($old_role);
 
-		// Users role is different than the new role
+		// User's role is different than the new role
 		} else {
 
-			// Remove the old role
-			if ( ! empty( $role ) ) {
-				$user->remove_role( $role );
+			// Remove the old role if there is one
+			if ( !empty($old_role) ) {
+				$user->remove_role( $old_role );
 			}
 
 			// Add the new role
@@ -97,22 +111,60 @@ function bbp_set_user_role( $user_id = 0, $new_role = '' ) {
 	return apply_filters( 'bbp_set_user_role', $new_role, $user_id, $user );
 }
 
+function bbp_password_broken( $user_pass ) {
+	return '_' === $user_pass[0];
+}
+
+function bbp_break_password( $user_id, $user_pass ) {
+	global $wpdb;
+
+	if ( !bbp_password_broken( $user_pass ) ) {
+
+		$wpdb->update(
+			$wpdb->users,
+			// Prefixing an underscore makes the hash invalid
+			array( 'user_pass' => "_{$user_pass}" ),
+			array( 'ID' => $user_id )
+		);
+
+		clean_user_cache( $user_id );
+
+	}
+}
+
+function bbp_fix_password( $user_id, $user_pass ) {
+	global $wpdb;
+
+	if ( bbp_password_broken( $user_pass ) ) {
+
+		$wpdb->update(
+			$wpdb->users,
+			array( 'user_pass' => substr( $user_pass, 1 )  ),
+			array( 'ID' => $user_id )
+		);
+
+		clean_user_cache( $user_id );
+
+	}
+}
+
 /**
  * Return a user's forums role
  *
  * @since bbPress (r3860)
  *
  * @param int $user_id
+ * @param WP_User|null $user
  * @uses bbp_get_user_id() To get the user id
  * @uses get_userdata() To get the user data
  * @uses apply_filters() Calls 'bbp_get_user_role' with the role and user id
  * @return string
  */
-function bbp_get_user_role( $user_id = 0 ) {
+function bbp_get_user_role( $user_id = 0, $user = null ) {
 
 	// Validate user id
 	$user_id = bbp_get_user_id( $user_id );
-	$user    = get_userdata( $user_id );
+	$user    = $user === null ? get_userdata( $user_id ) : $user;
 	$role    = false;
 
 	// User has roles so look for a bbPress one
@@ -183,26 +235,27 @@ function bbp_get_user_blog_role( $user_id = 0 ) {
  * @since bbPress (r4235)
  *
  * @param int $user_id
+ * @param WP_User|null $old_user
  * @uses bbp_reset_user_caps() to reset caps
  * @usse bbp_save_user_caps() to save caps
  */
-function bbp_profile_update_role( $user_id = 0 ) {
+function bbp_profile_update_role( $user_id = 0, $old_user = null ) {
 
 	// Bail if no user ID was passed
 	if ( empty( $user_id ) )
 		return;
 
+	// Bail if no old user data was passed
+	if ( null === $old_user )
+		return;
+
 	// Bail if no role
 	if ( ! isset( $_POST['bbp-forums-role'] ) )
 		return;
 
-	// Fromus role we want the user to have
+	// Forums role we want the user to have
 	$new_role    = sanitize_text_field( $_POST['bbp-forums-role'] );
-	$forums_role = bbp_get_user_role( $user_id );
-
-	// Bail if no role change
-	if ( $new_role === $forums_role )
-		return;
+	$forums_role = bbp_get_user_role( $user_id, $old_user );
 
 	// Bail if trying to set their own role
 	if ( bbp_is_user_home_edit() )
@@ -213,7 +266,7 @@ function bbp_profile_update_role( $user_id = 0 ) {
 		return;
 
 	// Set the new forums role
-	bbp_set_user_role( $user_id, $new_role );
+	bbp_set_user_role( $user_id, $new_role, $forums_role );
 }
 
 /**
