Merge pull request #4217 from adelez/fix_coverage

Run code coverage no matter if tests failed or succeeded.
diff --git a/examples/objective-c/auth_sample/AuthTestService.podspec b/examples/objective-c/auth_sample/AuthTestService.podspec
index 9521d49..e935626 100644
--- a/examples/objective-c/auth_sample/AuthTestService.podspec
+++ b/examples/objective-c/auth_sample/AuthTestService.podspec
@@ -29,7 +29,7 @@
     ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}"
     ss.header_mappings_dir = dir
     ss.requires_arc = true
-    ss.dependency "gRPC", "~> 0.11"
+    ss.dependency "gRPC", "~> 0.12"
     ss.dependency "#{s.name}/Messages"
   end
 end
diff --git a/examples/objective-c/helloworld/HelloWorld.podspec b/examples/objective-c/helloworld/HelloWorld.podspec
index 600898f..bdf782f 100644
--- a/examples/objective-c/helloworld/HelloWorld.podspec
+++ b/examples/objective-c/helloworld/HelloWorld.podspec
@@ -29,7 +29,7 @@
     ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}"
     ss.header_mappings_dir = dir
     ss.requires_arc = true
-    ss.dependency "gRPC", "~> 0.11"
+    ss.dependency "gRPC", "~> 0.12"
     ss.dependency "#{s.name}/Messages"
   end
 end
diff --git a/examples/objective-c/route_guide/RouteGuide.podspec b/examples/objective-c/route_guide/RouteGuide.podspec
index e00f827..4bc2c42 100644
--- a/examples/objective-c/route_guide/RouteGuide.podspec
+++ b/examples/objective-c/route_guide/RouteGuide.podspec
@@ -29,7 +29,7 @@
     ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}"
     ss.header_mappings_dir = dir
     ss.requires_arc = true
-    ss.dependency "gRPC", "~> 0.11"
+    ss.dependency "gRPC", "~> 0.12"
     ss.dependency "#{s.name}/Messages"
   end
 end
diff --git a/gRPC.podspec b/gRPC.podspec
index 6700932..2797943 100644
--- a/gRPC.podspec
+++ b/gRPC.podspec
@@ -36,7 +36,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC'
-  version = '0.11.2'
+  version = '0.12.0'
   s.version  = version
   s.summary  = 'gRPC client library for iOS/OSX'
   s.homepage = 'http://www.grpc.io'
@@ -584,7 +584,7 @@
 
     ss.requires_arc = false
     ss.libraries = 'z'
-    ss.dependency 'OpenSSL', '~> 1.0.200'
+    ss.dependency 'OpenSSL', '~> 1.0.204.1'
 
     # ss.compiler_flags = '-GCC_WARN_INHIBIT_ALL_WARNINGS', '-w'
   end
diff --git a/include/grpc++/security/credentials.h b/include/grpc++/security/credentials.h
index cc827f0..e5652dc 100644
--- a/include/grpc++/security/credentials.h
+++ b/include/grpc++/security/credentials.h
@@ -38,6 +38,7 @@
 #include <memory>
 
 #include <grpc++/impl/grpc_library.h>
+#include <grpc++/security/auth_context.h>
 #include <grpc++/support/config.h>
 #include <grpc++/support/status.h>
 #include <grpc++/support/string_ref.h>
@@ -206,9 +207,17 @@
   // a different thread from the one processing the call.
   virtual bool IsBlocking() const { return true; }
 
+  // Type of credentials this plugin is implementing.
+  virtual const char* GetType() const { return ""; }
+
   // Gets the auth metatada produced by this plugin.
