diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 78a8bcee6e..713ef7c248 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -2589,7 +2589,7 @@ dblink_security_check(PGconn *conn, remoteConn *rconn)
 {
 	if (!superuser())
 	{
-		if (!PQconnectionUsedPassword(conn))
+		if (!(PQconnectionUsedPassword(conn) || PQconnectionUsedGSSAPI(conn)))
 		{
 			libpqsrv_disconnect(conn);
 			if (rconn)
@@ -2597,8 +2597,8 @@ dblink_security_check(PGconn *conn, remoteConn *rconn)
 
 			ereport(ERROR,
 					(errcode(ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED),
-					 errmsg("password is required"),
-					 errdetail("Non-superuser cannot connect if the server does not request a password."),
+					 errmsg("password or GSSAPI is required"),
+					 errdetail("Non-superuser cannot connect if the server does not request a password or use GSSAPI."),
 					 errhint("Target server's authentication method must be changed.")));
 		}
 	}
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index d5fc61446a..77656ccf80 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -171,7 +171,8 @@ ALTER SERVER testserver1 OPTIONS (
 	sslcrl 'value',
 	--requirepeer 'value',
 	krbsrvname 'value',
-	gsslib 'value'
+	gsslib 'value',
+	gssdeleg 'value'
 	--replication 'value'
 );
 -- Error, invalid list syntax
diff --git a/contrib/postgres_fdw/option.c b/contrib/postgres_fdw/option.c
index 984e4d168a..bb6f309907 100644
--- a/contrib/postgres_fdw/option.c
+++ b/contrib/postgres_fdw/option.c
@@ -286,6 +286,9 @@ InitPgFdwOptions(void)
 		{"sslcert", UserMappingRelationId, true},
 		{"sslkey", UserMappingRelationId, true},
 
+		/* gssencmode is also libpq option, same to above. */
+		{"gssencmode", UserMappingRelationId, true},
+
 		{NULL, InvalidOid, false}
 	};
 
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index 1e50be137b..1a43bdf55b 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -185,7 +185,8 @@ ALTER SERVER testserver1 OPTIONS (
 	sslcrl 'value',
 	--requirepeer 'value',
 	krbsrvname 'value',
-	gsslib 'value'
+	gsslib 'value',
+	gssdeleg 'value'
 	--replication 'value'
 );
 
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index ecd9aa73ef..a931996968 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -1170,6 +1170,23 @@ include_dir 'conf.d'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-gss-accept-deleg" xreflabel="gss_accept_deleg">
+      <term><varname>gss_accept_deleg</varname> (<type>boolean</type>)
+      <indexterm>
+       <primary><varname>gss_accept_deleg</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Sets whether GSSAPI delegation should be accepted from the client.
+        The default is <literal>off</literal> meaning credentials from the client will
+        NOT be accepted.  Changing this to <literal>on</literal> will make the server
+        accept credentials delegated to it from the client. This parameter can only be
+        set in the <filename>postgresql.conf</filename> file or on the server command line.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry id="guc-db-user-namespace" xreflabel="db_user_namespace">
       <term><varname>db_user_namespace</varname> (<type>boolean</type>)
       <indexterm>
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 0e7ae70c70..9f3e12b2a7 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1879,6 +1879,18 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
       </listitem>
      </varlistentry>
 
+     <varlistentry id="libpq-connect-gssdeleg" xreflabel="gssdeleg">
+      <term><literal>gssdeleg</literal></term>
+      <listitem>
+       <para>
+        Forward (delegate) GSS credentials to the server.  The default is
+        <literal>disable</literal> which means credentials will not be forwarded
+        to the server.  Set this to <literal>enable</literal> to have
+        credentials forwarded when possible.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry id="libpq-connect-service" xreflabel="service">
       <term><literal>service</literal></term>
       <listitem>
@@ -2479,6 +2491,25 @@ int PQconnectionUsedPassword(const PGconn *conn);
       </para>
      </listitem>
     </varlistentry>
+
+    <varlistentry id="libpq-PQconnectionUsedGSSAPI">
+     <term><function>PQconnectionUsedGSSAPI</function><indexterm><primary>PQconnectionUsedGSSAPI</primary></indexterm></term>
+     <listitem>
+      <para>
+       Returns true (1) if the connection authentication method
+       used GSSAPI. Returns false (0) if not.
+
+<synopsis>
+int PQconnectionUsedGSSAPI(const PGconn *conn);
+</synopsis>
+      </para>
+
+      <para>
+       This function can be applied to detect whether the connection was
+       authenticated with GSSAPI.
+      </para>
+     </listitem>
+    </varlistentry>
    </variablelist>
   </para>
 
@@ -7981,6 +8012,16 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
      </para>
     </listitem>
 
+    <listitem>
+     <para>
+      <indexterm>
+       <primary><envar>PGGSSDELEG</envar></primary>
+      </indexterm>
+      <envar>PGGSSDELEG</envar> behaves the same as the <xref
+      linkend="libpq-connect-gssdeleg"/> connection parameter.
+     </para>
+    </listitem>
+
     <listitem>
      <para>
       <indexterm>
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index b0b997f092..48cc5608b6 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -3573,6 +3573,15 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
        True if GSSAPI encryption is in use on this connection
       </para></entry>
      </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>credentials_proxied</structfield> <type>boolean</type>
+      </para>
+      <para>
+       True if GSSAPI credentials were forwarded/proxied on this connection.
+      </para></entry>
+     </row>
     </tbody>
    </tgroup>
   </table>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 34ca0e739f..1843de1c77 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -977,7 +977,8 @@ CREATE VIEW pg_stat_gssapi AS
             S.pid,
             S.gss_auth AS gss_authenticated,
             S.gss_princ AS principal,
-            S.gss_enc AS encrypted
+            S.gss_enc AS encrypted,
+            S.gss_proxy AS credentials_proxied
     FROM pg_stat_get_activity(NULL) AS S
     WHERE S.client_port IS NOT NULL;
 
diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c
index dca02271dc..6e1977fa62 100644
--- a/src/backend/foreign/foreign.c
+++ b/src/backend/foreign/foreign.c
@@ -574,6 +574,7 @@ static const struct ConnectionOption libpq_conninfo_options[] = {
 	{"requiressl", ForeignServerRelationId},
 	{"sslmode", ForeignServerRelationId},
 	{"gsslib", ForeignServerRelationId},
+	{"gssdeleg", ForeignServerRelationId},
 	{NULL, InvalidOid}
 };
 
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index 25b3a781cd..963bc26b97 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -161,6 +161,7 @@ static int	CheckCertAuth(Port *port);
  */
 char	   *pg_krb_server_keyfile;
 bool		pg_krb_caseins_users;
+bool		pg_gss_accept_deleg;
 
 
 /*----------------------------------------------------------------
@@ -914,6 +915,7 @@ pg_GSS_recvauth(Port *port)
 	int			mtype;
 	StringInfoData buf;
 	gss_buffer_desc gbuf;
+	gss_cred_id_t proxy;
 
 	/*
 	 * Use the configured keytab, if there is one.  Unfortunately, Heimdal
@@ -943,6 +945,9 @@ pg_GSS_recvauth(Port *port)
 	 */
 	port->gss->ctx = GSS_C_NO_CONTEXT;
 
+	proxy = NULL;
+	port->gss->proxy_creds = false;
+
 	/*
 	 * Loop through GSSAPI message exchange. This exchange can consist of
 	 * multiple messages sent in both directions. First message is always from
@@ -993,7 +998,7 @@ pg_GSS_recvauth(Port *port)
 										  &port->gss->outbuf,
 										  &gflags,
 										  NULL,
-										  NULL);
+										  pg_gss_accept_deleg ? &proxy : NULL);
 
 		/* gbuf no longer used */
 		pfree(buf.data);
@@ -1005,6 +1010,12 @@ pg_GSS_recvauth(Port *port)
 
 		CHECK_FOR_INTERRUPTS();
 
+		if (proxy != NULL)
+		{
+			pg_store_proxy_credential(proxy);
+			port->gss->proxy_creds = true;
+		}
+
 		if (port->gss->outbuf.length != 0)
 		{
 			/*
diff --git a/src/backend/libpq/be-gssapi-common.c b/src/backend/libpq/be-gssapi-common.c
index fb39c760d8..d5a9926d5c 100644
--- a/src/backend/libpq/be-gssapi-common.c
+++ b/src/backend/libpq/be-gssapi-common.c
@@ -92,3 +92,54 @@ pg_GSS_error(const char *errmsg,
 			(errmsg_internal("%s", errmsg),
 			 errdetail_internal("%s: %s", msg_major, msg_minor)));
 }
+
+/*
+ * Store the credentials passed in into the memory cache for later usage.
+ *
+ * This allows credentials to be delegated to us for us to use to connect
+ * to other systems with, using, e.g. postgres_fdw or dblink.
+ */
+#define GSS_MEMORY_CACHE "MEMORY:"
+void
+pg_store_proxy_credential(gss_cred_id_t cred)
+{
+	OM_uint32 major, minor;
+	gss_OID_set mech;
+	gss_cred_usage_t usage;
+	gss_key_value_element_desc cc;
+	gss_key_value_set_desc ccset;
+
+	cc.key = "ccache";
+	cc.value = GSS_MEMORY_CACHE;
+	ccset.count = 1;
+	ccset.elements = &cc;
+
+	/* Make the proxy credential only available to current process */
+	major = gss_store_cred_into(&minor,
+		cred,
+		GSS_C_INITIATE, /* credential only used for starting libpq connection */
+		GSS_C_NULL_OID, /* store all */
+		true, /* overwrite */
+		true, /* make default */
+		&ccset,
+		&mech,
+		&usage);
+
+	if (major != GSS_S_COMPLETE)
+	{
+		pg_GSS_error("gss_store_cred", major, minor);
+	}
+
+	/* Credential stored, so we can release our credential handle. */
+	major = gss_release_cred(&minor, &cred);
+	if (major != GSS_S_COMPLETE)
+	{
+		pg_GSS_error("gss_release_cred", major, minor);
+	}
+
+	/*
+	 * Set KRB5CCNAME for this backend, so that later calls to gss_acquire_cred
+	 * will find the proxied credentials we stored.
+	 */
+	setenv("KRB5CCNAME", GSS_MEMORY_CACHE, 1);
+}
diff --git a/src/backend/libpq/be-secure-gssapi.c b/src/backend/libpq/be-secure-gssapi.c
index 3b55f43199..9ff91534e1 100644
--- a/src/backend/libpq/be-secure-gssapi.c
+++ b/src/backend/libpq/be-secure-gssapi.c
@@ -497,6 +497,7 @@ secure_open_gssapi(Port *port)
 	bool		complete_next = false;
 	OM_uint32	major,
 				minor;
+	gss_cred_id_t	proxy;
 
 	/*
 	 * Allocate subsidiary Port data for GSSAPI operations.
@@ -504,6 +505,9 @@ secure_open_gssapi(Port *port)
 	port->gss = (pg_gssinfo *)
 		MemoryContextAllocZero(TopMemoryContext, sizeof(pg_gssinfo));
 
+	proxy = NULL;
+	port->gss->proxy_creds = false;
+
 	/*
 	 * Allocate buffers and initialize state variables.  By malloc'ing the
 	 * buffers at this point, we avoid wasting static data space in processes
@@ -588,7 +592,8 @@ secure_open_gssapi(Port *port)
 									   GSS_C_NO_CREDENTIAL, &input,
 									   GSS_C_NO_CHANNEL_BINDINGS,
 									   &port->gss->name, NULL, &output, NULL,
-									   NULL, NULL);
+									   NULL, pg_gss_accept_deleg ? &proxy : NULL);
+
 		if (GSS_ERROR(major))
 		{
 			pg_GSS_error(_("could not accept GSSAPI security context"),
@@ -605,6 +610,12 @@ secure_open_gssapi(Port *port)
 			complete_next = true;
 		}
 
+		if (proxy != NULL)
+		{
+			pg_store_proxy_credential(proxy);
+			port->gss->proxy_creds = true;
+		}
+
 		/* Done handling the incoming packet, reset our buffer */
 		PqGSSRecvLength = 0;
 
@@ -731,3 +742,16 @@ be_gssapi_get_princ(Port *port)
 
 	return port->gss->princ;
 }
