diff --git a/subsys/zigbee/lib/zigbee_app_utils/zigbee_app_utils.c b/subsys/zigbee/lib/zigbee_app_utils/zigbee_app_utils.c
index d88b3ee99..e8378d1ee 100644
--- a/subsys/zigbee/lib/zigbee_app_utils/zigbee_app_utils.c
+++ b/subsys/zigbee/lib/zigbee_app_utils/zigbee_app_utils.c
@@ -30,6 +30,10 @@
 /* Maximum interval between join/rejoin attempts. */
 #define REJOIN_INTERVAL_MAX_S    (15 * 60)
 
+/* Rejoin interval, after which the device will perform TC rejoin instead of a secure rejoin. */
+#define TC_REJOIN_INTERVAL_THRESHOLD_S (3)
+#define ZB_SECUR_PROVISIONAL_KEY 2
+
 #define IEEE_ADDR_BUF_SIZE       17
 
 #if defined CONFIG_ZIGBEE_FACTORY_RESET
@@ -53,6 +57,7 @@ static volatile bool is_rejoin_start_scheduled;
 static void rejoin_the_network(zb_uint8_t param);
 static void start_network_rejoin(void);
 static void stop_network_rejoin(zb_uint8_t was_scheduled);
+void zb_nwk_forget_device(zb_uint8_t addr_ref);
 
 
 #if defined CONFIG_ZIGBEE_FACTORY_RESET
@@ -489,6 +494,7 @@ zb_ret_t zigbee_default_signal_handler(zb_bufid_t bufid)
 				zb_zdo_signal_device_update_params_t);
 		char ieee_addr_buf[IEEE_ADDR_BUF_SIZE] = { 0 };
 		int addr_len;
+		zb_address_ieee_ref_t addr_ref;
 
 		addr_len = ieee_addr_to_str(ieee_addr_buf,
 					    sizeof(ieee_addr_buf),
@@ -500,6 +506,11 @@ zb_ret_t zigbee_default_signal_handler(zb_bufid_t bufid)
 			update_params->short_addr,
 			log_strdup(ieee_addr_buf),
 			update_params->status);
+
+		if ((zb_address_by_ieee(update_params->long_addr, ZB_FALSE, ZB_FALSE, &addr_ref) == RET_OK)
+			&& (zb_secur_get_link_key_by_address(update_params->long_addr, ZB_SECUR_PROVISIONAL_KEY) != NULL)) {
+			ZB_SCHEDULE_APP_ALARM_CANCEL(zb_nwk_forget_device, addr_ref);
+		}
 		break;
 	}
 
@@ -623,6 +634,52 @@ zb_ret_t zigbee_default_signal_handler(zb_bufid_t bufid)
 		/* Obsolete signals, used for pre-R21 ZBOSS API. Ignore. */
 		break;
 
+	case ZB_BDB_SIGNAL_TC_REJOIN_DONE:
+		/* This signal informs that TC rejoin is completed.
+		 * The signal status indicates if the device has successfully
+		 * rejoined the network.
+		 *
+		 * Next step: if the device implement Zigbee router or
+		 *            end device, and the TC rejoijn has failed,
+		 *            perform restart the generic rejoin procedure.
+		 */
+		if (status == RET_OK) {
+			zb_ext_pan_id_t extended_pan_id;
+			char ieee_addr_buf[IEEE_ADDR_BUF_SIZE] = { 0 };
+			int addr_len;
+
+			zb_get_extended_pan_id(extended_pan_id);
+			addr_len = ieee_addr_to_str(ieee_addr_buf,
+						    sizeof(ieee_addr_buf),
+						    extended_pan_id);
+			if (addr_len < 0) {
+				strcpy(ieee_addr_buf, "unknown");
+			}
+
+			LOG_INF("Joined network successfully after TC rejoin (Extended PAN ID: %s, PAN ID: 0x%04hx)",
+				log_strdup(ieee_addr_buf),
+				ZB_PIBCACHE_PAN_ID());
+			/* Device has joined the network so stop the network
+			 * rejoin procedure.
+			 */
+			if (role != ZB_NWK_DEVICE_TYPE_COORDINATOR) {
+				stop_network_rejoin(ZB_FALSE);
+			}
+		} else {
+			if (role != ZB_NWK_DEVICE_TYPE_COORDINATOR) {
+				LOG_INF("TC Rejoin was not successful (status: %d)",
+					status);
+				start_network_rejoin();
+			} else {
+				LOG_INF("Network steering failed on Zigbee coordinator (status: %d)",
+					status);
+			}
+		}
+		if (!IS_ENABLED(CONFIG_ZIGBEE_ROLE_END_DEVICE)) {
+			zb_enable_auto_pan_id_conflict_resolution(ZB_FALSE);
+		}
+		break;
+
 	default:
 		/* Unimplemented signal. For more information,
 		 * see: zb_zdo_app_signal_type_e and zb_ret_e.
@@ -697,6 +754,7 @@ static void rejoin_the_network(zb_uint8_t param)
 		} else if (!is_rejoin_in_progress) {
 			/* Calculate new timeout */
 			zb_time_t timeout_s;
+			zb_ret_t zb_err_code;
 
 			if ((1 << rejoin_attempt_cnt) > REJOIN_INTERVAL_MAX_S) {
 				timeout_s = REJOIN_INTERVAL_MAX_S;
@@ -705,12 +763,21 @@ static void rejoin_the_network(zb_uint8_t param)
 				rejoin_attempt_cnt++;
 			}
 
-			zb_ret_t zb_err_code = ZB_SCHEDULE_APP_ALARM(
-				start_network_steering,
-				ZB_FALSE,
-				ZB_MILLISECONDS_TO_BEACON_INTERVAL(timeout_s *
-								   1000));
-			ZB_ERROR_CHECK(zb_err_code);
+			if ((timeout_s > TC_REJOIN_INTERVAL_THRESHOLD_S) && (!zb_bdb_is_factory_new())) {
+				zb_err_code = ZB_SCHEDULE_APP_ALARM(
+					zb_bdb_initiate_tc_rejoin,
+					ZB_UNDEFINED_BUFFER,
+					ZB_MILLISECONDS_TO_BEACON_INTERVAL(timeout_s *
+									   1000));
+				ZB_ERROR_CHECK(zb_err_code);
+			} else {
+				zb_err_code = ZB_SCHEDULE_APP_ALARM(
+					start_network_steering,
+					ZB_FALSE,
+					ZB_MILLISECONDS_TO_BEACON_INTERVAL(timeout_s *
+									   1000));
+				ZB_ERROR_CHECK(zb_err_code);
+			}
 
 			is_rejoin_in_progress = true;
 		}