+  // The fully qualified method name is:
+  // service_url + "/" + method_name.
+  // The channel_auth_context contains (among other things), the identity of
+  // the server.
   virtual Status GetMetadata(
-      grpc::string_ref service_url,
+      grpc::string_ref service_url, grpc::string_ref method_name,
+      const AuthContext& channel_auth_context,
       std::multimap<grpc::string, grpc::string>* metadata) = 0;
 };
 
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index c8da593..655f45a 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -41,6 +41,81 @@
 extern "C" {
 #endif
 
+/* --- Authentication Context. --- */
+
+#define GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME "transport_security_type"
+#define GRPC_SSL_TRANSPORT_SECURITY_TYPE "ssl"
+
+#define GRPC_X509_CN_PROPERTY_NAME "x509_common_name"
+#define GRPC_X509_SAN_PROPERTY_NAME "x509_subject_alternative_name"
+
+typedef struct grpc_auth_context grpc_auth_context;
+
+typedef struct grpc_auth_property_iterator {
+  const grpc_auth_context *ctx;
+  size_t index;
+  const char *name;
+} grpc_auth_property_iterator;
+
+/* value, if not NULL, is guaranteed to be NULL terminated. */
+typedef struct grpc_auth_property {
+  char *name;
+  char *value;
+  size_t value_length;
+} grpc_auth_property;
+
+/* Returns NULL when the iterator is at the end. */
+const grpc_auth_property *grpc_auth_property_iterator_next(
+    grpc_auth_property_iterator *it);
+
+/* Iterates over the auth context. */
+grpc_auth_property_iterator grpc_auth_context_property_iterator(
+    const grpc_auth_context *ctx);
+
+/* Gets the peer identity. Returns an empty iterator (first _next will return
+   NULL) if the peer is not authenticated. */
+grpc_auth_property_iterator grpc_auth_context_peer_identity(
+    const grpc_auth_context *ctx);
+
+/* Finds a property in the context. May return an empty iterator (first _next
+   will return NULL) if no property with this name was found in the context. */
+grpc_auth_property_iterator grpc_auth_context_find_properties_by_name(
+    const grpc_auth_context *ctx, const char *name);
+
+/* Gets the name of the property that indicates the peer identity. Will return
+   NULL if the peer is not authenticated. */
+const char *grpc_auth_context_peer_identity_property_name(
+    const grpc_auth_context *ctx);
+
+/* Returns 1 if the peer is authenticated, 0 otherwise. */
+int grpc_auth_context_peer_is_authenticated(const grpc_auth_context *ctx);
+
+/* Gets the auth context from the call. Caller needs to call
+   grpc_auth_context_release on the returned context. */
+grpc_auth_context *grpc_call_auth_context(grpc_call *call);
+
+/* Releases the auth context returned from grpc_call_auth_context. */
+void grpc_auth_context_release(grpc_auth_context *context);
+
+/* --
+   The following auth context methods should only be called by a server metadata
+   processor to set properties extracted from auth metadata.
+   -- */
+
+/* Add a property. */
+void grpc_auth_context_add_property(grpc_auth_context *ctx, const char *name,
+                                    const char *value, size_t value_length);
+
+/* Add a C string property. */
+void grpc_auth_context_add_cstring_property(grpc_auth_context *ctx,
+                                            const char *name,
+                                            const char *value);
+
+/* Sets the property name. Returns 1 if successful or 0 in case of failure
+   (which means that no property with this name exists). */
+int grpc_auth_context_set_peer_identity_property_name(grpc_auth_context *ctx,
+                                                      const char *name);
+
 /* --- grpc_channel_credentials object. ---
 
    A channel credentials object represents a way to authenticate a client on a
@@ -165,6 +240,24 @@
     void *user_data, const grpc_metadata *creds_md, size_t num_creds_md,
     grpc_status_code status, const char *error_details);
 
+/* Context that can be used by metadata credentials plugin in order to create
+   auth related metadata. */
+typedef struct {
+  /* The fully qualifed service url. */
+  const char *service_url;
+
+  /* The method name of the RPC being called (not fully qualified).
+     The fully qualified method name can be built from the service_url:
+     full_qualified_method_name = ctx->service_url + '/' + ctx->method_name. */
+  const char *method_name;
+
+  /* The auth_context of the channel which gives the server's identity. */
+  const grpc_auth_context *channel_auth_context;
+
+  /* Reserved for future use. */
+  void *reserved;
+} grpc_auth_metadata_context;
+
 /* grpc_metadata_credentials plugin is an API user provided structure used to
    create grpc_credentials objects that can be set on a channel (composed) or
    a call. See grpc_credentials_metadata_create_from_plugin below.
@@ -172,11 +265,11 @@
    every call in scope for the credentials created from it. */
 typedef struct {
   /* The implementation of this method has to be non-blocking.
-     - service_url is the fully qualified URL that the client stack is
-       connecting to.
+     - context is the information that can be used by the plugin to create auth
+       metadata.
      - cb is the callback that needs to be called when the metadata is ready.
      - user_data needs to be passed as the first parameter of the callback. */
-  void (*get_metadata)(void *state, const char *service_url,
+  void (*get_metadata)(void *state, grpc_auth_metadata_context context,
                        grpc_credentials_plugin_metadata_cb cb, void *user_data);
 
   /* Destroys the plugin state. */
@@ -184,6 +277,9 @@
 
   /* State that will be set as the first parameter of the methods above. */
   void *state;
+
+  /* Type of credentials that this plugin is implementing. */
+  const char *type;
 } grpc_metadata_credentials_plugin;
 
 /* Creates a credentials object from a plugin. */
@@ -239,81 +335,6 @@
 grpc_call_error grpc_call_set_credentials(grpc_call *call,
                                           grpc_call_credentials *creds);
 
-/* --- Authentication Context. --- */
-
-#define GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME "transport_security_type"
-#define GRPC_SSL_TRANSPORT_SECURITY_TYPE "ssl"
-
-#define GRPC_X509_CN_PROPERTY_NAME "x509_common_name"
-#define GRPC_X509_SAN_PROPERTY_NAME "x509_subject_alternative_name"
-
-typedef struct grpc_auth_context grpc_auth_context;
-
-typedef struct grpc_auth_property_iterator {
-  const grpc_auth_context *ctx;
-  size_t index;
-  const char *name;
-} grpc_auth_property_iterator;
-
-/* value, if not NULL, is guaranteed to be NULL terminated. */
-typedef struct grpc_auth_property {
-  char *name;
-  char *value;
-  size_t value_length;
-} grpc_auth_property;
-
-/* Returns NULL when the iterator is at the end. */
-const grpc_auth_property *grpc_auth_property_iterator_next(
-    grpc_auth_property_iterator *it);
-
-/* Iterates over the auth context. */
-grpc_auth_property_iterator grpc_auth_context_property_iterator(
-    const grpc_auth_context *ctx);
-
-/* Gets the peer identity. Returns an empty iterator (first _next will return
-   NULL) if the peer is not authenticated. */
-grpc_auth_property_iterator grpc_auth_context_peer_identity(
-    const grpc_auth_context *ctx);
-
-/* Finds a property in the context. May return an empty iterator (first _next
-   will return NULL) if no property with this name was found in the context. */
-grpc_auth_property_iterator grpc_auth_context_find_properties_by_name(
-    const grpc_auth_context *ctx, const char *name);
-
-/* Gets the name of the property that indicates the peer identity. Will return
-   NULL if the peer is not authenticated. */
-const char *grpc_auth_context_peer_identity_property_name(
-    const grpc_auth_context *ctx);
-
-/* Returns 1 if the peer is authenticated, 0 otherwise. */
-int grpc_auth_context_peer_is_authenticated(const grpc_auth_context *ctx);
-
-/* Gets the auth context from the call. Caller needs to call
-   grpc_auth_context_release on the returned context. */
-grpc_auth_context *grpc_call_auth_context(grpc_call *call);
-
-/* Releases the auth context returned from grpc_call_auth_context. */
-void grpc_auth_context_release(grpc_auth_context *context);
-
-/* --
-   The following auth context methods should only be called by a server metadata
-   processor to set properties extracted from auth metadata.
-   -- */
-
-/* Add a property. */
-void grpc_auth_context_add_property(grpc_auth_context *ctx, const char *name,
-                                    const char *value, size_t value_length);
-
-/* Add a C string property. */
-void grpc_auth_context_add_cstring_property(grpc_auth_context *ctx,
-                                            const char *name,
-                                            const char *value);
-
-/* Sets the property name. Returns 1 if successful or 0 in case of failure
-   (which means that no property with this name exists). */
-int grpc_auth_context_set_peer_identity_property_name(grpc_auth_context *ctx,
-                                                      const char *name);
-
 /* --- Auth Metadata Processing --- */
 
 /* Callback function that is called when the metadata processing is done.
diff --git a/package.json b/package.json
index 1fd0ffb..9517c59 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "grpc",
-  "version": "0.11.1",
+  "version": "0.12.0",
   "author": "Google Inc.",
   "description": "gRPC Library for Node",
   "homepage": "http://www.grpc.io/",
diff --git a/src/core/security/client_auth_filter.c b/src/core/security/client_auth_filter.c
index be2522a..d3d948a 100644
--- a/src/core/security/client_auth_filter.c
+++ b/src/core/security/client_auth_filter.c
@@ -61,7 +61,7 @@
   grpc_transport_stream_op op;
   gpr_uint8 security_context_set;
   grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT];
-  char *service_url;
+  grpc_auth_metadata_context auth_md_context;
 } call_data;
 
 /* We can have a per-channel credentials. */
@@ -74,11 +74,20 @@
   grpc_mdstr *status_key;
 } channel_data;
 
-static void reset_service_url(call_data *calld) {
-  if (calld->service_url != NULL) {
-    gpr_free(calld->service_url);
-    calld->service_url = NULL;
+static void reset_auth_metadata_context(
+    grpc_auth_metadata_context *auth_md_context) {
+  if (auth_md_context->service_url != NULL) {
+    gpr_free((char *)auth_md_context->service_url);
+    auth_md_context->service_url = NULL;
   }
+  if (auth_md_context->method_name != NULL) {
+    gpr_free((char *)auth_md_context->method_name);
+    auth_md_context->method_name = NULL;
+  }
+  GRPC_AUTH_CONTEXT_UNREF(
+      (grpc_auth_context *)auth_md_context->channel_auth_context,
+      "grpc_auth_metadata_context");
+  auth_md_context->channel_auth_context = NULL;
 }
 
 static void bubble_up_error(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
@@ -99,7 +108,7 @@
   grpc_transport_stream_op *op = &calld->op;
   grpc_metadata_batch *mdb;
   size_t i;
-  reset_service_url(calld);
+  reset_auth_metadata_context(&calld->auth_md_context);
   if (status != GRPC_CREDENTIALS_OK) {
     bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED,
                     "Credentials failed to get metadata.");
@@ -117,9 +126,13 @@
   grpc_call_next_op(exec_ctx, elem, op);
 }
 
-void build_service_url(const char *url_scheme, call_data *calld) {
+void build_auth_metadata_context(grpc_security_connector *sc,
+                                 call_data *calld) {
   char *service = gpr_strdup(grpc_mdstr_as_c_string(calld->method));
   char *last_slash = strrchr(service, '/');
+  char *method_name = NULL;
+  char *service_url = NULL;
+  reset_auth_metadata_context(&calld->auth_md_context);
   if (last_slash == NULL) {
     gpr_log(GPR_ERROR, "No '/' found in fully qualified method name");
     service[0] = '\0';
@@ -128,11 +141,16 @@
     service[1] = '\0';
   } else {
     *last_slash = '\0';
+    method_name = gpr_strdup(last_slash + 1);
   }
-  if (url_scheme == NULL) url_scheme = "";
-  reset_service_url(calld);
-  gpr_asprintf(&calld->service_url, "%s://%s%s", url_scheme,
+  if (method_name == NULL) method_name = gpr_strdup("");
+  gpr_asprintf(&service_url, "%s://%s%s",
+               sc->url_scheme == NULL ? "" : sc->url_scheme,
                grpc_mdstr_as_c_string(calld->host), service);
+  calld->auth_md_context.service_url = service_url;
+  calld->auth_md_context.method_name = method_name;
+  calld->auth_md_context.channel_auth_context =
+      GRPC_AUTH_CONTEXT_REF(sc->auth_context, "grpc_auth_metadata_context");
   gpr_free(service);
 }
 
@@ -166,12 +184,12 @@
         call_creds_has_md ? ctx->creds : channel_call_creds);
   }
 
-  build_service_url(chand->security_connector->base.url_scheme, calld);
+  build_auth_metadata_context(&chand->security_connector->base, calld);
   calld->op = *op; /* Copy op (originates from the caller's stack). */
   GPR_ASSERT(calld->pollset);
-  grpc_call_credentials_get_request_metadata(exec_ctx, calld->creds,
-                                             calld->pollset, calld->service_url,
-                                             on_credentials_metadata, elem);
+  grpc_call_credentials_get_request_metadata(
+      exec_ctx, calld->creds, calld->pollset, calld->auth_md_context,
+      on_credentials_metadata, elem);
 }
 
 static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data,
@@ -285,7 +303,7 @@
   if (calld->method != NULL) {
     GRPC_MDSTR_UNREF(calld->method);
   }
-  reset_service_url(calld);
+  reset_auth_metadata_context(&calld->auth_md_context);
 }
 
 /* Constructor for channel_data */
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
index f7a2e73..543c750 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -33,16 +33,16 @@
 
 #include "src/core/security/credentials.h"
 
-#include <string.h>
 #include <stdio.h>
+#include <string.h>
 
 #include "src/core/channel/channel_args.h"
 #include "src/core/channel/http_client_filter.h"
-#include "src/core/json/json.h"
 #include "src/core/httpcli/httpcli.h"
 #include "src/core/iomgr/iomgr.h"
-#include "src/core/surface/api_trace.h"
+#include "src/core/json/json.h"
 #include "src/core/support/string.h"
+#include "src/core/surface/api_trace.h"
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
@@ -116,19 +116,17 @@
   grpc_call_credentials_unref(creds);
 }
 