+
+/*
+ * Return if GSSAPI delegated/proxy credentials were included on this
+ * connection.
+ */
+bool
+be_gssapi_get_proxy(Port *port)
+{
+	if (!port || !port->gss)
+		return NULL;
+
+	return port->gss->proxy_creds;
+}
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 608d01ea0d..778d5769fd 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -384,6 +384,7 @@ pgstat_bestart(void)
 		lbeentry.st_gss = true;
 		lgssstatus.gss_auth = be_gssapi_get_auth(MyProcPort);
 		lgssstatus.gss_enc = be_gssapi_get_enc(MyProcPort);
+		lgssstatus.gss_proxy = be_gssapi_get_proxy(MyProcPort);
 		if (princ)
 			strlcpy(lgssstatus.gss_princ, princ, NAMEDATALEN);
 	}
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 9d707c3521..cf774a6848 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -303,7 +303,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_activity(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_ACTIVITY_COLS	30
+#define PG_STAT_GET_ACTIVITY_COLS	31
 	int			num_backends = pgstat_fetch_stat_numbackends();
 	int			curr_backend;
 	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
@@ -395,7 +395,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 			pfree(clipped_activity);
 
 			/* leader_pid */
-			nulls[28] = true;
+			nulls[29] = true;
 
 			proc = BackendPidGetProc(beentry->st_procpid);
 
@@ -432,8 +432,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 				 */
 				if (leader && leader->pid != beentry->st_procpid)
 				{
-					values[28] = Int32GetDatum(leader->pid);
-					nulls[28] = false;
+					values[29] = Int32GetDatum(leader->pid);
+					nulls[29] = false;
 				}
 				else if (beentry->st_backendType == B_BG_WORKER)
 				{
@@ -441,8 +441,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 
 					if (leader_pid != InvalidPid)
 					{
-						values[28] = Int32GetDatum(leader_pid);
-						nulls[28] = false;
+						values[29] = Int32GetDatum(leader_pid);
+						nulls[29] = false;
 					}
 				}
 			}
@@ -600,6 +600,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 				values[25] = BoolGetDatum(beentry->st_gssstatus->gss_auth); /* gss_auth */
 				values[26] = CStringGetTextDatum(beentry->st_gssstatus->gss_princ);
 				values[27] = BoolGetDatum(beentry->st_gssstatus->gss_enc);	/* GSS Encryption in use */
+				values[28] = BoolGetDatum(beentry->st_gssstatus->gss_proxy);	/* GSS credentials proxied */
 			}
 			else
 			{
@@ -607,11 +608,13 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 				nulls[26] = true;	/* No GSS principal */
 				values[27] = BoolGetDatum(false);	/* GSS Encryption not in
 													 * use */
+				values[28] = BoolGetDatum(false);	/* GSS credentials not
+													 * proxied */
 			}
 			if (beentry->st_query_id == 0)
-				nulls[29] = true;
+				nulls[30] = true;
 			else
-				values[29] = UInt64GetDatum(beentry->st_query_id);
+				values[30] = UInt64GetDatum(beentry->st_query_id);
 		}
 		else
 		{
@@ -640,6 +643,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 			nulls[27] = true;
 			nulls[28] = true;
 			nulls[29] = true;
+			nulls[30] = true;
 		}
 
 		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 2f07ca7a0e..c872512bbc 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -282,15 +282,17 @@ PerformAuthentication(Port *port)
 
 			if (princ)
 				appendStringInfo(&logmsg,
-								 _(" GSS (authenticated=%s, encrypted=%s, principal=%s)"),
+								 _(" GSS (authenticated=%s, encrypted=%s, proxy_credentials=%s, principal=%s)"),
 								 be_gssapi_get_auth(port) ? _("yes") : _("no"),
 								 be_gssapi_get_enc(port) ? _("yes") : _("no"),
+								 be_gssapi_get_proxy(port) ? _("yes") : _("no"),
 								 princ);
 			else
 				appendStringInfo(&logmsg,
-								 _(" GSS (authenticated=%s, encrypted=%s)"),
+								 _(" GSS (authenticated=%s, encrypted=%s, proxy_credentials=%s)"),
 								 be_gssapi_get_auth(port) ? _("yes") : _("no"),
-								 be_gssapi_get_enc(port) ? _("yes") : _("no"));
+								 be_gssapi_get_enc(port) ? _("yes") : _("no"),
+								 be_gssapi_get_proxy(port) ? _("yes") : _("no"));
 		}
 #endif
 
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 1c0583fe26..6d7d5908ef 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -1708,6 +1708,16 @@ struct config_bool ConfigureNamesBool[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"gss_accept_deleg", PGC_SIGHUP, CONN_AUTH_AUTH,
+			gettext_noop("Sets whether GSSAPI delegation should be accepted from the client."),
+			NULL
+		},
+		&pg_gss_accept_deleg,
+		false,
+		NULL, NULL, NULL
+	},
+
 	{
 		{"escape_string_warning", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
 			gettext_noop("Warn about backslash escapes in ordinary string literals."),
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index d06074b86f..7d26d58de3 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -100,6 +100,7 @@
 # GSSAPI using Kerberos
 #krb_server_keyfile = 'FILE:${sysconfdir}/krb5.keytab'
 #krb_caseins_users = off
+#gss_accept_deleg = off
 
 # - SSL -
 
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 66b73c3900..44f05cfac0 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5404,9 +5404,9 @@
   proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
   proretset => 't', provolatile => 's', proparallel => 'r',
   prorettype => 'record', proargtypes => 'int4',
-  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8}',
-  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
-  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id}',
+  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,bool,int4,int8}',
+  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,gss_proxy,leader_pid,query_id}',
   prosrc => 'pg_stat_get_activity' },
 { oid => '3318',
   descr => 'statistics: information about progress of backends running maintenance command',
diff --git a/src/include/libpq/auth.h b/src/include/libpq/auth.h
index 137bee7c45..9105d6757d 100644
--- a/src/include/libpq/auth.h
+++ b/src/include/libpq/auth.h
@@ -18,6 +18,7 @@
 
 extern PGDLLIMPORT char *pg_krb_server_keyfile;
 extern PGDLLIMPORT bool pg_krb_caseins_users;
+extern PGDLLIMPORT bool pg_gss_accept_deleg;
 extern PGDLLIMPORT char *pg_krb_realm;
 
 extern void ClientAuthentication(Port *port);
diff --git a/src/include/libpq/be-gssapi-common.h b/src/include/libpq/be-gssapi-common.h
index facd24ff7f..841facde12 100644
--- a/src/include/libpq/be-gssapi-common.h
+++ b/src/include/libpq/be-gssapi-common.h
@@ -18,13 +18,16 @@
 
 #if defined(HAVE_GSSAPI_H)
 #include <gssapi.h>
+#include <gssapi_ext.h>
 #else
 #include <gssapi/gssapi.h>
+#include <gssapi/gssapi_ext.h>
 #endif
 
 extern void pg_GSS_error(const char *errmsg,
 						 OM_uint32 maj_stat, OM_uint32 min_stat);
 
+extern void pg_store_proxy_credential(gss_cred_id_t cred);
 #endif							/* ENABLE_GSS */
 
 #endif							/* BE_GSSAPI_COMMON_H */
diff --git a/src/include/libpq/libpq-be.h b/src/include/libpq/libpq-be.h
index ac6407e9f6..4d6a8c31cb 100644
--- a/src/include/libpq/libpq-be.h
+++ b/src/include/libpq/libpq-be.h
@@ -84,6 +84,7 @@ typedef struct
 								 * GSSAPI auth was not used */
 	bool		auth;			/* GSSAPI Authentication used */
 	bool		enc;			/* GSSAPI encryption in use */
+	bool		proxy_creds;	/* GSSAPI Delegated/proxy credentials */
 #endif
 } pg_gssinfo;
 #endif
