diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index b6dd441d4d7c5638f7ee5a3fe7f14166eb2a0ae4..9baceb944437e4bb6e2b7ad8f840e1dc8305b43b 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -316,6 +316,15 @@ enum ast_sip_session_media_encryption {
 	AST_SIP_MEDIA_ENCRYPT_DTLS,
 };
 
+enum ast_sip_session_redirect {
+	/*! User portion of the target URI should be used as the target in the dialplan */
+	AST_SIP_REDIRECT_USER = 0,
+	/*! Target URI should be used as the target in the dialplan */
+	AST_SIP_REDIRECT_URI_CORE,
+	/*! Target URI should be used as the target within chan_pjsip itself */
+	AST_SIP_REDIRECT_URI_PJSIP,
+};
+
 /*!
  * \brief Session timers options
  */
@@ -574,6 +583,8 @@ struct ast_sip_endpoint {
 	unsigned int faxdetect;
 	/*! Determines if transfers (using REFER) are allowed by this endpoint */
 	unsigned int allowtransfer;
+	/*! Method used when handling redirects */
+	enum ast_sip_session_redirect redirect_method;
 };
 
 /*!
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index db4f32f2cbf5e5f5fde5c8fc2333edb8ab9c33af..37762e6cf607ebf98d1dc15972781633b130d0ab 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -244,6 +244,27 @@
 						</enumlist>
 					</description>
 				</configOption>
+				<configOption name="redirect_method">
+					<synopsis>How redirects received from an endpoint are handled</synopsis>
+					<description><para>
+						When a redirect is received from an endpoint there are multiple ways it can be handled.
+						If this option is set to <literal>user</literal> the user portion of the redirect target
+						is treated as an extension within the dialplan and dialed using a Local channel. If this option
+						is set to <literal>uri_core</literal> the target URI is returned to the dialing application
+						which dials it using the PJSIP channel driver and endpoint originally used. If this option is
+						set to <literal>uri_pjsip</literal> the redirect occurs within chan_pjsip itself and is not exposed
+						to the core at all. The <literal>uri_pjsip</literal> option has the benefit of being more efficient
+						and also supporting multiple potential redirect targets. The con is that since redirection occurs
+						within chan_pjsip redirecting information is not forwarded and redirection can not be
+						prevented.
+						</para>
+						<enumlist>
+							<enum name="user" />
+							<enum name="uri_core" />
+							<enum name="uri_pjsip" />
+						</enumlist>
+					</description>
+				</configOption>
 				<configOption name="mailboxes">
 					<synopsis>Mailbox(es) to be associated with</synopsis>
 				</configOption>
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 4642c5e665ece0051523b50fd2b79bbae86e0516..835dbfbf69ef6d4e5505fb3d6aa91d35a8954b45 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -455,6 +455,25 @@ static int ident_to_str(const void *obj, const intptr_t *args, char **buf)
 	return 0;
 }
 
+static int redirect_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
+{
+	struct ast_sip_endpoint *endpoint = obj;
+
+	if (!strcasecmp(var->value, "user")) {
+		endpoint->redirect_method = AST_SIP_REDIRECT_USER;
+	} else if (!strcasecmp(var->value, "uri_core")) {
+		endpoint->redirect_method = AST_SIP_REDIRECT_URI_CORE;
+	} else if (!strcasecmp(var->value, "uri_pjsip")) {
+		endpoint->redirect_method = AST_SIP_REDIRECT_URI_PJSIP;
+	} else {
+		ast_log(LOG_ERROR, "Unrecognized redirect method %s specified for endpoint %s\n",
+			var->value, ast_sorcery_object_get_id(endpoint));
+		return -1;
+	}
+
+	return 0;
+}
+
 static int direct_media_method_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
 {
 	struct ast_sip_endpoint *endpoint = obj;
@@ -1353,6 +1372,7 @@ int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_mod
 	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_ca_path", "", dtls_handler, dtlscapath_to_str, 0, 0);
 	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_setup", "", dtls_handler, dtlssetup_to_str, 0, 0);
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "srtp_tag_32", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.srtp_tag_32));
+	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "redirect_method", "user", redirect_handler, NULL, 0, 0);
 
 	if (ast_sip_initialize_sorcery_transport(sip_sorcery)) {
 		ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index f44ec4422cc36721d4b7fa94825c8299c34a6514..065f40d4e75006cea8d4b90a8108545ae8a0cf1a 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -2065,13 +2065,31 @@ static void session_inv_on_media_update(pjsip_inv_session *inv, pj_status_t stat
 static pjsip_redirect_op session_inv_on_redirected(pjsip_inv_session *inv, const pjsip_uri *target, const pjsip_event *e)
 {
 	struct ast_sip_session *session = inv->mod_data[session_module.id];
+	const pjsip_sip_uri *uri;
 
-	if (PJSIP_URI_SCHEME_IS_SIP(target) || PJSIP_URI_SCHEME_IS_SIPS(target)) {
-		const pjsip_sip_uri *uri = pjsip_uri_get_uri(target);
+	if (session->endpoint->redirect_method == AST_SIP_REDIRECT_URI_PJSIP) {
+		return PJSIP_REDIRECT_ACCEPT;
+	}
+
+	if (!PJSIP_URI_SCHEME_IS_SIP(target) && !PJSIP_URI_SCHEME_IS_SIPS(target)) {
+		return PJSIP_REDIRECT_STOP;
+	}
+
+	uri = pjsip_uri_get_uri(target);
+
+	if (session->endpoint->redirect_method == AST_SIP_REDIRECT_USER) {
 		char exten[AST_MAX_EXTENSION];
 
 		ast_copy_pj_str(exten, &uri->user, sizeof(exten));
 		ast_channel_call_forward_set(session->channel, exten);
+	} else if (session->endpoint->redirect_method == AST_SIP_REDIRECT_URI_CORE) {
+		char target_uri[PJSIP_MAX_URL_SIZE];
+		/* PJSIP/ + endpoint length + / + max URL size */
+		char forward[8 + strlen(ast_sorcery_object_get_id(session->endpoint)) + PJSIP_MAX_URL_SIZE];
+
+		pjsip_uri_print(PJSIP_URI_IN_REQ_URI, uri, target_uri, sizeof(target_uri));
+		sprintf(forward, "PJSIP/%s/%s", ast_sorcery_object_get_id(session->endpoint), target_uri);
+		ast_channel_call_forward_set(session->channel, forward);
 	}
 
 	return PJSIP_REDIRECT_STOP;