-void grpc_call_credentials_get_request_metadata(grpc_exec_ctx *exec_ctx,
-                                                grpc_call_credentials *creds,
-                                                grpc_pollset *pollset,
-                                                const char *service_url,
-                                                grpc_credentials_metadata_cb cb,
-                                                void *user_data) {
+void grpc_call_credentials_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+    grpc_pollset *pollset, grpc_auth_metadata_context context,
+    grpc_credentials_metadata_cb cb, void *user_data) {
   if (creds == NULL || creds->vtable->get_request_metadata == NULL) {
     if (cb != NULL) {
       cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
     }
     return;
   }
-  creds->vtable->get_request_metadata(exec_ctx, creds, pollset, service_url, cb,
+  creds->vtable->get_request_metadata(exec_ctx, creds, pollset, context, cb,
                                       user_data);
 }
 
@@ -429,7 +427,7 @@
 static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
                                      grpc_call_credentials *creds,
                                      grpc_pollset *pollset,
-                                     const char *service_url,
+                                     grpc_auth_metadata_context context,
                                      grpc_credentials_metadata_cb cb,
                                      void *user_data) {
   grpc_service_account_jwt_access_credentials *c =
@@ -442,7 +440,7 @@
   {
     gpr_mu_lock(&c->cache_mu);
     if (c->cached.service_url != NULL &&
-        strcmp(c->cached.service_url, service_url) == 0 &&
+        strcmp(c->cached.service_url, context.service_url) == 0 &&
         c->cached.jwt_md != NULL &&
         (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration,
                                    gpr_now(GPR_CLOCK_REALTIME)),
@@ -457,14 +455,15 @@
     /* Generate a new jwt. */
     gpr_mu_lock(&c->cache_mu);
     jwt_reset_cache(c);
-    jwt = grpc_jwt_encode_and_sign(&c->key, service_url, c->jwt_lifetime, NULL);
+    jwt = grpc_jwt_encode_and_sign(&c->key, context.service_url,
+                                   c->jwt_lifetime, NULL);
     if (jwt != NULL) {
       char *md_value;
       gpr_asprintf(&md_value, "Bearer %s", jwt);
       gpr_free(jwt);
       c->cached.jwt_expiration =
           gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime);
-      c->cached.service_url = gpr_strdup(service_url);
+      c->cached.service_url = gpr_strdup(context.service_url);
       c->cached.jwt_md = grpc_credentials_md_store_create(1);
       grpc_credentials_md_store_add_cstrings(
           c->cached.jwt_md, GRPC_AUTHORIZATION_METADATA_KEY, md_value);
@@ -649,7 +648,7 @@
 
 static void oauth2_token_fetcher_get_request_metadata(
     grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
-    grpc_pollset *pollset, const char *service_url,
+    grpc_pollset *pollset, grpc_auth_metadata_context context,
     grpc_credentials_metadata_cb cb, void *user_data) {
   grpc_oauth2_token_fetcher_credentials *c =
       (grpc_oauth2_token_fetcher_credentials *)creds;
@@ -804,12 +803,10 @@
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
-static void md_only_test_get_request_metadata(grpc_exec_ctx *exec_ctx,
-                                              grpc_call_credentials *creds,
-                                              grpc_pollset *pollset,
-                                              const char *service_url,
-                                              grpc_credentials_metadata_cb cb,
-                                              void *user_data) {
+static void md_only_test_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+    grpc_pollset *pollset, grpc_auth_metadata_context context,
+    grpc_credentials_metadata_cb cb, void *user_data) {
   grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
 
   if (c->is_async) {
@@ -846,12 +843,10 @@
   grpc_credentials_md_store_unref(c->access_token_md);
 }
 
-static void access_token_get_request_metadata(grpc_exec_ctx *exec_ctx,
-                                              grpc_call_credentials *creds,
-                                              grpc_pollset *pollset,
-                                              const char *service_url,
-                                              grpc_credentials_metadata_cb cb,
-                                              void *user_data) {
+static void access_token_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+    grpc_pollset *pollset, grpc_auth_metadata_context context,
+    grpc_credentials_metadata_cb cb, void *user_data) {
   grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
   cb(exec_ctx, user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK);
 }
@@ -932,7 +927,7 @@
   grpc_composite_call_credentials *composite_creds;
   size_t creds_index;
   grpc_credentials_md_store *md_elems;
-  char *service_url;
+  grpc_auth_metadata_context auth_md_context;
   void *user_data;
   grpc_pollset *pollset;
   grpc_credentials_metadata_cb cb;
@@ -950,7 +945,6 @@
 static void composite_call_md_context_destroy(
     grpc_composite_call_credentials_metadata_context *ctx) {
   grpc_credentials_md_store_unref(ctx->md_elems);
-  if (ctx->service_url != NULL) gpr_free(ctx->service_url);
   gpr_free(ctx);
 }
 
@@ -978,9 +972,9 @@
   if (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
     grpc_call_credentials *inner_creds =
         ctx->composite_creds->inner.creds_array[ctx->creds_index++];
-    grpc_call_credentials_get_request_metadata(exec_ctx, inner_creds,
-                                               ctx->pollset, ctx->service_url,
-                                               composite_call_metadata_cb, ctx);
+    grpc_call_credentials_get_request_metadata(
+        exec_ctx, inner_creds, ctx->pollset, ctx->auth_md_context,
+        composite_call_metadata_cb, ctx);
     return;
   }
 
@@ -990,26 +984,24 @@
   composite_call_md_context_destroy(ctx);
 }
 
-static void composite_call_get_request_metadata(grpc_exec_ctx *exec_ctx,
-                                                grpc_call_credentials *creds,
-                                                grpc_pollset *pollset,
-                                                const char *service_url,
-                                                grpc_credentials_metadata_cb cb,
-                                                void *user_data) {
+static void composite_call_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+    grpc_pollset *pollset, grpc_auth_metadata_context auth_md_context,
+    grpc_credentials_metadata_cb cb, void *user_data) {
   grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
   grpc_composite_call_credentials_metadata_context *ctx;
 
   ctx = gpr_malloc(sizeof(grpc_composite_call_credentials_metadata_context));
   memset(ctx, 0, sizeof(grpc_composite_call_credentials_metadata_context));
-  ctx->service_url = gpr_strdup(service_url);
+  ctx->auth_md_context = auth_md_context;
   ctx->user_data = user_data;
   ctx->cb = cb;
   ctx->composite_creds = c;
   ctx->pollset = pollset;
   ctx->md_elems = grpc_credentials_md_store_create(c->inner.num_creds);
   grpc_call_credentials_get_request_metadata(
-      exec_ctx, c->inner.creds_array[ctx->creds_index++], pollset, service_url,
-      composite_call_metadata_cb, ctx);
+      exec_ctx, c->inner.creds_array[ctx->creds_index++], pollset,
+      auth_md_context, composite_call_metadata_cb, ctx);
 }
 
 static grpc_call_credentials_vtable composite_call_credentials_vtable = {
@@ -1103,7 +1095,7 @@
 static void iam_get_request_metadata(grpc_exec_ctx *exec_ctx,
                                      grpc_call_credentials *creds,
                                      grpc_pollset *pollset,
-                                     const char *service_url,
+                                     grpc_auth_metadata_context context,
                                      grpc_credentials_metadata_cb cb,
                                      void *user_data) {
   grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
@@ -1192,7 +1184,7 @@
 static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
                                         grpc_call_credentials *creds,
                                         grpc_pollset *pollset,
-                                        const char *service_url,
+                                        grpc_auth_metadata_context context,
                                         grpc_credentials_metadata_cb cb,
                                         void *user_data) {
   grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
@@ -1201,7 +1193,7 @@
     memset(request, 0, sizeof(*request));
     request->user_data = user_data;
     request->cb = cb;
-    c->plugin.get_metadata(c->plugin.state, service_url,
+    c->plugin.get_metadata(c->plugin.state, context,
                            plugin_md_request_metadata_ready, request);
   } else {
     cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
@@ -1218,7 +1210,7 @@
                  (reserved));
   GPR_ASSERT(reserved == NULL);
   memset(c, 0, sizeof(*c));
-  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_METADATA_PLUGIN;
+  c->base.type = plugin.type;
   c->base.vtable = &plugin_vtable;
   gpr_ref_init(&c->base.refcount, 1);
   c->plugin = plugin;
diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h
index 1320609..6d45895 100644
--- a/src/core/security/credentials.h
+++ b/src/core/security/credentials.h
@@ -59,7 +59,6 @@
   "FakeTransportSecurity"
 
 #define GRPC_CALL_CREDENTIALS_TYPE_OAUTH2 "Oauth2"
-#define GRPC_CALL_CREDENTIALS_TYPE_METADATA_PLUGIN "Plugin"
 #define GRPC_CALL_CREDENTIALS_TYPE_JWT "Jwt"
 #define GRPC_CALL_CREDENTIALS_TYPE_IAM "Iam"
 #define GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE "Composite"
@@ -162,7 +161,7 @@
   void (*destruct)(grpc_call_credentials *c);
   void (*get_request_metadata)(grpc_exec_ctx *exec_ctx,
                                grpc_call_credentials *c, grpc_pollset *pollset,
-                               const char *service_url,
+                               grpc_auth_metadata_context context,
                                grpc_credentials_metadata_cb cb,
                                void *user_data);
 } grpc_call_credentials_vtable;
@@ -175,12 +174,10 @@
 
 grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds);
 void grpc_call_credentials_unref(grpc_call_credentials *creds);
-void grpc_call_credentials_get_request_metadata(grpc_exec_ctx *exec_ctx,
-                                                grpc_call_credentials *creds,
-                                                grpc_pollset *pollset,
-                                                const char *service_url,
-                                                grpc_credentials_metadata_cb cb,
-                                                void *user_data);
+void grpc_call_credentials_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+    grpc_pollset *pollset, grpc_auth_metadata_context context,
+    grpc_credentials_metadata_cb cb, void *user_data);
 
 typedef struct {
   grpc_call_credentials **creds_array;
diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc
index a1b9a30..6409323 100644
--- a/src/cpp/client/secure_credentials.cc
+++ b/src/cpp/client/secure_credentials.cc
@@ -37,6 +37,7 @@
 #include <grpc++/support/channel_arguments.h>
 #include "src/cpp/client/create_channel_internal.h"
 #include "src/cpp/client/secure_credentials.h"
+#include "src/cpp/common/secure_auth_context.h"
 
 namespace grpc {
 
@@ -160,7 +161,7 @@
 }
 
 void MetadataCredentialsPluginWrapper::GetMetadata(
-    void* wrapper, const char* service_url,
+    void* wrapper, grpc_auth_metadata_context context,
     grpc_credentials_plugin_metadata_cb cb, void* user_data) {
   GPR_ASSERT(wrapper);
   MetadataCredentialsPluginWrapper* w =
@@ -171,18 +172,25 @@
   }
   if (w->plugin_->IsBlocking()) {
     w->thread_pool_->Add(
-        std::bind(&MetadataCredentialsPluginWrapper::InvokePlugin, w,
-                  service_url, cb, user_data));
+        std::bind(&MetadataCredentialsPluginWrapper::InvokePlugin, w, context,
+                  cb, user_data));
   } else {
-    w->InvokePlugin(service_url, cb, user_data);
+    w->InvokePlugin(context, cb, user_data);
   }
 }
 
 void MetadataCredentialsPluginWrapper::InvokePlugin(
-    const char* service_url, grpc_credentials_plugin_metadata_cb cb,
+    grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb,
     void* user_data) {
   std::multimap<grpc::string, grpc::string> metadata;
-  Status status = plugin_->GetMetadata(service_url, &metadata);
+
+  // const_cast is safe since the SecureAuthContext does not take owndership and
+  // the object is passed as a const ref to plugin_->GetMetadata.
+  SecureAuthContext cpp_channel_auth_context(
+      const_cast<grpc_auth_context*>(context.channel_auth_context), false);
+
+  Status status = plugin_->GetMetadata(context.service_url, context.method_name,
+                                       cpp_channel_auth_context, &metadata);
   std::vector<grpc_metadata> md;
   for (auto it = metadata.begin(); it != metadata.end(); ++it) {
     grpc_metadata md_entry;
@@ -204,11 +212,12 @@
 std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin(
     std::unique_ptr<MetadataCredentialsPlugin> plugin) {
   GrpcLibrary init;  // To call grpc_init().
+  const char* type = plugin->GetType();
   MetadataCredentialsPluginWrapper* wrapper =
       new MetadataCredentialsPluginWrapper(std::move(plugin));
   grpc_metadata_credentials_plugin c_plugin = {
       MetadataCredentialsPluginWrapper::GetMetadata,
-      MetadataCredentialsPluginWrapper::Destroy, wrapper};
+      MetadataCredentialsPluginWrapper::Destroy, wrapper, type};
   return WrapCallCredentials(
       grpc_metadata_credentials_create_from_plugin(c_plugin, nullptr));
 }
diff --git a/src/cpp/client/secure_credentials.h b/src/cpp/client/secure_credentials.h
index e9afa9e..cef5929 100644
--- a/src/cpp/client/secure_credentials.h
+++ b/src/cpp/client/secure_credentials.h
@@ -79,7 +79,7 @@
 class MetadataCredentialsPluginWrapper GRPC_FINAL {
  public:
   static void Destroy(void* wrapper);
-  static void GetMetadata(void* wrapper, const char* service_url,
+  static void GetMetadata(void* wrapper, grpc_auth_metadata_context context,
                           grpc_credentials_plugin_metadata_cb cb,
                           void* user_data);
 
@@ -87,7 +87,7 @@
       std::unique_ptr<MetadataCredentialsPlugin> plugin);
 
  private:
-  void InvokePlugin(const char* service_url,
+  void InvokePlugin(grpc_auth_metadata_context context,
                     grpc_credentials_plugin_metadata_cb cb, void* user_data);
   std::unique_ptr<ThreadPoolInterface> thread_pool_;
   std::unique_ptr<MetadataCredentialsPlugin> plugin_;
diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs
index e9ec30e..818ddb8 100644
--- a/src/csharp/Grpc.Core/VersionInfo.cs
+++ b/src/csharp/Grpc.Core/VersionInfo.cs
@@ -41,6 +41,6 @@
         /// <summary>
         /// Current version of gRPC C#
         /// </summary>
-        public const string CurrentVersion = "0.7.1";
+        public const string CurrentVersion = "0.12.0";
     }
 }
diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat
index b864a95..45f6b26 100644
--- a/src/csharp/build_packages.bat
+++ b/src/csharp/build_packages.bat
@@ -1,8 +1,8 @@
 @rem Builds gRPC NuGet packages
 
 @rem Current package versions
-set VERSION=0.7.1
-set CORE_VERSION=0.11.1
+set VERSION=0.12.0
+set CORE_VERSION=0.12.0
 set PROTOBUF_VERSION=3.0.0-alpha4
 
 @rem Packages that depend on prerelease packages (like Google.Protobuf) need to have prerelease suffix as well.
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index 1839319..b8705c4 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -930,11 +930,12 @@
   void *state, const char *service_url, grpc_credentials_plugin_metadata_cb cb,
   void *user_data, gpr_int32 is_destroy);
 
-static void grpcsharp_get_metadata_handler(void *state, const char *service_url,
-  grpc_credentials_plugin_metadata_cb cb, void *user_data) {
+static void grpcsharp_get_metadata_handler(
+    void *state, grpc_auth_metadata_context context,
+    grpc_credentials_plugin_metadata_cb cb, void *user_data) {
   grpcsharp_metadata_interceptor_func interceptor =
       (grpcsharp_metadata_interceptor_func)(gpr_intptr)state;
-  interceptor(state, service_url, cb, user_data, 0);
+  interceptor(state, context.service_url, cb, user_data, 0);
 }
 
 static void grpcsharp_metadata_credentials_destroy_handler(void *state) {
@@ -949,6 +950,7 @@
   plugin.get_metadata = grpcsharp_get_metadata_handler;
   plugin.destroy = grpcsharp_metadata_credentials_destroy_handler;
   plugin.state = (void*)(gpr_intptr)metadata_interceptor;
+  plugin.type = "";
   return grpc_metadata_credentials_create_from_plugin(plugin, NULL);
 }
 
diff --git a/src/node/ext/byte_buffer.cc b/src/node/ext/byte_buffer.cc
index e1786dd..c306292 100644
--- a/src/node/ext/byte_buffer.cc
+++ b/src/node/ext/byte_buffer.cc
@@ -77,6 +77,7 @@
   while (grpc_byte_buffer_reader_next(&reader, &next) != 0) {
     memcpy(result + offset, GPR_SLICE_START_PTR(next), GPR_SLICE_LENGTH(next));
     offset += GPR_SLICE_LENGTH(next);
+    gpr_slice_unref(next);
   }
   return scope.Escape(MakeFastBuffer(
       Nan::NewBuffer(result, length).ToLocalChecked()));
diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc
index a98ae85..c0e2b0f 100644
--- a/src/node/ext/call.cc
+++ b/src/node/ext/call.cc
@@ -234,6 +234,14 @@
 
 class SendMessageOp : public Op {
  public:
+  SendMessageOp() {
+    send_message = NULL;
+  }
+  ~SendMessageOp() {
+    if (send_message != NULL) {
+      grpc_byte_buffer_destroy(send_message);
+    }
+  }
   Local<Value> GetNodeValue() const {
     EscapableHandleScope scope;
     return scope.Escape(Nan::True());
@@ -253,7 +261,8 @@
         out->flags = maybe_flag.FromMaybe(0) & GRPC_WRITE_USED_MASK;
       }
     }
-    out->data.send_message = BufferToByteBuffer(value);
+    send_message = BufferToByteBuffer(value);
+    out->data.send_message = send_message;
     PersistentValue *handle = new PersistentValue(value);
     resources->handles.push_back(unique_ptr<PersistentValue>(handle));
     return true;
@@ -262,6 +271,8 @@
   std::string GetTypeString() const {
     return "send_message";
   }
+ private:
+  grpc_byte_buffer *send_message;
 };
 
 class SendClientCloseOp : public Op {
diff --git a/src/node/ext/call_credentials.cc b/src/node/ext/call_credentials.cc
index 9c5d9d2..8cbfb1e 100644
--- a/src/node/ext/call_credentials.cc
+++ b/src/node/ext/call_credentials.cc
@@ -162,6 +162,7 @@
   plugin.get_metadata = plugin_get_metadata;
   plugin.destroy = plugin_destroy_state;
   plugin.state = reinterpret_cast<void*>(state);
+  plugin.type = "";
   grpc_call_credentials *creds = grpc_metadata_credentials_create_from_plugin(
       plugin, NULL);
   info.GetReturnValue().Set(WrapStruct(creds));
@@ -225,7 +226,7 @@
   uv_close((uv_handle_t *)async, (uv_close_cb)free);
 }
 
-void plugin_get_metadata(void *state, const char *service_url,
+void plugin_get_metadata(void *state, grpc_auth_metadata_context context,
                          grpc_credentials_plugin_metadata_cb cb,
                          void *user_data) {
   uv_async_t *async = static_cast<uv_async_t*>(malloc(sizeof(uv_async_t)));
@@ -234,7 +235,7 @@
                 SendPluginCallback);
   plugin_callback_data *data = new plugin_callback_data;
   data->state = reinterpret_cast<plugin_state*>(state);
-  data->service_url = service_url;
+  data->service_url = context.service_url;
   data->cb = cb;
   data->user_data = user_data;
   async->data = data;
diff --git a/src/node/ext/call_credentials.h b/src/node/ext/call_credentials.h
index 1cd8d8d..a9bfe30 100644
--- a/src/node/ext/call_credentials.h
+++ b/src/node/ext/call_credentials.h
@@ -84,7 +84,7 @@
   void *user_data;
 } plugin_callback_data;
 
-void plugin_get_metadata(void *state, const char *service_url,
+void plugin_get_metadata(void *state, grpc_auth_metadata_context context,
                          grpc_credentials_plugin_metadata_cb cb,
                          void *user_data);
 
diff --git a/src/objective-c/README.md b/src/objective-c/README.md
index c1d25b9..30d9aad 100644
--- a/src/objective-c/README.md
+++ b/src/objective-c/README.md
@@ -48,8 +48,8 @@
   s.version  = '0.0.1'
   s.license  = '...'
 
-  s.ios.deployment_target = '6.0'
-  s.osx.deployment_target = '10.8'
+  s.ios.deployment_target = '7.1'
+  s.osx.deployment_target = '10.9'
 
   # Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients.
   # You can run this command manually if you later change your protos and need to regenerate.
@@ -60,7 +60,7 @@
     ms.source_files = "*.pbobjc.{h,m}"
     ms.header_mappings_dir = "."
     ms.requires_arc = false
-    ms.dependency "Protobuf", "~> 3.0.0-alpha-3"
+    ms.dependency "Protobuf", "~> 3.0.0-alpha-4"
   end
 
   # The --objcgrpc_out plugin generates a pair of .pbrpc.h/.pbrpc.m files for each .proto file with
@@ -69,7 +69,7 @@
     ss.source_files = "*.pbrpc.{h,m}"
     ss.header_mappings_dir = "."
     ss.requires_arc = true
-    ss.dependency "gRPC", "~> 0.5"
+    ss.dependency "gRPC", "~> 0.12"
     ss.dependency "#{s.name}/Messages"
   end
 end
@@ -156,7 +156,7 @@
 
 You need to compile the generated `.pbobjc.*` files (the enums and messages) without ARC support,
 and the generated `.pbrpc.*` files (the services) with ARC support. The generated code depends on
-v0.5+ of the Objective-C gRPC runtime library and v3.0.0-alpha-3+ of the Objective-C Protobuf
+v0.12+ of the Objective-C gRPC runtime library and v3.0.0-alpha-4+ of the Objective-C Protobuf
 runtime library.
 
 These libraries need to be integrated into your project as described in their respective Podspec
diff --git a/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec b/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec
index d4f8084..5addf26f 100644
--- a/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec
+++ b/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec
@@ -3,8 +3,8 @@
   s.version  = "0.0.1"
   s.license  = "New BSD"
 
-  s.ios.deployment_target = "6.0"
-  s.osx.deployment_target = "10.8"
+  s.ios.deployment_target = '7.1'
+  s.osx.deployment_target = '10.9'
 
   # Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients.
   s.prepare_command = <<-CMD
@@ -22,7 +22,7 @@
     ss.source_files = "*.pbrpc.{h,m}"
     ss.header_mappings_dir = "."
     ss.requires_arc = true
-    ss.dependency "gRPC", "~> 0.7"
+    ss.dependency "gRPC", "~> 0.12"
     ss.dependency "#{s.name}/Messages"
   end
 end
diff --git a/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec b/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec
index 8710753..6ecef05 100644
--- a/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec
+++ b/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec
@@ -3,8 +3,8 @@
   s.version  = "0.0.1"
   s.license  = "New BSD"
 
-  s.ios.deployment_target = "6.0"
-  s.osx.deployment_target = "10.8"
+  s.ios.deployment_target = '7.1'
+  s.osx.deployment_target = '10.9'
 
   # Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients.
   s.prepare_command = <<-CMD
@@ -18,14 +18,14 @@
     ms.source_files = "*.pbobjc.{h,m}"
     ms.header_mappings_dir = "."
     ms.requires_arc = false
-    ms.dependency "Protobuf", "~> 3.0.0-alpha-3"
+    ms.dependency "Protobuf", "~> 3.0.0-alpha-4"
   end
 
   s.subspec "Services" do |ss|
     ss.source_files = "*.pbrpc.{h,m}"
     ss.header_mappings_dir = "."
     ss.requires_arc = true
-    ss.dependency "gRPC", "~> 0.5"
+    ss.dependency "gRPC", "~> 0.12"
     ss.dependency "#{s.name}/Messages"
   end
 end
diff --git a/src/objective-c/tests/run_tests.sh b/src/objective-c/tests/run_tests.sh
index 598f4e7..c4fc564 100755
--- a/src/objective-c/tests/run_tests.sh
+++ b/src/objective-c/tests/run_tests.sh
@@ -51,4 +51,5 @@
     -scheme AllTests \
     -destination name="iPhone 6" \
     test \
-    | egrep "$XCODEBUILD_FILTER" -
+    | egrep "$XCODEBUILD_FILTER" \
+    | egrep -v "(GPBDictionary|GPBArray)" -
diff --git a/templates/gRPC.podspec.template b/templates/gRPC.podspec.template
index 3885cb3..de5ed7c 100644
--- a/templates/gRPC.podspec.template
+++ b/templates/gRPC.podspec.template
@@ -54,7 +54,7 @@
   %>
   Pod::Spec.new do |s|
     s.name     = 'gRPC'
-    version = '0.11.2'
+    version = '0.12.0'
     s.version  = version
     s.summary  = 'gRPC client library for iOS/OSX'
     s.homepage = 'http://www.grpc.io'
@@ -97,7 +97,7 @@
 
       ss.requires_arc = false
       ss.libraries = 'z'
-      ss.dependency 'OpenSSL', '~> 1.0.200'
+      ss.dependency 'OpenSSL', '~> 1.0.204.1'
 
       # ss.compiler_flags = '-GCC_WARN_INHIBIT_ALL_WARNINGS', '-w'
     end
diff --git a/test/core/client_config/lb_policies_test.c b/test/core/client_config/lb_policies_test.c
index 5aa8140..6f218e7 100644
--- a/test/core/client_config/lb_policies_test.c
+++ b/test/core/client_config/lb_policies_test.c
@@ -135,9 +135,8 @@
   gpr_log(GPR_INFO, "KILLING SERVER %d", i);
   GPR_ASSERT(f->servers[i] != NULL);
   grpc_server_shutdown_and_notify(f->servers[i], f->cq, tag(10000));
-  GPR_ASSERT(
-      grpc_completion_queue_pluck(f->cq, tag(10000), n_millis_time(5000), NULL)
-          .type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(10000), n_millis_time(5000),
+                                         NULL).type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->servers[i]);
   f->servers[i] = NULL;
 }