@@ -328,6 +329,7 @@ extern PGDLLIMPORT openssl_tls_init_hook_typ openssl_tls_init_hook;
 extern bool be_gssapi_get_auth(Port *port);
 extern bool be_gssapi_get_enc(Port *port);
 extern const char *be_gssapi_get_princ(Port *port);
+extern bool be_gssapi_get_proxy(Port *port);
 
 /* Read and write to a GSSAPI-encrypted connection. */
 extern ssize_t be_gssapi_read(Port *port, void *ptr, size_t len);
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index f7bd83113a..0e680f0332 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -77,6 +77,7 @@ typedef struct PgBackendGSSStatus
 	char		gss_princ[NAMEDATALEN]; /* GSSAPI Principal used to auth */
 	bool		gss_auth;		/* If GSSAPI authentication was used */
 	bool		gss_enc;		/* If encryption is being used */
+	bool		gss_proxy;		/* If credentials proxied */
 
 } PgBackendGSSStatus;
 
diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt
index e8bcc88370..7ded77aff3 100644
--- a/src/interfaces/libpq/exports.txt
+++ b/src/interfaces/libpq/exports.txt
@@ -186,3 +186,4 @@ PQpipelineStatus          183
 PQsetTraceFlags           184
 PQmblenBounded            185
 PQsendFlushRequest        186
+PQconnectionUsedGSSAPI    187
diff --git a/src/interfaces/libpq/fe-auth.c b/src/interfaces/libpq/fe-auth.c
index 9afc6f19b9..a518378915 100644
--- a/src/interfaces/libpq/fe-auth.c
+++ b/src/interfaces/libpq/fe-auth.c
@@ -58,9 +58,11 @@ pg_GSS_continue(PGconn *conn, int payloadlen)
 {
 	OM_uint32	maj_stat,
 				min_stat,
-				lmin_s;
+				lmin_s,
+				gss_flags = GSS_C_MUTUAL_FLAG;
 	gss_buffer_desc ginbuf;
 	gss_buffer_desc goutbuf;
+	gss_cred_id_t proxy = GSS_C_NO_CREDENTIAL;
 
 	/*
 	 * On first call, there's no input token. On subsequent calls, read the
@@ -92,12 +94,19 @@ pg_GSS_continue(PGconn *conn, int payloadlen)
 		ginbuf.value = NULL;
 	}
 
+	/* Only try to acquire credentials if GSS delegation isn't disabled. */
+	if (!pg_GSS_have_cred_cache(&proxy))
+		proxy = GSS_C_NO_CREDENTIAL;
+
+	if (conn->gssdeleg && pg_strcasecmp(conn->gssdeleg,"enable") == 0)
+		gss_flags |= GSS_C_DELEG_FLAG;
+
 	maj_stat = gss_init_sec_context(&min_stat,
-									GSS_C_NO_CREDENTIAL,
+									proxy,
 									&conn->gctx,
 									conn->gtarg_nam,
 									GSS_C_NO_OID,
-									GSS_C_MUTUAL_FLAG,
+									gss_flags,
 									0,
 									GSS_C_NO_CHANNEL_BINDINGS,
 									(ginbuf.value == NULL) ? GSS_C_NO_BUFFER : &ginbuf,
@@ -136,7 +145,10 @@ pg_GSS_continue(PGconn *conn, int payloadlen)
 	}
 
 	if (maj_stat == GSS_S_COMPLETE)
+	{
 		gss_release_name(&lmin_s, &conn->gtarg_nam);
+		conn->gssapi_used = true;
+	}
 
 	return STATUS_OK;
 }
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 50b5df3490..69c7e1346a 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -332,6 +332,10 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
 		"GSS-library", "", 7,	/* sizeof("gssapi") == 7 */
 	offsetof(struct pg_conn, gsslib)},
 
+	{"gssdeleg", "PGGSSDELEG", NULL, NULL,
+		"GSS-delegation", "", 8,	/* sizeof("disable") == 8 */
+	offsetof(struct pg_conn, gssdeleg)},
+
 	{"replication", NULL, NULL, NULL,
 		"Replication", "D", 5,
 	offsetof(struct pg_conn, replication)},
