diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index 9ed32e2c9fb9605e77ff75a50bd9589bb4797bc0..92b712536b17fdf8092e5774f5bd2fc83fae62a5 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -23,6 +23,7 @@
 /* Needed for SUBSCRIBE, NOTIFY, and PUBLISH method definitions */
 #include <pjsip_simple.h>
 #include <pjsip/sip_transaction.h>
+#include <pjsip/sip_auth.h>
 #include <pj/timer.h>
 /* Needed for pj_sockaddr */
 #include <pjlib.h>
@@ -1107,6 +1108,11 @@ struct ast_sip_endpoint {
 	unsigned int max_sessions;
 	char *realms;
 	bool cached_auth;
+	/* Authorization sessions. */
+	pjsip_auth_clt_sess auth_sess_reg;
+	pjsip_auth_clt_sess auth_sess_inv;
+	ast_mutex_t auth_sess_reg_lock;
+	ast_mutex_t auth_sess_inv_lock;
 };
 
 struct pjsip_register_dest {
diff --git a/include/asterisk/res_pjsip_outbound_registration.h b/include/asterisk/res_pjsip_outbound_registration.h
index b371b7dda3c074bd2f57b0d13e6e542fd7d95f3e..0a47b416d048293baeff8c15be0617508fabbe35 100644
--- a/include/asterisk/res_pjsip_outbound_registration.h
+++ b/include/asterisk/res_pjsip_outbound_registration.h
@@ -3,6 +3,7 @@
 
 void queue_registration_recovery_flow(const char *registration_name);
 void update_emergency_registration_ongoing_status(const char *registration_name, bool action);
-void add_cached_auth_header_from_reg(pjsip_tx_data *tdata, const char *registration_name);
+void check_and_update_nextnonce(pjsip_auth_clt_sess *sess, const char *realm, pjsip_rx_data *rdata);
+void sync_cached_auth_between_reg_inv(pjsip_auth_clt_sess *sess_from, pjsip_auth_clt_sess *sess_to, const pj_str_t *realm );
 
 #endif /* _RES_PJSIP_OUTBOUND_REGISTRATION_H */
diff --git a/res/res_pjsip_outbound_authenticator_digest.c b/res/res_pjsip_outbound_authenticator_digest.c
index aee4afc90ec5a23b9b4090ce1c278eb9c5f24380..d3a6b825ba79b72212dc131098a6a587ed96b5e3 100644
--- a/res/res_pjsip_outbound_authenticator_digest.c
+++ b/res/res_pjsip_outbound_authenticator_digest.c
@@ -31,6 +31,7 @@
 #include "asterisk/module.h"
 #include "asterisk/strings.h"
 #include "asterisk/vector.h"
+#include "asterisk/res_pjsip_outbound_registration.h"
 
 pj_str_t supported_digest_algorithms[] = {
 	{ "MD5", 3}
@@ -478,16 +479,25 @@ static int digest_create_request_with_auth(const struct ast_sip_auth_vector *aut
 		goto cleanup;
 	}
 
-	if (pjsip_auth_clt_init(&auth_sess, ast_sip_get_pjsip_endpoint(),
-				old_request->pool, 0) != PJ_SUCCESS) {
-		ast_log(LOG_ERROR, "%s: '%s': Failed to initialize client authentication session\n",
-			id_type, id);
-		res = -1;
-		goto cleanup;
+	pjsip_hdr_e search_type = get_auth_search_type(challenge);
+	struct ast_sip_auth *auth = NULL;
+	if (search_type != PJSIP_H_OTHER) {
+		pjsip_www_authenticate_hdr *auth_hdr = NULL;
+		while ((auth_hdr = pjsip_msg_find_hdr(challenge->msg_info.msg, search_type, auth_hdr ? auth_hdr->next : NULL))) {
+			for (int i = 0; i < auth_object_count; ++i) {
+				auth = AST_VECTOR_GET(&auth_objects_vector, i);
+
+				if (pj_stricmp2(&auth_hdr->challenge.digest.realm, auth->realm) == 0) {
+					ast_debug(3, "Found matching auth '%s' with realm '%s'\n", ast_sorcery_object_get_id(auth), auth->realm);
+					endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",  ast_sorcery_object_get_id(auth));
+					break;
+				}
+			}
+		}
 	}
 
 	/*
-	 * realms is used only for displaying good error messages.
+	 * realms is used for displaying good error messages, and for caching auth header
 	 */
 	realms = ast_str_create(32);
 	if (!realms) {
@@ -495,11 +505,25 @@ static int digest_create_request_with_auth(const struct ast_sip_auth_vector *aut
 		goto cleanup;
 	}
 
-	/*
-	 * Load pjproject with the valid credentials for the Authentication headers
-	 * received on the 401 or 407 response.
-	 */
-	status = set_outbound_authentication_credentials(&auth_sess, &auth_objects_vector, challenge, &realms);
+	if (endpoint && (pjsip_method_cmp(&old_request->msg->line.req.method, &pjsip_register_method) ==0 || pjsip_method_cmp(&old_request->msg->line.req.method, &pjsip_invite_method) ==0)) {
+		if(auth && auth->realm){
+			ast_str_append(&realms, 0, "%s ", auth->realm);
+		}
+		goto add_header; // auth_sess for REGISTER and INVITE has been inited during sip_outbound_registration_regc_alloc
+	} else if (pjsip_auth_clt_init(&auth_sess, ast_sip_get_pjsip_endpoint(),
+				old_request->pool, 0) != PJ_SUCCESS) {
+		ast_log(LOG_ERROR, "%s: '%s': Failed to initialize client authentication session\n",
+			id_type, id);
+		res = -1;
+		goto cleanup;
+	} else {
+		/*
+		 * Load pjproject with the valid credentials for the Authentication headers
+		 * received on the 401 or 407 response.
+		 */
+		status = set_outbound_authentication_credentials(&auth_sess, &auth_objects_vector, challenge, &realms);
+	}
+
 	switch (status) {
 	case PJ_SUCCESS:
 		break;
@@ -515,13 +539,40 @@ static int digest_create_request_with_auth(const struct ast_sip_auth_vector *aut
 		goto cleanup;
 	}
 
+add_header:
 	/*
 	 * reinit_req actually creates the Authorization headers to send on
 	 * the next request.  If reinit_req already has a cached credential
 	 * from an earlier successful authorization, it'll use it. Otherwise
 	 * it'll create a new authorization and cache it.
 	 */
-	status = pjsip_auth_clt_reinit_req(&auth_sess, challenge, old_request, new_request);
+	if(endpoint &&pjsip_method_cmp(&old_request->msg->line.req.method, &pjsip_register_method) ==0 ){
+		ast_mutex_lock(&endpoint->auth_sess_reg_lock);
+		status = pjsip_auth_clt_reinit_req(&endpoint->auth_sess_reg, challenge, old_request, new_request);
+		//if success, sync cached info to inv
+		if (status == PJ_SUCCESS){
+			ast_debug(3, "sync cached auth info from auth_sess_reg to auth_sess_inv\n");
+			pj_str_t realms_pj_str = pj_str(endpoint->realms);
+			ast_mutex_lock(&endpoint->auth_sess_inv_lock);
+			sync_cached_auth_between_reg_inv(&endpoint->auth_sess_reg, &endpoint->auth_sess_inv, &realms_pj_str);
+			ast_mutex_unlock(&endpoint->auth_sess_inv_lock);
+		}
+		ast_mutex_unlock(&endpoint->auth_sess_reg_lock);
+	} else if (endpoint && pjsip_method_cmp(&old_request->msg->line.req.method, &pjsip_invite_method) ==0 ){
+		ast_mutex_lock(&endpoint->auth_sess_inv_lock);
+		status = pjsip_auth_clt_reinit_req(&endpoint->auth_sess_inv, challenge, old_request, new_request);
+		//if success, sync cached info to reg
+		if (status == PJ_SUCCESS){
+			ast_debug(3, "sync cached auth info from auth_sess_inv to auth_sess_reg\n");
+			pj_str_t realms_pj_str = pj_str(endpoint->realms);
+			ast_mutex_lock(&endpoint->auth_sess_reg_lock);
+			sync_cached_auth_between_reg_inv(&endpoint->auth_sess_inv, &endpoint->auth_sess_reg, &realms_pj_str);
+			ast_mutex_unlock(&endpoint->auth_sess_reg_lock);
+		}
+		ast_mutex_unlock(&endpoint->auth_sess_inv_lock);
+	} else {
+		status = pjsip_auth_clt_reinit_req(&auth_sess, challenge, old_request, new_request);
+	}
 
 	switch (status) {
 	case PJ_SUCCESS:
diff --git a/res/res_pjsip_outbound_registration.c b/res/res_pjsip_outbound_registration.c
index 9ed4056fea3b64dbcc9f3656447a4ac40e0fcbb4..5f84bee3124365064342d7d1038cf13cc57daa8d 100644
--- a/res/res_pjsip_outbound_registration.c
+++ b/res/res_pjsip_outbound_registration.c
@@ -515,7 +515,6 @@ struct sip_outbound_registration_client_state {
 	bool Emergency_reg_ongoing;
 	bool Emergency_reg_hangup;
 	bool Emergency_call_ongoing;
-	char *cached_nonce;
 };
 
 /*! \brief Outbound registration state information (persists for lifetime that registration should exist) */
@@ -951,6 +950,18 @@ static pj_status_t registration_client_send(struct sip_outbound_registration_cli
 			ao2_cleanup(reg);
 		}
 	}
+	//if cached_auth, no auth header, call pjsip_auth_clt_init_req
+	if (endpoint->cached_auth == true && (pjsip_msg_find_hdr(tdata->msg, PJSIP_H_AUTHORIZATION, NULL) == NULL)){
+		//check and sync info from auth_sess_inv, nc, nonce
+		pj_str_t realms_pj_str = pj_str(endpoint->realms);
+		ast_mutex_lock(&endpoint->auth_sess_reg_lock);
+		ast_mutex_lock(&endpoint->auth_sess_inv_lock);
+		sync_cached_auth_between_reg_inv(&endpoint->auth_sess_inv, &endpoint->auth_sess_reg, &realms_pj_str);
+		ast_mutex_unlock(&endpoint->auth_sess_inv_lock);
+		ast_debug(3, "Add cached auth header\n");
+		pjsip_auth_clt_init_req(&endpoint->auth_sess_reg, tdata);
+		ast_mutex_unlock(&endpoint->auth_sess_reg_lock);
+	}
 
 	client_state->attempts++;
 	ast_sip_mod_data_set(tdata->pool, tdata->mod_data, log_register_module.id,
@@ -1297,7 +1308,25 @@ static int handle_client_state_destruction(void *data)
 		pjsip_regc_destroy(client_state->client);
 		client_state->client = NULL;
 	}
-
+	struct ast_sip_endpoint *endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", client_state->registration_name);
+	if(endpoint){
+		if(endpoint->auth_sess_reg.endpt){
+			pjsip_auth_clt_deinit(&endpoint->auth_sess_reg);
+			if (endpoint->auth_sess_reg.pool) {
+				pj_pool_release(endpoint->auth_sess_reg.pool);
+				endpoint->auth_sess_reg.pool = NULL;
+			}
+			ast_mutex_destroy(&endpoint->auth_sess_reg_lock);
+		}
+		if(endpoint->auth_sess_inv.endpt){
+			pjsip_auth_clt_deinit(&endpoint->auth_sess_inv);
+			if (endpoint->auth_sess_inv.pool) {
+				pj_pool_release(endpoint->auth_sess_inv.pool);
+				endpoint->auth_sess_inv.pool = NULL;
+			}
+			ast_mutex_destroy(&endpoint->auth_sess_inv_lock);
+		}
+	}
 	update_client_state_status(client_state, SIP_REGISTRATION_STOPPED);
 	ast_sip_auth_vector_destroy(&client_state->outbound_auths);
 	ast_sip_security_mechanisms_vector_destroy(&client_state->security_mechanisms);
@@ -1927,51 +1956,12 @@ static int handle_registration_response(void *data)
 		pjsip_cseq_hdr *cseq_hdr;
 		pjsip_tx_data *tdata;
 
-		// remove the unwanted auth header generated from libpjsip in case of no stale flag in the challenge.
-		// old_request has been updated under libpjsip after received 401/407 and before calling the callback.
-		pjsip_authorization_hdr *auth = pjsip_msg_find_hdr(response->old_request->msg, PJSIP_H_AUTHORIZATION, NULL);
-		if(auth){
-			char nonce[64];
-			ast_copy_pj_str(nonce, &auth->credential.digest.nonce, sizeof(nonce));
-			struct ast_sip_endpoint *endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
-						client_state->registration_name);
-			if (endpoint && endpoint->cached_auth != true ){
-				ast_debug(8, "no cached_auth, remove the unwanted header from old_request\n");
-				pjsip_msg_find_remove_hdr(response->old_request->msg, PJSIP_H_AUTHORIZATION, NULL);
-			} else if (endpoint && endpoint->cached_auth == true){
-				pjsip_www_authenticate_hdr *challenge_auth = pjsip_msg_find_hdr(response->rdata->msg_info.msg, PJSIP_H_WWW_AUTHENTICATE, NULL);
-				if (pj_strcmp2(&challenge_auth->challenge.digest.nonce, (const char *)client_state->cached_nonce)){
-					ast_debug(8, "nonce from challenge and cache are different, remove the unwanted header generated from libpjsip\n");
-					pjsip_msg_find_remove_hdr(response->old_request->msg, PJSIP_H_AUTHORIZATION, NULL);
-				}
-			}
-		}
-
 		if (!ast_sip_create_request_with_auth(&client_state->outbound_auths,
 				response->rdata, response->old_request, &tdata)) {
 			client_state->auth_attempted = 1;
 			ast_debug(1, "Sending authenticated REGISTER to server '%s' from client '%s'\n",
 					server_uri, client_uri);
 
-			pjsip_authorization_hdr *auth = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_AUTHORIZATION, NULL);
-			if (auth && !pj_strcmp2(&auth->scheme, "Digest")) {
-				// sync the cnonce with pjproject
-				char cnonce[64];
-				ast_copy_pj_str(cnonce, &auth->credential.digest.cnonce, sizeof(cnonce));
-				ast_debug(3, "sync cnonce: %s\n", cnonce);
-				pj_str_t cnonce_pj_str = pj_str(cnonce);
-				struct ast_sip_endpoint *endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", client_state->registration_name);
-				if(endpoint && endpoint->realms){
-					pj_str_t realms_pj_str = pj_str(endpoint->realms);
-					int test_ret = pjsip_regc_update_cnonce(client_state->client, &cnonce_pj_str, &realms_pj_str);
-					ast_debug(3, "pjsip_regc_update_cnonce: %d, realms:'%s'\n, cnonce: %s", test_ret, endpoint->realms, cnonce);
-				}
-				// cache nonce for stale flag correction
-				char nonce[64];
-				ast_copy_pj_str(nonce, &auth->credential.digest.nonce, sizeof(nonce));
-				client_state->cached_nonce = ast_strdup(nonce);
-				ast_debug(3, "client_state->cached_nonce: %s\n", client_state->cached_nonce);
-			}
 			/* Add MEDIASEC headers */
 			if (client_state->mediasec) {
 				struct ast_sip_endpoint *endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
@@ -2134,26 +2124,21 @@ static int handle_registration_response(void *data)
 		if (strlen(endpoint->incoming_mwi_mailbox))
 			mwi_send_subscribe(endpoint, response->expiration);
 
-		if(endpoint && endpoint->realms){
-			static const pj_str_t headerName = { "Authentication-Info", 19 };
-			pjsip_generic_string_hdr *auth_info = NULL;
-			auth_info = pjsip_msg_find_hdr_by_name(response->rdata->msg_info.msg, &headerName, NULL);
-			if(auth_info){
-				char value[pj_strlen(&((pjsip_generic_string_hdr*)auth_info)->hvalue) + 1];
-				ast_copy_pj_str(value, &((pjsip_generic_string_hdr*)auth_info)->hvalue, sizeof(value));
-				char nextnonce[64];
-				char *_buf = strstr(value, "nextnonce=");
-				if (_buf) {
-					sscanf(_buf, "nextnonce=\"%s", nextnonce);
-					char *buf_s = strstr(nextnonce, "\"");
-					nextnonce[((int)strlen(nextnonce)-(int)strlen(buf_s))]='\0';
-					ast_log(LOG_NOTICE, "received nextnonce: %s\n", nextnonce);
-					pj_str_t nextnonce_pj_str = pj_str(nextnonce);
-					pj_str_t realms_pj_str = pj_str(endpoint->realms);
-					int test_ret = pjsip_regc_update_nextnonce(client_state->client, &nextnonce_pj_str, &realms_pj_str);
-					ast_log(LOG_NOTICE, "pjsip_regc_update_nextnonce: %d, realms:'%s'\n, nextnonce: %s", test_ret, endpoint->realms, nextnonce);
-					client_state->cached_nonce = ast_strdup(nextnonce);
-				}
+		if (endpoint){
+			if (endpoint->realms){
+				ast_mutex_lock(&endpoint->auth_sess_reg_lock);
+				check_and_update_nextnonce(&endpoint->auth_sess_reg, endpoint->realms, response->rdata);
+				ast_mutex_unlock(&endpoint->auth_sess_reg_lock);
+			}
+			if (endpoint->cached_auth){
+				//if cached, sync to auth_sess_inv, nc, nonce
+				pj_str_t realms_pj_str = pj_str(endpoint->realms);
+				ast_debug(3, "Sync cached auth sess from auth_sess_reg to auth_sess_inv\n");
+				ast_mutex_lock(&endpoint->auth_sess_reg_lock);
+				ast_mutex_lock(&endpoint->auth_sess_inv_lock);
+				sync_cached_auth_between_reg_inv(&endpoint->auth_sess_reg, &endpoint->auth_sess_inv, &realms_pj_str); // (from, to, realm)
+				ast_mutex_unlock(&endpoint->auth_sess_inv_lock);
+				ast_mutex_unlock(&endpoint->auth_sess_reg_lock);
 			}
 		}
 
@@ -2782,6 +2767,9 @@ static int set_outbound_initial_authentication_credentials(pjsip_regc *regc,
 			pjsip_regc_set_credentials(regc, 1, auth_creds);
 			struct ast_sip_endpoint *endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", ast_sorcery_object_get_id(auths[idx]));
 			endpoint->realms = ast_strdup(auths[idx]->realm);
+			// set credentials for local auth_sess endpoint->auth_sess_reg/auth_sess_inv
+			pjsip_auth_clt_set_credentials(&endpoint->auth_sess_reg, 1, auth_creds);
+			pjsip_auth_clt_set_credentials(&endpoint->auth_sess_inv, 1, auth_creds);
 		default:
 			/* other cases handled after receiving auth rejection */
 			break;
@@ -2899,6 +2887,20 @@ static int sip_outbound_registration_regc_alloc(void *data)
 		return -1;
 	}
 
+	struct pjsip_endpoint *endpt = ast_sip_get_pjsip_endpoint();
+	struct ast_sip_endpoint *endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", state->client_state->registration_name);
+	pool = pjsip_endpt_create_pool(endpt, "sip_auth_session_reg%p", 1024, 1024);
+	if(pjsip_auth_clt_init(&endpoint->auth_sess_reg, endpt, pool, 0) != PJ_SUCCESS){
+		ast_log(LOG_WARNING, "auth_sess_reg init failed!\n");
+	}else{
+		ast_mutex_init(&endpoint->auth_sess_reg_lock);
+	}
+	pool = pjsip_endpt_create_pool(endpt, "sip_auth_session_inv%p", 1024, 1024);
+	if(pjsip_auth_clt_init(&endpoint->auth_sess_inv, endpt, pool, 0) != PJ_SUCCESS){
+		ast_log(LOG_WARNING, "auth_sess_inv init failed!\n");
+	}else{
+		ast_mutex_init(&endpoint->auth_sess_inv_lock);
+	}
 	return 0;
 }
 /*! \brief Helper function which performs a single registration for recovery flow*/
@@ -3318,32 +3320,95 @@ void update_emergency_registration_ongoing_status(const char *registration_name,
 
 }
 
-void add_cached_auth_header_from_reg(pjsip_tx_data *tdata, const char *registration_name)
+void queue_registration_recovery_flow(const char *registration_name)
 {
 	struct sip_outbound_registration_state *state;
 	state = get_state(registration_name);
 	if (!state) {
 		ast_log(LOG_WARNING, "Unable to retrieve registration %s\n", registration_name);
 	} else {
-		struct ast_sip_endpoint *endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", registration_name);
-		if(endpoint && endpoint->realms){
-			pj_str_t realms_pj_str = pj_str(endpoint->realms);
-			int test_ret = pjsip_regc_add_cached_auth_for_inv(tdata, state->client_state->client, &realms_pj_str);
-			ast_debug(3, "pjsip_regc_add_cached_auth_for_inv: %d, realms:'%s'\n", test_ret, endpoint->realms);
+		cancel_registration(state->client_state);
+		ast_log(LOG_NOTICE, "Queue registration with new state \n");
+		re_register_with_new_state(ast_sip_get_sorcery(), state->registration);
+	}
+}
+
+void check_and_update_nextnonce(pjsip_auth_clt_sess *sess, const char *realm, pjsip_rx_data *rdata){
+	pjsip_generic_string_hdr *auth_info = NULL;
+	static const pj_str_t headerName = { "Authentication-Info", 19 };
+	auth_info = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &headerName, NULL);
+   if(auth_info){
+		char value[pj_strlen(&((pjsip_generic_string_hdr*)auth_info)->hvalue) + 1];
+		ast_copy_pj_str(value, &((pjsip_generic_string_hdr*)auth_info)->hvalue, sizeof(value));
+		char nextnonce[64];
+		char *_buf = strstr(value, "nextnonce=");
+		if (_buf) {
+			sscanf(_buf, "nextnonce=\"%s", nextnonce);
+			char *buf_s = strstr(nextnonce, "\"");
+			nextnonce[((int)strlen(nextnonce)-(int)strlen(buf_s))]='\0';
+			ast_log(LOG_NOTICE, "received nextnonce: %s\n", nextnonce);
+			pj_str_t nextnonce_pj_str = pj_str(nextnonce);
+			pj_str_t realms_pj_str = pj_str(realm);
+			pjsip_cached_auth *cached_auth;
+			cached_auth = pjsip_auth_find_cached_auth(sess, &realms_pj_str);
+			if (cached_auth) {
+				pj_strdup(cached_auth->pool, &cached_auth->last_chal->challenge.digest.nonce, &nextnonce_pj_str);
+				cached_auth->nc=0;
+				ast_debug(3, "update nextnonce to cached auth\n");
+			}
 		}
 	}
 }
 
-void queue_registration_recovery_flow(const char *registration_name)
+void sync_cached_auth_between_reg_inv(pjsip_auth_clt_sess *sess_from, pjsip_auth_clt_sess *sess_to, const pj_str_t *realm )
 {
-	struct sip_outbound_registration_state *state;
-	state = get_state(registration_name);
-	if (!state) {
-		ast_log(LOG_WARNING, "Unable to retrieve registration %s\n", registration_name);
-	} else {
-		cancel_registration(state->client_state);
-		ast_log(LOG_NOTICE, "Queue registration with new state \n");
-		re_register_with_new_state(ast_sip_get_sorcery(), state->registration);
+	pjsip_cached_auth *cached_auth_from, *cached_auth_to;
+	cached_auth_from = pjsip_auth_find_cached_auth(sess_from, realm);
+	if (cached_auth_from) {
+		const pjsip_cred_info *cred;
+		pjsip_authorization_hdr *hauth;
+		pj_status_t status;
+		cred = pjsip_auth_find_cred(sess_from, &cached_auth_from->realm, &cached_auth_from->last_chal->scheme );
+		if (!cred)
+			return;
+		// Find cached_auth for INVITE, create new if not exists.
+		cached_auth_to = pjsip_auth_find_cached_auth(sess_to, realm);
+		if (!cached_auth_to) {
+			cached_auth_to = PJ_POOL_ZALLOC_T(sess_to->pool, pjsip_cached_auth);
+			cached_auth_to->pool = pjsip_endpt_create_pool(sess_to->endpt, "auth_sync_cli%p", 1024, 1024);
+			pj_strdup(cached_auth_to->pool, &cached_auth_to->realm, realm);
+			cached_auth_to->is_proxy = PJ_TRUE;
+			pj_list_init(&cached_auth_to->cached_hdr);
+			pj_list_insert_before(&sess_to->cached_auth, cached_auth_to);
+			ast_debug(8, "New cached auth created\n");
+		}
+		// Sync with cached_auth info
+		cached_auth_to->nc = cached_auth_from->nc;
+		cached_auth_to->qop_value = cached_auth_from->qop_value;
+		cached_auth_to->stale_cnt = cached_auth_from->stale_cnt;
+		pj_strdup(cached_auth_to->pool, &cached_auth_to->cnonce, &cached_auth_from->cnonce);
+		pj_pool_t *pool = pjsip_endpt_create_pool(sess_from->endpt, "m_auth_cli%p", 1024, 1024);
+		pjsip_www_authenticate_hdr *hdr;
+		if (cached_auth_from->last_chal->type == PJSIP_H_WWW_AUTHENTICATE)
+			hdr = pjsip_proxy_authenticate_hdr_create(pool);
+		else
+			hdr = pjsip_www_authenticate_hdr_create(pool);
+
+		pj_strdup(pool, &hdr->scheme, &cached_auth_from->last_chal->scheme);
+		if (pj_stricmp2(&hdr->scheme, "digest") == 0) {
+			pj_strdup(pool, &hdr->challenge.digest.realm, &cached_auth_from->last_chal->challenge.digest.realm);
+			pj_strdup(pool, &hdr->challenge.digest.domain, &cached_auth_from->last_chal->challenge.digest.domain);
+			pj_strdup(pool, &hdr->challenge.digest.nonce, &cached_auth_from->last_chal->challenge.digest.nonce);
+			pj_strdup(pool, &hdr->challenge.digest.opaque, &cached_auth_from->last_chal->challenge.digest.opaque);
+			hdr->challenge.digest.stale = cached_auth_from->last_chal->challenge.digest.stale;
+			pj_strdup(pool, &hdr->challenge.digest.algorithm, &cached_auth_from->last_chal->challenge.digest.algorithm);
+			pj_strdup(pool, &hdr->challenge.digest.qop, &cached_auth_from->last_chal->challenge.digest.qop);
+			pjsip_param_clone(pool, &hdr->challenge.digest.other_param,
+							  &cached_auth_from->last_chal->challenge.digest.other_param);
+		}
+		pjsip_endpt_release_pool(sess_from->endpt, pool);
+		cached_auth_to->last_chal = (pjsip_www_authenticate_hdr*) pjsip_hdr_clone(cached_auth_to->pool, hdr);
+		ast_debug(8, "cached auth synced\n");
 	}
 }
 
diff --git a/res/res_pjsip_outbound_registration.exports.in b/res/res_pjsip_outbound_registration.exports.in
index be75cc4300aa55afee2fc2fbc9559f7d60a0e764..05c3efb00a057c91db3019db17449cea5d69241a 100644
--- a/res/res_pjsip_outbound_registration.exports.in
+++ b/res/res_pjsip_outbound_registration.exports.in
@@ -2,7 +2,8 @@
 	global:
 		LINKER_SYMBOL_PREFIXqueue_registration_recovery_flow;
 		LINKER_SYMBOL_PREFIXupdate_emergency_registration_ongoing_status;
-		LINKER_SYMBOL_PREFIXadd_cached_auth_header_from_reg;
+		LINKER_SYMBOL_PREFIXcheck_and_update_nextnonce;
+		LINKER_SYMBOL_PREFIXsync_cached_auth_between_reg_inv;
 	local:
 		*;
 };
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index e35701f8a13da7718f29fa1502c0dd54bbf37663..710d519ef6e0e872ceb4f3205ebe123723bc6925 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -2966,7 +2966,11 @@ int ast_sip_session_create_invite(struct ast_sip_session *session, pjsip_tx_data
 
 	if (session->endpoint->cached_auth){
 		ast_debug(3, "INVITE: Attach cached auth headers\n");
-		add_cached_auth_header_from_reg(*tdata, ast_sorcery_object_get_id(session->endpoint));
+		if (pjsip_msg_find_hdr((*tdata)->msg, PJSIP_H_PROXY_AUTHORIZATION, NULL) == NULL){
+			ast_mutex_lock(&session->endpoint->auth_sess_inv_lock);
+			pjsip_auth_clt_init_req(&session->endpoint->auth_sess_inv, *tdata);
+			ast_mutex_unlock(&session->endpoint->auth_sess_inv_lock);
+		}
 	}
 
 	content_header = pjsip_msg_find_hdr_by_name((*tdata)->msg, &headerName, NULL);
@@ -3343,6 +3347,25 @@ void ast_sip_session_unsuspend(struct ast_sip_session *session)
 	ast_taskprocessor_unsuspend(session->serializer);
 }
 
+static void invite_nextnonce_update(pjsip_rx_data *rdata){
+	pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
+	pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
+	if (!dlg || !tsx) {
+		return;
+	}
+	if (tsx->method.id != PJSIP_INVITE_METHOD) {
+		/* Not an INVITE that needs authentication */
+		return;
+	}
+	pjsip_inv_session *inv = pjsip_dlg_get_inv_session(dlg);
+	struct ast_sip_session *session = inv->mod_data[session_module.id];
+	if (session->endpoint && session->endpoint->realms){
+		ast_mutex_lock(&session->endpoint->auth_sess_inv_lock);
+		check_and_update_nextnonce(&session->endpoint->auth_sess_inv, session->endpoint->realms, rdata);
+		ast_mutex_unlock(&session->endpoint->auth_sess_inv_lock);
+	}
+}
+
 /*!
  * \internal
  * \brief Handle initial INVITE challenge response message.
@@ -3363,6 +3386,8 @@ static pj_bool_t outbound_invite_auth(pjsip_rx_data *rdata)
 
 	if (rdata->msg_info.msg->line.status.code != 401
 		&& rdata->msg_info.msg->line.status.code != 407) {
+		// check and update for nextnonce if needed
+		invite_nextnonce_update(rdata);
 		/* Doesn't pertain to us. Move on */
 		return PJ_FALSE;
 	}
diff --git a/third-party/pjproject/patches/0021-Update-for-Authorization-header-handling.patch b/third-party/pjproject/patches/0021-Update-for-Authorization-header-handling.patch
index c575da1a467c1b85fca61349eeecbaca4b22801b..286675b2ef1980050eaf21e8d439bf51f636092f 100644
--- a/third-party/pjproject/patches/0021-Update-for-Authorization-header-handling.patch
+++ b/third-party/pjproject/patches/0021-Update-for-Authorization-header-handling.patch
@@ -1,131 +1,64 @@
-From 850281ea4ce63fe71434613916223190ae5522b9 Mon Sep 17 00:00:00 2001
+From d0879fbe17d213a267b6015b85f5810fb34ec78b Mon Sep 17 00:00:00 2001
 From: "wenpeng.song" <wenpeng.song@iopsys.eu>
-Date: Tue, 29 Apr 2025 11:02:24 +0200
-Subject: [PATCH] Update for Authorization header handling.
+Date: Wed, 14 May 2025 15:14:16 +0200
+Subject: [PATCH] Update for Authorization header handling
 
- * Add support for next nonce, and cached Authorization header.
- * Call callback to let Asterisk control the REGISTER challenge handling.
- * Add support for resend the cached Authorization header for INVITE.
+ * Call callback to let Asterisk control the REGISTER challenge handling
+ * Add wrapper api for find_cached_auth, auth_find_cred
 ---
- pjsip/include/pjsip-ua/sip_regc.h | 12 ++++++
- pjsip/include/pjsip/sip_auth.h    | 37 +++++++++++++++++++
- pjsip/src/pjsip-ua/sip_reg.c      | 42 +++++++++++++++++----
- pjsip/src/pjsip/sip_auth_client.c | 61 +++++++++++++++++++++++++++++++
- 4 files changed, 144 insertions(+), 8 deletions(-)
+ build.symbian/pjsipU.def          |  2 ++
+ pjsip/include/pjsip/sip_auth.h    |  8 ++++++++
+ pjsip/src/pjsip-ua/sip_reg.c      | 22 ++++++++++++----------
+ pjsip/src/pjsip/sip_auth_client.c | 12 ++++++++++++
+ 4 files changed, 34 insertions(+), 10 deletions(-)
 
-diff --git a/pjsip/include/pjsip-ua/sip_regc.h b/pjsip/include/pjsip-ua/sip_regc.h
-index df97a6011..53ba89abd 100644
---- a/pjsip/include/pjsip-ua/sip_regc.h
-+++ b/pjsip/include/pjsip-ua/sip_regc.h
-@@ -312,6 +312,18 @@ PJ_DECL(pj_status_t) pjsip_regc_set_credentials( pjsip_regc *regc,
-                                                  int count,
-                                                  const pjsip_cred_info cred[] );
- 
-+PJ_DECL(pj_status_t) pjsip_regc_update_nextnonce( pjsip_regc *regc,
-+                                                const pj_str_t *nextnonce,
-+                                                const pj_str_t *realm );
-+
-+PJ_DECL(pj_status_t) pjsip_regc_update_cnonce( pjsip_regc *regc,
-+                                                const pj_str_t *cnonce,
-+                                                const pj_str_t *realm );
-+
-+PJ_DECL(pj_status_t) pjsip_regc_add_cached_auth_for_inv( pjsip_tx_data *tdata,
-+                                                pjsip_regc *regc,
-+                                                const pj_str_t *realm );
-+
- /**
-  * Set authentication preference.
-  *
+diff --git a/build.symbian/pjsipU.def b/build.symbian/pjsipU.def
+index 68d31eba3..5490d1e33 100644
+--- a/build.symbian/pjsipU.def
++++ b/build.symbian/pjsipU.def
+@@ -278,3 +278,5 @@ EXPORTS
+ 	pjsip_warning_hdr_create                 @ 277 NONAME
+ 	pjsip_warning_hdr_create_from_status     @ 278 NONAME
+ 	pjsip_www_authenticate_hdr_create        @ 279 NONAME
++	pjsip_auth_find_cached_auth              @ 280 NONAME
++	pjsip_auth_find_cred                     @ 281 NONAME
 diff --git a/pjsip/include/pjsip/sip_auth.h b/pjsip/include/pjsip/sip_auth.h
-index fa55830fd..0af4ec972 100644
+index fa55830fd..02a8a7cde 100644
 --- a/pjsip/include/pjsip/sip_auth.h
 +++ b/pjsip/include/pjsip/sip_auth.h
-@@ -342,7 +342,44 @@ PJ_DECL(pj_status_t) pjsip_auth_clt_init( pjsip_auth_clt_sess *sess,
-                                           pj_pool_t *pool, 
-                                           unsigned options);
+@@ -628,6 +628,14 @@ PJ_DEF(pj_status_t) pjsip_auth_create_digestSHA256(pj_str_t* result,
+  * @}
+  */
  
-+/**
-+ * Update the nonce with the nextnonce received from response.
-+ *
-+ * @param sess          The client authentication session.
-+ * @param nextnonce     The nextnonce received from response.
-+ * @param realm         The realm used for the authentication.
-+ *
-+ * @return              PJ_SUCCESS on success.
-+ */
-+PJ_DECL(pj_status_t) pjsip_auth_clt_update_cache(  pjsip_auth_clt_sess *sess,
-+                                                const pj_str_t *nextnonce,
-+                                                const pj_str_t *realm );
++/* Find cached authentication in the list for the specified realm. */
++PJ_DECL(pjsip_cached_auth) *pjsip_auth_find_cached_auth( pjsip_auth_clt_sess *sess,
++                                            const pj_str_t *realm );
++
++/* Find credential to use for the specified realm and auth scheme. */
++PJ_DECL(pjsip_cred_info*) pjsip_auth_find_cred( const pjsip_auth_clt_sess *sess,
++                                              const pj_str_t *realm,
++                                              const pj_str_t *auth_scheme);
  
-+/**
-+ * Update the cnonce with the cnonce generated from asterisk.
-+ *
-+ * @param sess          The client authentication session.
-+ * @param cnonce        The cnonce generated from asterisk.
-+ * @param realm         The realm used for the authentication.
-+ *
-+ * @return              PJ_SUCCESS on success.
-+ */
-+PJ_DECL(pj_status_t) pjsip_auth_clt_update_cache_cnonce(  pjsip_auth_clt_sess *sess,
-+                                                const pj_str_t *cnonce,
-+                                                const pj_str_t *realm );
-+
-+/**
-+ * Use the cached auth header for subsequent invite request.
-+ *
-+ * @param tdata         The outgoing invite request message.
-+ * @param sess          The client authentication session.
-+ * @param realm         The realm used for the authentication.
-+ *
-+ * @return              PJ_SUCCESS on success.
-+ */
-+PJ_DECL(pj_status_t) new_invite_req_with_auth( pjsip_tx_data *tdata,
-+                                     pjsip_auth_clt_sess *sess,
-+                                     const pj_str_t *realm );
- /**
-  * Deinitialize client authentication session data structure.
-  *
+ 
+ PJ_END_DECL
 diff --git a/pjsip/src/pjsip-ua/sip_reg.c b/pjsip/src/pjsip-ua/sip_reg.c
-index 947e9edb7..1911142ea 100644
+index 947e9edb7..6a3aad194 100644
 --- a/pjsip/src/pjsip-ua/sip_reg.c
 +++ b/pjsip/src/pjsip-ua/sip_reg.c
-@@ -434,6 +434,31 @@ PJ_DEF(pj_status_t) pjsip_regc_set_credentials( pjsip_regc *regc,
-     return pjsip_auth_clt_set_credentials(&regc->auth_sess, count, cred);
- }
- 
-+PJ_DEF(pj_status_t) pjsip_regc_update_nextnonce( pjsip_regc *regc,
-+                                                const pj_str_t *nextnonce,
-+                                                const pj_str_t *realm )
-+{
-+    PJ_ASSERT_RETURN(regc && nextnonce && realm, PJ_EINVAL);
-+    return pjsip_auth_clt_update_cache(&regc->auth_sess, nextnonce, realm);
-+}
-+
-+PJ_DEF(pj_status_t) pjsip_regc_update_cnonce( pjsip_regc *regc,
-+                                                const pj_str_t *cnonce,
-+                                                const pj_str_t *realm )
-+{
-+    PJ_ASSERT_RETURN(regc && cnonce && realm, PJ_EINVAL);
-+    return pjsip_auth_clt_update_cache_cnonce(&regc->auth_sess, cnonce, realm);
-+}
-+
-+PJ_DEF(pj_status_t) pjsip_regc_add_cached_auth_for_inv( pjsip_tx_data *tdata,
-+                                                pjsip_regc *regc,
-+                                                const pj_str_t *realm )
-+{
-+    PJ_ASSERT_RETURN(regc && tdata && realm, PJ_EINVAL);
-+    return new_invite_req_with_auth(tdata, &regc->auth_sess, realm);
-+}
-+
-+
- PJ_DEF(pj_status_t) pjsip_regc_set_prefs( pjsip_regc *regc,
-                                           const pjsip_auth_clt_pref *pref)
- {
-@@ -1216,19 +1241,20 @@ static void regc_tsx_callback(void *token, pjsip_event *event)
+@@ -1210,25 +1210,27 @@ static void regc_tsx_callback(void *token, pjsip_event *event)
+                 pj_list_erase(chdr);
+             }
+         }
+-
++        status = PJ_SUCCESS;
++/*
+         status = pjsip_auth_clt_reinit_req( &regc->auth_sess,
+                                             rdata, 
                                              tsx->last_tx,  
                                              &tdata);
- 
+-
 -        if (status == PJ_SUCCESS) {
++*/
 +// Call callback anyway to let asterisk control the handling of the challenge
 +//        if (status == PJ_SUCCESS) {
              /* Need to unlock the regc temporarily while sending the message
@@ -149,7 +82,7 @@ index 947e9edb7..1911142ea 100644
              /* Only call callback if application is still interested
               * in it.
               */
-@@ -1242,7 +1268,7 @@ static void regc_tsx_callback(void *token, pjsip_event *event)
+@@ -1242,7 +1244,7 @@ static void regc_tsx_callback(void *token, pjsip_event *event)
                                rdata, NOEXP, 0, NULL, is_unreg);
                  pj_lock_acquire(regc->lock);
              }
@@ -159,73 +92,24 @@ index 947e9edb7..1911142ea 100644
      } else if (regc->_delete_flag) {
  
 diff --git a/pjsip/src/pjsip/sip_auth_client.c b/pjsip/src/pjsip/sip_auth_client.c
-index ee2876d99..f8b4ff9d9 100644
+index ee2876d99..fd5c93007 100644
 --- a/pjsip/src/pjsip/sip_auth_client.c
 +++ b/pjsip/src/pjsip/sip_auth_client.c
-@@ -1528,3 +1528,64 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_reinit_req(  pjsip_auth_clt_sess *sess,
+@@ -1528,3 +1528,15 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_reinit_req(  pjsip_auth_clt_sess *sess,
  
  }
  
-+
-+PJ_DEF(pj_status_t) pjsip_auth_clt_update_cache(  pjsip_auth_clt_sess *sess,
-+                                                const pj_str_t *nextnonce,
-+                                                const pj_str_t *realm ){
-+
-+    PJ_ASSERT_RETURN(sess && nextnonce && realm, PJ_EINVAL);
-+    pjsip_cached_auth *cached_auth;
-+    cached_auth = find_cached_auth(sess, realm);
-+    if (cached_auth) {
-+        pj_strdup(cached_auth->pool, &cached_auth->last_chal->challenge.digest.nonce, nextnonce);
-+        cached_auth->nc=0;
-+        return PJ_SUCCESS;
-+    }
-+    return PJ_EINVAL;
-+}
-+
-+PJ_DEF(pj_status_t) pjsip_auth_clt_update_cache_cnonce(  pjsip_auth_clt_sess *sess,
-+                                                const pj_str_t *cnonce,
-+                                                const pj_str_t *realm ){
-+
-+    PJ_ASSERT_RETURN(sess && cnonce && realm, PJ_EINVAL);
-+    pjsip_cached_auth *cached_auth;
-+    cached_auth = find_cached_auth(sess, realm);
-+    if (cached_auth) {
-+        pj_strdup(cached_auth->pool, &cached_auth->cnonce, cnonce);
-+        return PJ_SUCCESS;
-+    }
-+    return PJ_EINVAL;
++/* Find cached authentication in the list for the specified realm. */
++PJ_DEF(pjsip_cached_auth) *pjsip_auth_find_cached_auth( pjsip_auth_clt_sess *sess,
++                                            const pj_str_t *realm ){
++    return find_cached_auth(sess, realm);
 +}
 +
-+PJ_DEF(pj_status_t) new_invite_req_with_auth( pjsip_tx_data *tdata,
-+                                     pjsip_auth_clt_sess *sess,
-+                                     const pj_str_t *realm )
-+{
-+
-+    PJ_ASSERT_RETURN(sess && tdata && realm, PJ_EINVAL);
-+    pjsip_cached_auth *cached_auth;
-+    cached_auth = find_cached_auth(sess, realm);
-+    if (cached_auth) {
-+        const pjsip_cred_info *cred;
-+        pjsip_authorization_hdr *hauth;
-+        pj_status_t status;
-+
-+        PJ_ASSERT_RETURN(cached_auth->last_chal != NULL, PJSIP_EAUTHNOPREVCHAL);
-+
-+        cred = auth_find_cred( sess, &cached_auth->realm, &cached_auth->last_chal->scheme );
-+        if (!cred)
-+            return PJSIP_ENOCREDENTIAL;
-+
-+        status = auth_respond( tdata->pool, cached_auth->last_chal,
-+                               tdata->msg->line.req.uri,
-+                               cred, &pjsip_register_method,
-+                               sess->pool, cached_auth, &hauth);
-+        if (status != PJ_SUCCESS)
-+            return status;
-+        pjsip_msg_add_hdr( tdata->msg, (pjsip_hdr*)hauth);
-+        return PJ_SUCCESS;
-+    }
-+    return PJ_EINVAL;
-+
++/* Find credential to use for the specified realm and auth scheme. */
++PJ_DEF(pjsip_cred_info*) pjsip_auth_find_cred( const pjsip_auth_clt_sess *sess,
++                                              const pj_str_t *realm,
++                                              const pj_str_t *auth_scheme){
++    return auth_find_cred(sess, realm, auth_scheme);
 +}
 -- 
 2.43.0