@@ -203,8 +202,8 @@
     if (f->servers[i] == NULL) continue;
     grpc_server_shutdown_and_notify(f->servers[i], f->cq, tag(10000));
     GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(10000),
-                                           n_millis_time(5000), NULL)
-                   .type == GRPC_OP_COMPLETE);
+                                           n_millis_time(5000),
+                                           NULL).type == GRPC_OP_COMPLETE);
     grpc_server_destroy(f->servers[i]);
   }
   grpc_completion_queue_shutdown(f->cq);
@@ -304,8 +303,8 @@
 
     s_idx = -1;
     while ((ev = grpc_completion_queue_next(
-                f->cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1), NULL))
-               .type != GRPC_QUEUE_TIMEOUT) {
+                f->cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1), NULL)).type !=
+           GRPC_QUEUE_TIMEOUT) {
       GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
       read_tag = ((int)(gpr_intptr)ev.tag);
       gpr_log(GPR_DEBUG, "EVENT: success:%d, type:%d, tag:%d iter:%d",
diff --git a/test/core/client_config/set_initial_connect_string_test.c b/test/core/client_config/set_initial_connect_string_test.c
index 13517b7..ceca56c 100644
--- a/test/core/client_config/set_initial_connect_string_test.c
+++ b/test/core/client_config/set_initial_connect_string_test.c
@@ -66,15 +66,15 @@
 
 static void handle_read(grpc_exec_ctx *exec_ctx, void *arg, int success) {
   GPR_ASSERT(success);
-  gpr_slice_buffer_move_into(
-    &state.temp_incoming_buffer, &state.incoming_buffer);
+  gpr_slice_buffer_move_into(&state.temp_incoming_buffer,
+                             &state.incoming_buffer);
   if (state.incoming_buffer.length > strlen(magic_connect_string)) {
     state.done = 1;
     grpc_endpoint_shutdown(exec_ctx, state.tcp);
     grpc_endpoint_destroy(exec_ctx, state.tcp);
   } else {
-    grpc_endpoint_read(
-      exec_ctx, state.tcp, &state.temp_incoming_buffer, &on_read);
+    grpc_endpoint_read(exec_ctx, state.tcp, &state.temp_incoming_buffer,
+                       &on_read);
   }
 }
 
diff --git a/test/core/end2end/tests/hpack_size.c b/test/core/end2end/tests/hpack_size.c
index 297ea8d..997969d 100644
--- a/test/core/end2end/tests/hpack_size.c
+++ b/test/core/end2end/tests/hpack_size.c
@@ -262,9 +262,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
-                 .type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
+                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
+                                         NULL).type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c
index 4cfef7b..b2b7cfd 100644
--- a/test/core/security/credentials_test.c
+++ b/test/core/security/credentials_test.c
@@ -126,6 +126,8 @@
 static const char test_service_url[] = "https://foo.com/foo.v1";
 static const char other_test_service_url[] = "https://bar.com/bar.v1";
 
+static const char test_method[] = "ThisIsNotAMethod";
+
 /* -- Utils. -- */
 
 static char *test_json_key_str(void) {
@@ -352,9 +354,10 @@
   grpc_call_credentials *creds = grpc_google_iam_credentials_create(
       test_google_iam_authorization_token, test_google_iam_authority_selector,
       NULL);
-  grpc_call_credentials_get_request_metadata(&exec_ctx, creds, NULL,
-                                             test_service_url,
-                                             check_google_iam_metadata, creds);
+  grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+                                            NULL};
+  grpc_call_credentials_get_request_metadata(
+      &exec_ctx, creds, NULL, auth_md_ctx, check_google_iam_metadata, creds);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
@@ -375,10 +378,11 @@
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_call_credentials *creds =
       grpc_access_token_credentials_create("blah", NULL);
+  grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+                                            NULL};
   GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0);
   grpc_call_credentials_get_request_metadata(
-      &exec_ctx, creds, NULL, test_service_url, check_access_token_metadata,
-      creds);
+      &exec_ctx, creds, NULL, auth_md_ctx, check_access_token_metadata, creds);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
@@ -430,6 +434,8 @@
 static void test_oauth2_google_iam_composite_creds(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   const grpc_call_credentials_array *creds_array;
+  grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+                                            NULL};
   grpc_call_credentials *oauth2_creds = grpc_md_only_test_credentials_create(
       "authorization", test_oauth2_bearer_token, 0);
   grpc_call_credentials *google_iam_creds = grpc_google_iam_credentials_create(
@@ -450,7 +456,7 @@
   GPR_ASSERT(strcmp(creds_array->creds_array[1]->type,
                     GRPC_CALL_CREDENTIALS_TYPE_IAM) == 0);
   grpc_call_credentials_get_request_metadata(
-      &exec_ctx, composite_creds, NULL, test_service_url,
+      &exec_ctx, composite_creds, NULL, auth_md_ctx,
       check_oauth2_google_iam_composite_metadata, composite_creds);
   grpc_exec_ctx_finish(&exec_ctx);
 }