@@ -596,6 +600,7 @@ pqDropServerData(PGconn *conn)
 	conn->last_sqlstate[0] = '\0';
 	conn->auth_req_received = false;
 	conn->password_needed = false;
+	conn->gssapi_used = false;
 	conn->write_failed = false;
 	free(conn->write_err_msg);
 	conn->write_err_msg = NULL;
@@ -4028,6 +4033,7 @@ freePGconn(PGconn *conn)
 	free(conn->gssencmode);
 	free(conn->krbsrvname);
 	free(conn->gsslib);
+	free(conn->gssdeleg);
 	free(conn->connip);
 	/* Note that conn->Pfdebug is not ours to close or free */
 	free(conn->write_err_msg);
@@ -6816,6 +6822,17 @@ PQconnectionUsedPassword(const PGconn *conn)
 		return false;
 }
 
+int
+PQconnectionUsedGSSAPI(const PGconn *conn)
+{
+	if (!conn)
+		return false;
+	if (conn->gssapi_used)
+		return true;
+	else
+		return false;
+}
+
 int
 PQclientEncoding(const PGconn *conn)
 {
diff --git a/src/interfaces/libpq/fe-secure-gssapi.c b/src/interfaces/libpq/fe-secure-gssapi.c
index 038e847b7e..372bfdd21e 100644
--- a/src/interfaces/libpq/fe-secure-gssapi.c
+++ b/src/interfaces/libpq/fe-secure-gssapi.c
@@ -477,11 +477,13 @@ pqsecure_open_gss(PGconn *conn)
 {
 	ssize_t		ret;
 	OM_uint32	major,
-				minor;
+				minor,
+				gss_flags = GSS_REQUIRED_FLAGS;
 	uint32		netlen;
 	PostgresPollingStatusType result;
 	gss_buffer_desc input = GSS_C_EMPTY_BUFFER,
 				output = GSS_C_EMPTY_BUFFER;
+	static gss_cred_id_t proxy = GSS_C_NO_CREDENTIAL;
 
 	/*
 	 * If first time through for this connection, allocate buffers and
@@ -621,13 +623,30 @@ pqsecure_open_gss(PGconn *conn)
 	if (ret != STATUS_OK)
 		return PGRES_POLLING_FAILED;
 
+	if (conn->gssdeleg && pg_strcasecmp(conn->gssdeleg,"enable") == 0)
+	{
+		/* Acquire credentials if possbile */
+		if (proxy == GSS_C_NO_CREDENTIAL)
+			(void) pg_GSS_have_cred_cache(&proxy);
+
+		/*
+		 * We have credentials and gssdeleg is enabled, so request
+		 * credential delegation.  This may or may not actually result in
+		 * credentials being delegated- it depends on if the forwardable
+		 * flag has been set in the credential and if the server is
+		 * configured to accept delegated credentials.
+		 */
+		if (proxy != GSS_C_NO_CREDENTIAL)
+			gss_flags |= GSS_C_DELEG_FLAG;
+	}
+
 	/*
 	 * Call GSS init context, either with an empty input, or with a complete
 	 * packet from the server.
 	 */
-	major = gss_init_sec_context(&minor, conn->gcred, &conn->gctx,
+	major = gss_init_sec_context(&minor, proxy, &conn->gctx,
 								 conn->gtarg_nam, GSS_C_NO_OID,
-								 GSS_REQUIRED_FLAGS, 0, 0, &input, NULL,
+								 gss_flags, 0, 0, &input, NULL,
 								 &output, NULL, NULL);
 
 	/* GSS Init Sec Context uses the whole packet, so clear it */
@@ -647,6 +666,7 @@ pqsecure_open_gss(PGconn *conn)
 		 * to do GSS wrapping/unwrapping.
 		 */
 		conn->gssenc = true;
+		conn->gssapi_used = true;
 
 		/* Clean up */
 		gss_release_cred(&minor, &conn->gcred);
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index f3d9220496..7476dbe0e9 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -354,6 +354,7 @@ extern int	PQbackendPID(const PGconn *conn);
 extern PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 extern int	PQconnectionNeedsPassword(const PGconn *conn);
 extern int	PQconnectionUsedPassword(const PGconn *conn);
+extern int	PQconnectionUsedGSSAPI(const PGconn *conn);
 extern int	PQclientEncoding(const PGconn *conn);
 extern int	PQsetClientEncoding(PGconn *conn, const char *encoding);
 
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index d7ec5ed429..4828917d38 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -393,6 +393,7 @@ struct pg_conn
 	char	   *krbsrvname;		/* Kerberos service name */
 	char	   *gsslib;			/* What GSS library to use ("gssapi" or
 								 * "sspi") */
+	char	   *gssdeleg;		/* Try to delegate GSS credentials? */
 	char	   *ssl_min_protocol_version;	/* minimum TLS protocol version */
 	char	   *ssl_max_protocol_version;	/* maximum TLS protocol version */
 	char	   *target_session_attrs;	/* desired session properties */
@@ -452,6 +453,7 @@ struct pg_conn
 	int			sversion;		/* server version, e.g. 70401 for 7.4.1 */
 	bool		auth_req_received;	/* true if any type of auth req received */
 	bool		password_needed;	/* true if server demanded a password */
+	bool		gssapi_used;	/* true if authenticated via gssapi */
 	bool		sigpipe_so;		/* have we masked SIGPIPE via SO_NOSIGPIPE? */
 	bool		sigpipe_flag;	/* can we mask SIGPIPE via MSG_NOSIGNAL? */
 	bool		write_failed;	/* have we had a write failure on sock? */
diff --git a/src/test/kerberos/Makefile b/src/test/kerberos/Makefile
index 7765f3f93b..f460d2c0e7 100644
--- a/src/test/kerberos/Makefile
+++ b/src/test/kerberos/Makefile
@@ -13,6 +13,9 @@ subdir = src/test/kerberos
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
+EXTRA_INSTALL += contrib/postgres_fdw
+EXTRA_INSTALL += contrib/dblink
+
 export with_gssapi with_krb_srvnam
 
 check:
diff --git a/src/test/kerberos/t/001_auth.pl b/src/test/kerberos/t/001_auth.pl
index d610ce63ab..6e76ef6373 100644
--- a/src/test/kerberos/t/001_auth.pl
+++ b/src/test/kerberos/t/001_auth.pl
@@ -56,6 +56,7 @@ elsif ($^O eq 'linux')
 
 my $krb5_config  = 'krb5-config';
 my $kinit        = 'kinit';
+my $klist        = 'klist';
 my $kdb5_util    = 'kdb5_util';
 my $kadmin_local = 'kadmin.local';
 my $krb5kdc      = 'krb5kdc';
@@ -64,6 +65,7 @@ if ($krb5_bin_dir && -d $krb5_bin_dir)
 {
 	$krb5_config = $krb5_bin_dir . '/' . $krb5_config;
 	$kinit       = $krb5_bin_dir . '/' . $kinit;
+	$klist       = $krb5_bin_dir . '/' . $klist;
 }
 if ($krb5_sbin_dir && -d $krb5_sbin_dir)
 {
@@ -108,6 +110,7 @@ kdc = FILE:$kdc_log
 
 [libdefaults]
 default_realm = $realm
+forwardable = false
 
 [realms]
 $realm = {
@@ -185,7 +188,21 @@ lc_messages = 'C'
 });
 $node->start;
 
+my $port = $node->port();
+
 $node->safe_psql('postgres', 'CREATE USER test1;');
+$node->safe_psql('postgres', 'CREATE EXTENSION postgres_fdw;');
+$node->safe_psql('postgres', 'CREATE EXTENSION dblink;');
+$node->safe_psql('postgres', "CREATE SERVER s1 FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host '$host', hostaddr '$hostaddr', port '$port', dbname 'postgres');");
+
+$node->safe_psql('postgres', 'GRANT USAGE ON FOREIGN SERVER s1 TO test1;');
+
+$node->safe_psql('postgres', "CREATE USER MAPPING FOR test1 SERVER s1 OPTIONS (user 'test1', password_required 'false');");
+$node->safe_psql('postgres', "CREATE TABLE t1 (c1 int);");
+$node->safe_psql('postgres', "INSERT INTO t1 VALUES (1);");
+$node->safe_psql('postgres', "CREATE FOREIGN TABLE tf1 (c1 int) SERVER s1 OPTIONS (schema_name 'public', table_name 't1');");
+$node->safe_psql('postgres', "GRANT SELECT ON t1 TO test1;");
+$node->safe_psql('postgres', "GRANT SELECT ON tf1 TO test1;");
 
 # Set up a table for SYSTEM_USER parallel worker testing.
 $node->safe_psql('postgres',
@@ -258,6 +275,7 @@ $node->restart;
 test_access($node, 'test1', 'SELECT true', 2, '', 'fails without ticket');
 
 run_log [ $kinit, 'test1' ], \$test1_password or BAIL_OUT($?);
+run_log [ $klist, '-f' ] or BAIL_OUT($?);
 
 test_access(
 	$node,
@@ -275,34 +293,56 @@ $node->restart;
 test_access(
 	$node,
 	'test1',
-	'SELECT gss_authenticated AND encrypted from pg_stat_gssapi where pid = pg_backend_pid();',
+	'SELECT gss_authenticated AND encrypted AND NOT credentials_proxied FROM pg_stat_gssapi WHERE pid = pg_backend_pid();',
 	0,
 	'',
-	'succeeds with mapping with default gssencmode and host hba',
+	'succeeds with mapping with default gssencmode and host hba, ticket not forwardable',
 	"connection authenticated: identity=\"test1\@$realm\" method=gss",
-	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, principal=test1\@$realm)"
+	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, proxy_credentials=no, principal=test1\@$realm)"
 );
 
 test_access(
 	$node,
 	'test1',
-	'SELECT gss_authenticated AND encrypted from pg_stat_gssapi where pid = pg_backend_pid();',
+	'SELECT gss_authenticated AND encrypted AND NOT credentials_proxied FROM pg_stat_gssapi WHERE pid = pg_backend_pid();',
 	0,
 	'gssencmode=prefer',
-	'succeeds with GSS-encrypted access preferred with host hba',
+	'succeeds with GSS-encrypted access preferred with host hba, ticket not forwardable',
 	"connection authenticated: identity=\"test1\@$realm\" method=gss",
-	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, principal=test1\@$realm)"
+	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, proxy_credentials=no, principal=test1\@$realm)"
 );
 test_access(
 	$node,
 	'test1',
-	'SELECT gss_authenticated AND encrypted from pg_stat_gssapi where pid = pg_backend_pid();',
+	'SELECT gss_authenticated AND encrypted AND NOT credentials_proxied FROM pg_stat_gssapi WHERE pid = pg_backend_pid();',
 	0,
 	'gssencmode=require',
-	'succeeds with GSS-encrypted access required with host hba',
+	'succeeds with GSS-encrypted access required with host hba, ticket not forwardable',
+	"connection authenticated: identity=\"test1\@$realm\" method=gss",
+	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, proxy_credentials=no, principal=test1\@$realm)"
+);
+
+test_access(
+	$node,
+	'test1',
+	'SELECT gss_authenticated AND encrypted AND NOT credentials_proxied FROM pg_stat_gssapi WHERE pid = pg_backend_pid();',
+	0,
+	'gssencmode=prefer gssdeleg=enable',
+	'succeeds with GSS-encrypted access preferred with host hba and credentials not delegated even though asked for (ticket not forwardable)',
 	"connection authenticated: identity=\"test1\@$realm\" method=gss",
-	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, principal=test1\@$realm)"
+	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, proxy_credentials=no, principal=test1\@$realm)"
 );
