From 3c957e60a3901d2d56ce57e2c1b900a8c3697ea7 Mon Sep 17 00:00:00 2001
From: Julien Boeuf <jboeuf@google.com>
Date: Wed, 18 Nov 2015 21:33:58 -0800
Subject: [PATCH] Fixing implementations.

---
 include/grpc/grpc_security.h                  |  3 +-
 src/core/security/client_auth_filter.c        | 47 ++++++++----
 src/core/security/credentials.c               | 72 +++++++++---------
 src/core/security/credentials.h               |  4 +-
 src/cpp/client/secure_credentials.cc          |  6 +-
 src/cpp/client/secure_credentials.h           |  2 +-
 src/csharp/ext/grpc_csharp_ext.c              |  7 +-
 src/node/ext/call_credentials.cc              |  4 +-
 test/core/security/credentials_test.c         | 74 +++++++++++++------
 test/core/security/oauth2_utils.c             |  4 +-
 .../print_google_default_creds_token.c        |  5 +-
 11 files changed, 145 insertions(+), 83 deletions(-)

diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index 108240d7486..4f3efae4be5 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -246,7 +246,8 @@ typedef struct {
   /* The fully qualifed service url. */
   const char *service_url;
 
-  /* The method name of the RPC being called (not fully qualified). */
+  /* The method name of the RPC being called (not fully qualified).
+     Can be NULL if no method name was found. */
   const char *method_name;
 
   /* The auth_context of the channel which gives the server's identity. */
diff --git a/src/core/security/client_auth_filter.c b/src/core/security/client_auth_filter.c
index f257502a989..d822164233d 100644
--- a/src/core/security/client_auth_filter.c
+++ b/src/core/security/client_auth_filter.c
@@ -63,7 +63,7 @@ typedef struct {
   int sent_initial_metadata;
   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. */
@@ -76,11 +76,20 @@ typedef struct {
   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,
@@ -101,7 +110,7 @@ static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
   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.");
@@ -120,9 +129,13 @@ static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
   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';
@@ -131,11 +144,15 @@ void build_service_url(const char *url_scheme, call_data *calld) {
     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,
+  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);
 }
 
@@ -169,12 +186,12 @@ static void send_security_metadata(grpc_exec_ctx *exec_ctx,
         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,
@@ -297,7 +314,7 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
   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 5c9d89c7646..806f9a6f1c5 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>
@@ -117,15 +117,16 @@ void grpc_call_credentials_release(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) {
+    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);
 }
 
@@ -207,8 +208,7 @@ grpc_arg grpc_server_credentials_to_arg(grpc_server_credentials *p) {
   return arg;
 }
 
-grpc_server_credentials *grpc_server_credentials_from_arg(
-    const grpc_arg *arg) {
+grpc_server_credentials *grpc_server_credentials_from_arg(const grpc_arg *arg) {
   if (strcmp(arg->key, GRPC_SERVER_CREDENTIALS_ARG) != 0) return NULL;
   if (arg->type != GRPC_ARG_POINTER) {
     gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type,
@@ -424,9 +424,12 @@ static void jwt_destruct(grpc_call_credentials *creds) {
   gpr_mu_destroy(&c->cache_mu);
 }
 
-static void jwt_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 jwt_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_service_account_jwt_access_credentials *c =
       (grpc_service_account_jwt_access_credentials *)creds;
   gpr_timespec refresh_threshold = gpr_time_from_seconds(
@@ -437,7 +440,7 @@ static void jwt_get_request_metadata(
   {
     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)),
@@ -452,14 +455,15 @@ static void jwt_get_request_metadata(
     /* 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);
@@ -644,7 +648,7 @@ static void on_oauth2_token_fetcher_http_response(
 
 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;
@@ -800,8 +804,9 @@ static void on_simulated_token_fetch_done(void *user_data) {
 }
 
 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) {
+    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) {
@@ -839,8 +844,9 @@ static void access_token_destruct(grpc_call_credentials *creds) {
 }
 
 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) {
+    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);
 }
@@ -921,7 +927,7 @@ typedef struct {
   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;
@@ -939,7 +945,6 @@ static void composite_call_destruct(grpc_call_credentials *creds) {
 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);
 }
 
@@ -967,9 +972,9 @@ static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
   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;
   }
 
@@ -980,22 +985,23 @@ static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
 }
 
 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) {
+    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 = {
@@ -1089,7 +1095,7 @@ static void iam_destruct(grpc_call_credentials *creds) {
 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;
@@ -1098,7 +1104,7 @@ static void iam_get_request_metadata(grpc_exec_ctx *exec_ctx,
 }
 
 static grpc_call_credentials_vtable iam_vtable = {iam_destruct,
-                                             iam_get_request_metadata};
+                                                  iam_get_request_metadata};
 
 grpc_call_credentials *grpc_google_iam_credentials_create(
     const char *token, const char *authority_selector, void *reserved) {
@@ -1178,7 +1184,7 @@ static void plugin_md_request_metadata_ready(void *request,
 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;
@@ -1187,7 +1193,7 @@ static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
     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);
diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h
index 5189a6d8167..79caee7f99d 100644
--- a/src/core/security/credentials.h
+++ b/src/core/security/credentials.h
@@ -162,7 +162,7 @@ typedef struct {
   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;
@@ -178,7 +178,7 @@ 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_auth_metadata_context context,
                                                 grpc_credentials_metadata_cb cb,
                                                 void *user_data);
 
diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc
index a1b9a3018e8..fa374f808a0 100644
--- a/src/cpp/client/secure_credentials.cc
+++ b/src/cpp/client/secure_credentials.cc
@@ -160,7 +160,7 @@ void MetadataCredentialsPluginWrapper::Destroy(void* wrapper) {
 }
 
 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 =
@@ -172,9 +172,9 @@ void MetadataCredentialsPluginWrapper::GetMetadata(
   if (w->plugin_->IsBlocking()) {
     w->thread_pool_->Add(
         std::bind(&MetadataCredentialsPluginWrapper::InvokePlugin, w,
-                  service_url, cb, user_data));
+                  context.service_url, cb, user_data));
   } else {
-    w->InvokePlugin(service_url, cb, user_data);
+    w->InvokePlugin(context.service_url, cb, user_data);
   }
 }
 
diff --git a/src/cpp/client/secure_credentials.h b/src/cpp/client/secure_credentials.h
index b241761a7c4..b8fe075dc7d 100644
--- a/src/cpp/client/secure_credentials.h
+++ b/src/cpp/client/secure_credentials.h
@@ -80,7 +80,7 @@ class SecureCallCredentials GRPC_FINAL : public CallCredentials {
 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);
 
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index 183931936e7..e6a2664c53d 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -930,11 +930,12 @@ typedef void(GPR_CALLTYPE *grpcsharp_metadata_interceptor_func)(
   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) {
diff --git a/src/node/ext/call_credentials.cc b/src/node/ext/call_credentials.cc
index 9c5d9d291b7..d0d7140bb44 100644
--- a/src/node/ext/call_credentials.cc
+++ b/src/node/ext/call_credentials.cc
@@ -225,7 +225,7 @@ NAUV_WORK_CB(SendPluginCallback) {
   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 +234,7 @@ void plugin_get_metadata(void *state, const char *service_url,
                 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/test/core/security/credentials_test.c b/test/core/security/credentials_test.c
index dcb35e53096..ad17b059f16 100644
--- a/test/core/security/credentials_test.c
+++ b/test/core/security/credentials_test.c
@@ -126,6 +126,8 @@ static const char test_signed_jwt[] =
 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 @@ static void test_google_iam_creds(void) {
   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,9 +378,11 @@ static void test_access_token_creds(void) {
   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,
+      &exec_ctx, creds, NULL, auth_md_ctx, check_access_token_metadata,
       creds);
   grpc_exec_ctx_finish(&exec_ctx);
 }
@@ -430,6 +435,8 @@ static void check_oauth2_google_iam_composite_metadata(
 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(
@@ -449,7 +456,7 @@ static void test_oauth2_google_iam_composite_creds(void) {
   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);
 }
@@ -576,12 +583,14 @@ static void test_compute_engine_creds_success(void) {
   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);
 
@@ -589,7 +598,7 @@ static void test_compute_engine_creds_success(void) {
   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);
 
@@ -599,12 +608,14 @@ static void test_compute_engine_creds_success(void) {
 
 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);
@@ -656,6 +667,8 @@ static int refresh_token_httpcli_post_failure(
 
 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);
@@ -664,7 +677,7 @@ static void test_refresh_token_creds_success(void) {
   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);
 
@@ -672,7 +685,7 @@ static void test_refresh_token_creds_success(void) {
   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);
 
@@ -683,13 +696,15 @@ static void test_refresh_token_creds_success(void) {
 
 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);
@@ -772,6 +787,8 @@ static void on_jwt_creds_get_metadata_failure(grpc_exec_ctx *exec_ctx,
 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);
@@ -779,7 +796,7 @@ static void test_jwt_creds_success(void) {
   /* 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);
 
@@ -787,15 +804,16 @@ static void test_jwt_creds_success(void) {
   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);
 
@@ -807,13 +825,15 @@ static void test_jwt_creds_success(void) {
 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);
@@ -884,13 +904,17 @@ typedef struct {
 
 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));
@@ -901,11 +925,15 @@ static void plugin_get_metadata_success(void *state, const char *service_url,
   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.");
@@ -943,6 +971,8 @@ static void test_metadata_plugin_success(void) {
   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;
@@ -951,7 +981,7 @@ static void test_metadata_plugin_success(void) {
   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,
+      &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);
@@ -964,6 +994,8 @@ static void test_metadata_plugin_failure(void) {
   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;
@@ -972,7 +1004,7 @@ static void test_metadata_plugin_failure(void) {
   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,
+      &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);
diff --git a/test/core/security/oauth2_utils.c b/test/core/security/oauth2_utils.c
index fcfe8a63777..a283a881e0d 100644
--- a/test/core/security/oauth2_utils.c
+++ b/test/core/security/oauth2_utils.c
@@ -80,13 +80,15 @@ char *grpc_test_fetch_oauth2_token_with_credentials(
   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 eb637247153..50fe61c9969 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 @@ int main(int argc, char **argv) {
   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 @@ int main(int argc, char **argv) {
 
   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) {