@@ -578,12 +584,14 @@
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_call_credentials *compute_engine_creds =
       grpc_google_compute_engine_credentials_create(NULL);
+  grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+                                            NULL};
 
   /* First request: http get should be called. */
   grpc_httpcli_set_override(compute_engine_httpcli_get_success_override,
                             httpcli_post_should_not_be_called);
   grpc_call_credentials_get_request_metadata(
-      &exec_ctx, compute_engine_creds, NULL, test_service_url,
+      &exec_ctx, compute_engine_creds, NULL, auth_md_ctx,
       on_oauth2_creds_get_metadata_success, (void *)test_user_data);
   grpc_exec_ctx_flush(&exec_ctx);
 
@@ -591,7 +599,7 @@
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             httpcli_post_should_not_be_called);
   grpc_call_credentials_get_request_metadata(
-      &exec_ctx, compute_engine_creds, NULL, test_service_url,
+      &exec_ctx, compute_engine_creds, NULL, auth_md_ctx,
       on_oauth2_creds_get_metadata_success, (void *)test_user_data);
   grpc_exec_ctx_finish(&exec_ctx);
 
@@ -601,12 +609,14 @@
 
 static void test_compute_engine_creds_failure(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+                                            NULL};
   grpc_call_credentials *compute_engine_creds =
       grpc_google_compute_engine_credentials_create(NULL);
   grpc_httpcli_set_override(compute_engine_httpcli_get_failure_override,
                             httpcli_post_should_not_be_called);
   grpc_call_credentials_get_request_metadata(
-      &exec_ctx, compute_engine_creds, NULL, test_service_url,
+      &exec_ctx, compute_engine_creds, NULL, auth_md_ctx,
       on_oauth2_creds_get_metadata_failure, (void *)test_user_data);
   grpc_call_credentials_unref(compute_engine_creds);
   grpc_httpcli_set_override(NULL, NULL);