+test_access(
+	$node,
+	'test1',
+	'SELECT gss_authenticated AND encrypted AND NOT credentials_proxied FROM pg_stat_gssapi WHERE pid = pg_backend_pid();',
+	0,
+	'gssencmode=require gssdeleg=enable',
+	'succeeds with GSS-encrypted access required with host hba and credentials not delegated even though asked for (ticket not forwardable)',
+	"connection authenticated: identity=\"test1\@$realm\" method=gss",
+	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, proxy_credentials=no, principal=test1\@$realm)"
+);
+
 
 # Test that we can transport a reasonable amount of data.
 test_query(
@@ -345,27 +385,101 @@ test_query(
 unlink($node->data_dir . '/pg_hba.conf');
 $node->append_conf('pg_hba.conf',
 	qq{hostgssenc all all $hostaddr/32 gss map=mymap});
+
+string_replace_file($krb5_conf, "forwardable = false", "forwardable = true");
+
+run_log [ $kinit, 'test1' ], \$test1_password or BAIL_OUT($?);
+run_log [ $klist, '-f' ] or BAIL_OUT($?);
+
+test_access(
+	$node,
+	'test1',
+	'SELECT gss_authenticated AND encrypted AND NOT credentials_proxied from pg_stat_gssapi where pid = pg_backend_pid();',
+	0,
+	'gssencmode=prefer gssdeleg=enable',
+	'succeeds with GSS-encrypted access preferred and hostgssenc hba and credentials not forwarded (server does not accept them, default)',
+	"connection authenticated: identity=\"test1\@$realm\" method=gss",
+	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, proxy_credentials=no, principal=test1\@$realm)"
+);
+test_access(
+	$node,
+	'test1',
+	'SELECT gss_authenticated AND encrypted AND NOT credentials_proxied from pg_stat_gssapi where pid = pg_backend_pid();',
+	0,
+	'gssencmode=require gssdeleg=enable',
+	'succeeds with GSS-encrypted access required and hostgssenc hba and credentials not forwarded (server does not accept them, default)',
+	"connection authenticated: identity=\"test1\@$realm\" method=gss",
+	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, proxy_credentials=no, principal=test1\@$realm)"
+);
+
+$node->append_conf('postgresql.conf',
+	qq{gss_accept_deleg=off});
+$node->restart;
+
+test_access(
+	$node,
+	'test1',
+	'SELECT gss_authenticated AND encrypted AND NOT credentials_proxied from pg_stat_gssapi where pid = pg_backend_pid();',
+	0,
+	'gssencmode=prefer gssdeleg=enable',
+	'succeeds with GSS-encrypted access preferred and hostgssenc hba and credentials not forwarded (server does not accept them, explicitly disabled)',
+	"connection authenticated: identity=\"test1\@$realm\" method=gss",
+	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, proxy_credentials=no, principal=test1\@$realm)"
+);
+test_access(
+	$node,
+	'test1',
+	'SELECT gss_authenticated AND encrypted AND NOT credentials_proxied from pg_stat_gssapi where pid = pg_backend_pid();',
+	0,
+	'gssencmode=require gssdeleg=enable',
+	'succeeds with GSS-encrypted access required and hostgssenc hba and credentials not forwarded (server does not accept them, explicitly disabled)',
+	"connection authenticated: identity=\"test1\@$realm\" method=gss",
+	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, proxy_credentials=no, principal=test1\@$realm)"
+);
+
+$node->append_conf('postgresql.conf',
+	qq{gss_accept_deleg=on});
 $node->restart;
 
 test_access(
 	$node,
 	'test1',
-	'SELECT gss_authenticated AND encrypted from pg_stat_gssapi where pid = pg_backend_pid();',
+	'SELECT gss_authenticated AND encrypted AND credentials_proxied from pg_stat_gssapi where pid = pg_backend_pid();',
+	0,
+	'gssencmode=prefer gssdeleg=enable',
+	'succeeds with GSS-encrypted access preferred and hostgssenc hba and credentials forwarded',
+	"connection authenticated: identity=\"test1\@$realm\" method=gss",
+	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, proxy_credentials=yes, principal=test1\@$realm)"
+);
+test_access(
+	$node,
+	'test1',
+	'SELECT gss_authenticated AND encrypted AND credentials_proxied from pg_stat_gssapi where pid = pg_backend_pid();',
+	0,
+	'gssencmode=require gssdeleg=enable',
+	'succeeds with GSS-encrypted access required and hostgssenc hba and credentials forwarded',
+	"connection authenticated: identity=\"test1\@$realm\" method=gss",
+	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, proxy_credentials=yes, principal=test1\@$realm)"
+);
+test_access(
+	$node,
+	'test1',
+	'SELECT gss_authenticated AND encrypted AND NOT credentials_proxied FROM pg_stat_gssapi WHERE pid = pg_backend_pid();',
 	0,
 	'gssencmode=prefer',
-	'succeeds with GSS-encrypted access preferred and hostgssenc hba',
+	'succeeds with GSS-encrypted access preferred and hostgssenc hba and credentials not forwarded',
 	"connection authenticated: identity=\"test1\@$realm\" method=gss",
-	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, principal=test1\@$realm)"
+	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, proxy_credentials=no, principal=test1\@$realm)"
 );
 test_access(
 	$node,
 	'test1',
-	'SELECT gss_authenticated AND encrypted from pg_stat_gssapi where pid = pg_backend_pid();',
+	'SELECT gss_authenticated AND encrypted AND NOT credentials_proxied FROM pg_stat_gssapi WHERE pid = pg_backend_pid();',
 	0,
-	'gssencmode=require',
-	'succeeds with GSS-encrypted access required and hostgssenc hba',
+	'gssencmode=require gssdeleg=disable',
+	'succeeds with GSS-encrypted access required and hostgssenc hba and credentials not forwarded',
 	"connection authenticated: identity=\"test1\@$realm\" method=gss",
-	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, principal=test1\@$realm)"
+	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, proxy_credentials=no, principal=test1\@$realm)"
 );
 test_access($node, 'test1', 'SELECT true', 2, 'gssencmode=disable',
 	'fails with GSS encryption disabled and hostgssenc hba');