@@ -658,6 +668,8 @@
 
 static void test_refresh_token_creds_success(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+                                            NULL};
   grpc_call_credentials *refresh_token_creds =
       grpc_google_refresh_token_credentials_create(test_refresh_token_str,
                                                    NULL);
@@ -666,7 +678,7 @@
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             refresh_token_httpcli_post_success);
   grpc_call_credentials_get_request_metadata(
-      &exec_ctx, refresh_token_creds, NULL, test_service_url,
+      &exec_ctx, refresh_token_creds, NULL, auth_md_ctx,
       on_oauth2_creds_get_metadata_success, (void *)test_user_data);
   grpc_exec_ctx_flush(&exec_ctx);
 
@@ -674,7 +686,7 @@
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             httpcli_post_should_not_be_called);
   grpc_call_credentials_get_request_metadata(
-      &exec_ctx, refresh_token_creds, NULL, test_service_url,
+      &exec_ctx, refresh_token_creds, NULL, auth_md_ctx,
       on_oauth2_creds_get_metadata_success, (void *)test_user_data);
   grpc_exec_ctx_flush(&exec_ctx);
 
@@ -685,13 +697,15 @@
 
 static void test_refresh_token_creds_failure(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+                                            NULL};
   grpc_call_credentials *refresh_token_creds =
       grpc_google_refresh_token_credentials_create(test_refresh_token_str,
                                                    NULL);
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             refresh_token_httpcli_post_failure);
   grpc_call_credentials_get_request_metadata(
-      &exec_ctx, refresh_token_creds, NULL, test_service_url,
+      &exec_ctx, refresh_token_creds, NULL, auth_md_ctx,
       on_oauth2_creds_get_metadata_failure, (void *)test_user_data);
   grpc_call_credentials_unref(refresh_token_creds);
   grpc_httpcli_set_override(NULL, NULL);
@@ -774,6 +788,8 @@
 static void test_jwt_creds_success(void) {
   char *json_key_string = test_json_key_str();
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+                                            NULL};
   grpc_call_credentials *jwt_creds =
       grpc_service_account_jwt_access_credentials_create(
           json_key_string, grpc_max_auth_token_lifetime, NULL);
@@ -781,7 +797,7 @@
   /* First request: jwt_encode_and_sign should be called. */
   grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
   grpc_call_credentials_get_request_metadata(
-      &exec_ctx, jwt_creds, NULL, test_service_url,
+      &exec_ctx, jwt_creds, NULL, auth_md_ctx,
       on_jwt_creds_get_metadata_success, (void *)test_user_data);
   grpc_exec_ctx_flush(&exec_ctx);
 
@@ -789,15 +805,16 @@
   grpc_jwt_encode_and_sign_set_override(
       encode_and_sign_jwt_should_not_be_called);
   grpc_call_credentials_get_request_metadata(
-      &exec_ctx, jwt_creds, NULL, test_service_url,
+      &exec_ctx, jwt_creds, NULL, auth_md_ctx,
       on_jwt_creds_get_metadata_success, (void *)test_user_data);
   grpc_exec_ctx_flush(&exec_ctx);
 
   /* Third request: Different service url so jwt_encode_and_sign should be
      called again (no caching). */