@@ -378,26 +492,42 @@ $node->restart;
 test_access(
 	$node,
 	'test1',
-	'SELECT gss_authenticated and not encrypted from pg_stat_gssapi where pid = pg_backend_pid();',
+	'SELECT gss_authenticated AND NOT encrypted AND credentials_proxied FROM pg_stat_gssapi WHERE pid = pg_backend_pid();',
 	0,
-	'gssencmode=prefer',
+	'gssencmode=prefer gssdeleg=enable',
 	'succeeds with GSS-encrypted access preferred and hostnogssenc hba, but no encryption',
 	"connection authenticated: identity=\"test1\@$realm\" method=gss",
-	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=no, principal=test1\@$realm)"
+	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=no, proxy_credentials=yes, principal=test1\@$realm)"
 );
 test_access($node, 'test1', 'SELECT true', 2, 'gssencmode=require',
 	'fails with GSS-encrypted access required and hostnogssenc hba');
 test_access(
 	$node,
 	'test1',
-	'SELECT gss_authenticated and not encrypted from pg_stat_gssapi where pid = pg_backend_pid();',
+	'SELECT gss_authenticated AND NOT encrypted AND credentials_proxied FROM pg_stat_gssapi WHERE pid = pg_backend_pid();',
 	0,
-	'gssencmode=disable',
+	'gssencmode=disable gssdeleg=enable',
 	'succeeds with GSS encryption disabled and hostnogssenc hba',
 	"connection authenticated: identity=\"test1\@$realm\" method=gss",
-	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=no, principal=test1\@$realm)"
+	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=no, proxy_credentials=yes, principal=test1\@$realm)"
 );
 