+  auth_md_ctx.service_url = other_test_service_url;
   grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
   grpc_call_credentials_get_request_metadata(
-      &exec_ctx, jwt_creds, NULL, other_test_service_url,
+      &exec_ctx, jwt_creds, NULL, auth_md_ctx,
       on_jwt_creds_get_metadata_success, (void *)test_user_data);
   grpc_exec_ctx_flush(&exec_ctx);
 
@@ -809,13 +826,15 @@
 static void test_jwt_creds_signing_failure(void) {
   char *json_key_string = test_json_key_str();
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+                                            NULL};
   grpc_call_credentials *jwt_creds =
       grpc_service_account_jwt_access_credentials_create(
           json_key_string, grpc_max_auth_token_lifetime, NULL);
 
   grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_failure);
   grpc_call_credentials_get_request_metadata(
-      &exec_ctx, jwt_creds, NULL, test_service_url,
+      &exec_ctx, jwt_creds, NULL, auth_md_ctx,
       on_jwt_creds_get_metadata_failure, (void *)test_user_data);
 
   gpr_free(json_key_string);
@@ -886,13 +905,17 @@
 
 static const plugin_metadata plugin_md[] = {{"foo", "bar"}, {"hi", "there"}};
 
-static void plugin_get_metadata_success(void *state, const char *service_url,
+static void plugin_get_metadata_success(void *state,
+                                        grpc_auth_metadata_context context,
                                         grpc_credentials_plugin_metadata_cb cb,
                                         void *user_data) {
   size_t i;
   grpc_metadata md[GPR_ARRAY_SIZE(plugin_md)];
   plugin_state *s = (plugin_state *)state;
-  GPR_ASSERT(strcmp(service_url, test_service_url) == 0);
+  GPR_ASSERT(strcmp(context.service_url, test_service_url) == 0);
+  GPR_ASSERT(strcmp(context.method_name, test_method) == 0);
+  GPR_ASSERT(context.channel_auth_context == NULL);
+  GPR_ASSERT(context.reserved == NULL);
   *s = PLUGIN_GET_METADATA_CALLED_STATE;
   for (i = 0; i < GPR_ARRAY_SIZE(plugin_md); i++) {
     memset(&md[i], 0, sizeof(grpc_metadata));
@@ -903,11 +926,15 @@
   cb(user_data, md, GPR_ARRAY_SIZE(md), GRPC_STATUS_OK, NULL);
 }
 
-static void plugin_get_metadata_failure(void *state, const char *service_url,
+static void plugin_get_metadata_failure(void *state,
+                                        grpc_auth_metadata_context context,
                                         grpc_credentials_plugin_metadata_cb cb,
                                         void *user_data) {
   plugin_state *s = (plugin_state *)state;
-  GPR_ASSERT(strcmp(service_url, test_service_url) == 0);
+  GPR_ASSERT(strcmp(context.service_url, test_service_url) == 0);
+  GPR_ASSERT(strcmp(context.method_name, test_method) == 0);
+  GPR_ASSERT(context.channel_auth_context == NULL);
+  GPR_ASSERT(context.reserved == NULL);
   *s = PLUGIN_GET_METADATA_CALLED_STATE;
   cb(user_data, NULL, 0, GRPC_STATUS_UNAUTHENTICATED,
      "Could not get metadata for plugin.");
@@ -945,6 +972,8 @@
   plugin_state state = PLUGIN_INITIAL_STATE;
   grpc_metadata_credentials_plugin plugin;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+                                            NULL};
 
   plugin.state = &state;
   plugin.get_metadata = plugin_get_metadata_success;
@@ -953,8 +982,8 @@
   creds = grpc_metadata_credentials_create_from_plugin(plugin, NULL);
   GPR_ASSERT(state == PLUGIN_INITIAL_STATE);
   grpc_call_credentials_get_request_metadata(
-      &exec_ctx, creds, NULL, test_service_url,
-      on_plugin_metadata_received_success, NULL);
+      &exec_ctx, creds, NULL, auth_md_ctx, on_plugin_metadata_received_success,
+      NULL);
   GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE);
   grpc_call_credentials_release(creds);
   GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE);
@@ -966,6 +995,8 @@
   plugin_state state = PLUGIN_INITIAL_STATE;
   grpc_metadata_credentials_plugin plugin;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+                                            NULL};
 
   plugin.state = &state;
   plugin.get_metadata = plugin_get_metadata_failure;
@@ -974,8 +1005,8 @@
   creds = grpc_metadata_credentials_create_from_plugin(plugin, NULL);
   GPR_ASSERT(state == PLUGIN_INITIAL_STATE);
   grpc_call_credentials_get_request_metadata(
-      &exec_ctx, creds, NULL, test_service_url,
-      on_plugin_metadata_received_failure, NULL);
+      &exec_ctx, creds, NULL, auth_md_ctx, on_plugin_metadata_received_failure,
+      NULL);
   GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE);
   grpc_call_credentials_release(creds);
   GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE);
diff --git a/test/core/security/oauth2_utils.c b/test/core/security/oauth2_utils.c
index fcfe8a6..fb62bf4 100644
--- a/test/core/security/oauth2_utils.c
+++ b/test/core/security/oauth2_utils.c
@@ -80,13 +80,16 @@
   oauth2_request request;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_closure do_nothing_closure;
+  grpc_auth_metadata_context null_ctx = {"", "", NULL, NULL};
+
   grpc_pollset_init(&request.pollset);
   request.is_done = 0;
 
   grpc_closure_init(&do_nothing_closure, do_nothing, NULL);
 
   grpc_call_credentials_get_request_metadata(&exec_ctx, creds, &request.pollset,
-                                             "", on_oauth2_response, &request);
+                                             null_ctx, on_oauth2_response,
+                                             &request);
 
   grpc_exec_ctx_finish(&exec_ctx);
 
diff --git a/test/core/security/print_google_default_creds_token.c b/test/core/security/print_google_default_creds_token.c
index eb63724..50fe61c 100644
--- a/test/core/security/print_google_default_creds_token.c
+++ b/test/core/security/print_google_default_creds_token.c
@@ -74,10 +74,13 @@
   synchronizer sync;
   grpc_channel_credentials *creds = NULL;
   char *service_url = "https://test.foo.google.com/Foo";
+  grpc_auth_metadata_context context;
   gpr_cmdline *cl = gpr_cmdline_create("print_google_default_creds_token");
   gpr_cmdline_add_string(cl, "service_url",
                          "Service URL for the token request.", &service_url);
   gpr_cmdline_parse(cl, argc, argv);
+  memset(&context, 0, sizeof(context));
+  context.service_url = service_url;
 
   grpc_init();
 
@@ -93,7 +96,7 @@
 
   grpc_call_credentials_get_request_metadata(
       &exec_ctx, ((grpc_composite_channel_credentials *)creds)->call_creds,
-      &sync.pollset, service_url, on_metadata_response, &sync);
+      &sync.pollset, context, on_metadata_response, &sync);
 
   gpr_mu_lock(GRPC_POLLSET_MU(&sync.pollset));
   while (!sync.is_done) {
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index 6da9333..dd02c4a 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -119,10 +119,13 @@
 
   bool IsBlocking() const GRPC_OVERRIDE { return is_blocking_; }
 
-  Status GetMetadata(grpc::string_ref service_url,
+  Status GetMetadata(grpc::string_ref service_url, grpc::string_ref method_name,
+                     const grpc::AuthContext& channel_auth_context,
                      std::multimap<grpc::string, grpc::string>* metadata)
       GRPC_OVERRIDE {
     EXPECT_GT(service_url.length(), 0UL);
+    EXPECT_GT(method_name.length(), 0UL);
+    EXPECT_TRUE(channel_auth_context.IsPeerAuthenticated());
     EXPECT_TRUE(metadata != nullptr);
     if (is_successful_) {
       metadata->insert(std::make_pair(kMetadataKey, metadata_value_));