+test_query(
+	$node,
+	'test1',
+	"SELECT * FROM dblink('user=test1 dbname=$dbname host=$host hostaddr=$hostaddr port=$port password=1234','select 1') as t1(c1 int);",
+	qr/^1$/s,
+	'gssencmode=prefer gssdeleg=enable',
+	'dblink works not-encrypted');
+
+test_query(
+	$node,
+	'test1',
+	"TABLE tf1;",
+	qr/^1$/s,
+	'gssencmode=prefer gssdeleg=enable',
+	'postgres_fdw works not-encrypted');
+
 truncate($node->data_dir . '/pg_ident.conf', 0);
 unlink($node->data_dir . '/pg_hba.conf');
 $node->append_conf('pg_hba.conf',
@@ -407,14 +537,30 @@ $node->restart;
 test_access(
 	$node,
 	'test1',
-	'SELECT gss_authenticated AND encrypted from pg_stat_gssapi where pid = pg_backend_pid();',
+	'SELECT gss_authenticated AND encrypted AND credentials_proxied FROM pg_stat_gssapi WHERE pid = pg_backend_pid();',
 	0,
-	'',
+	'gssdeleg=enable',
 	'succeeds with include_realm=0 and defaults',
 	"connection authenticated: identity=\"test1\@$realm\" method=gss",
-	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, principal=test1\@$realm)"
+	"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, proxy_credentials=yes, principal=test1\@$realm)"
 );
 
+test_query(
+	$node,
+	'test1',
+	"SELECT * FROM dblink('user=test1 dbname=$dbname host=$host hostaddr=$hostaddr port=$port password=1234','select 1') as t1(c1 int);",
+	qr/^1$/s,
+	'gssencmode=require gssdeleg=enable',
+	'dblink works encrypted');
+
+test_query(
+	$node,
+	'test1',
+	"TABLE tf1;",
+	qr/^1$/s,
+	'gssencmode=require gssdeleg=enable',
+	'postgres_fdw works encrypted');
+
 # Reset pg_hba.conf, and cause a usermap failure with an authentication
 # that has passed.
 unlink($node->data_dir . '/pg_hba.conf');
diff --git a/src/test/perl/PostgreSQL/Test/Utils.pm b/src/test/perl/PostgreSQL/Test/Utils.pm
index 878e12b15e..9249954b49 100644
--- a/src/test/perl/PostgreSQL/Test/Utils.pm
+++ b/src/test/perl/PostgreSQL/Test/Utils.pm
@@ -65,6 +65,7 @@ our @EXPORT = qw(
   slurp_dir
   slurp_file
   append_to_file
+  string_replace_file
   check_mode_recursive
   chmod_recursive
   check_pg_config
@@ -549,6 +550,32 @@ sub append_to_file
 
 =pod
 
+=item string_replace_file(filename, find, replace)
+
+Find and replace string of a given file.
+
+=cut
+
+sub string_replace_file
+{
+	my ($filename, $find, $replace) = @_;
+	open(my $in, '<', $filename);
+	my $content;
+	while(<$in>)
+	{
+		$_ =~ s/$find/$replace/;
+		$content = $content.$_;
+	}
+	close $in;
+	open(my $out, '>', $filename);
+	print $out $content;
+	close($out);
+
+	return;
+}
+
+=pod
+
 =item check_mode_recursive(dir, expected_dir_mode, expected_file_mode, ignore_list)
 
 Check that all file/dir modes in a directory match the expected values,
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 174b725fff..9596a673ad 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1759,7 +1759,7 @@ pg_stat_activity| SELECT s.datid,
     s.query_id,
     s.query,
     s.backend_type
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, gss_proxy, leader_pid, query_id)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_all_indexes| SELECT c.oid AS relid,
@@ -1873,8 +1873,9 @@ pg_stat_database_conflicts| SELECT oid AS datid,
 pg_stat_gssapi| SELECT pid,
     gss_auth AS gss_authenticated,
     gss_princ AS principal,
-    gss_enc AS encrypted
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+    gss_enc AS encrypted,
+    gss_proxy AS credentials_proxied
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, gss_proxy, leader_pid, query_id)
   WHERE (client_port IS NOT NULL);
 pg_stat_io| SELECT backend_type,
     io_object,
@@ -2067,7 +2068,7 @@ pg_stat_replication| SELECT s.pid,
     w.sync_priority,
     w.sync_state,
     w.reply_time
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, gss_proxy, leader_pid, query_id)
      JOIN pg_stat_get_wal_senders() w(pid, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag, flush_lag, replay_lag, sync_priority, sync_state, reply_time) ON ((s.pid = w.pid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_replication_slots| SELECT s.slot_name,
@@ -2101,7 +2102,7 @@ pg_stat_ssl| SELECT pid,
     ssl_client_dn AS client_dn,
     ssl_client_serial AS client_serial,
     ssl_issuer_dn AS issuer_dn
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, gss_proxy, leader_pid, query_id)
   WHERE (client_port IS NOT NULL);
 pg_stat_subscription| SELECT su.oid AS subid,
     su.subname,
