diff --git a/BUILD b/BUILD
index c30fd5b6fa372b7b962893a4d23ca59d18b08584..72a496dce1a395a1f624fd779b0e3acc657caf70 100644
--- a/BUILD
+++ b/BUILD
@@ -727,7 +727,6 @@ cc_library(
     "include/grpc++/client_context.h",
     "include/grpc++/completion_queue.h",
     "include/grpc++/create_channel.h",
-    "include/grpc++/credentials.h",
     "include/grpc++/generic/async_generic_service.h",
     "include/grpc++/generic/generic_stub.h",
     "include/grpc++/impl/call.h",
@@ -744,13 +743,15 @@ cc_library(
     "include/grpc++/impl/thd.h",
     "include/grpc++/impl/thd_cxx11.h",
     "include/grpc++/impl/thd_no_cxx11.h",
+    "include/grpc++/security/auth_context.h",
+    "include/grpc++/security/auth_metadata_processor.h",
+    "include/grpc++/security/credentials.h",
+    "include/grpc++/security/server_credentials.h",
     "include/grpc++/server.h",
     "include/grpc++/server_builder.h",
     "include/grpc++/server_context.h",
-    "include/grpc++/server_credentials.h",
     "include/grpc++/support/async_stream.h",
     "include/grpc++/support/async_unary_call.h",
-    "include/grpc++/support/auth_context.h",
     "include/grpc++/support/byte_buffer.h",
     "include/grpc++/support/channel_arguments.h",
     "include/grpc++/support/config.h",
@@ -816,7 +817,6 @@ cc_library(
     "include/grpc++/client_context.h",
     "include/grpc++/completion_queue.h",
     "include/grpc++/create_channel.h",
-    "include/grpc++/credentials.h",
     "include/grpc++/generic/async_generic_service.h",
     "include/grpc++/generic/generic_stub.h",
     "include/grpc++/impl/call.h",
@@ -833,13 +833,15 @@ cc_library(
     "include/grpc++/impl/thd.h",
     "include/grpc++/impl/thd_cxx11.h",
     "include/grpc++/impl/thd_no_cxx11.h",
+    "include/grpc++/security/auth_context.h",
+    "include/grpc++/security/auth_metadata_processor.h",
+    "include/grpc++/security/credentials.h",
+    "include/grpc++/security/server_credentials.h",
     "include/grpc++/server.h",
     "include/grpc++/server_builder.h",
     "include/grpc++/server_context.h",
-    "include/grpc++/server_credentials.h",
     "include/grpc++/support/async_stream.h",
     "include/grpc++/support/async_unary_call.h",
-    "include/grpc++/support/auth_context.h",
     "include/grpc++/support/byte_buffer.h",
     "include/grpc++/support/channel_arguments.h",
     "include/grpc++/support/config.h",
diff --git a/Makefile b/Makefile
index 1d1ce18b9faf6c4a317a485f16c2bc1334532c5b..1c2fca3154d42f6a124152448ff571e2b90c297f 100644
--- a/Makefile
+++ b/Makefile
@@ -4591,7 +4591,6 @@ PUBLIC_HEADERS_CXX += \
     include/grpc++/client_context.h \
     include/grpc++/completion_queue.h \
     include/grpc++/create_channel.h \
-    include/grpc++/credentials.h \
     include/grpc++/generic/async_generic_service.h \
     include/grpc++/generic/generic_stub.h \
     include/grpc++/impl/call.h \
@@ -4608,13 +4607,15 @@ PUBLIC_HEADERS_CXX += \
     include/grpc++/impl/thd.h \
     include/grpc++/impl/thd_cxx11.h \
     include/grpc++/impl/thd_no_cxx11.h \
+    include/grpc++/security/auth_context.h \
+    include/grpc++/security/auth_metadata_processor.h \
+    include/grpc++/security/credentials.h \
+    include/grpc++/security/server_credentials.h \
     include/grpc++/server.h \
     include/grpc++/server_builder.h \
     include/grpc++/server_context.h \
-    include/grpc++/server_credentials.h \
     include/grpc++/support/async_stream.h \
     include/grpc++/support/async_unary_call.h \
-    include/grpc++/support/auth_context.h \
     include/grpc++/support/byte_buffer.h \
     include/grpc++/support/channel_arguments.h \
     include/grpc++/support/config.h \
@@ -4835,7 +4836,6 @@ PUBLIC_HEADERS_CXX += \
     include/grpc++/client_context.h \
     include/grpc++/completion_queue.h \
     include/grpc++/create_channel.h \
-    include/grpc++/credentials.h \
     include/grpc++/generic/async_generic_service.h \
     include/grpc++/generic/generic_stub.h \
     include/grpc++/impl/call.h \
@@ -4852,13 +4852,15 @@ PUBLIC_HEADERS_CXX += \
     include/grpc++/impl/thd.h \
     include/grpc++/impl/thd_cxx11.h \
     include/grpc++/impl/thd_no_cxx11.h \
+    include/grpc++/security/auth_context.h \
+    include/grpc++/security/auth_metadata_processor.h \
+    include/grpc++/security/credentials.h \
+    include/grpc++/security/server_credentials.h \
     include/grpc++/server.h \
     include/grpc++/server_builder.h \
     include/grpc++/server_context.h \
-    include/grpc++/server_credentials.h \
     include/grpc++/support/async_stream.h \
     include/grpc++/support/async_unary_call.h \
-    include/grpc++/support/auth_context.h \
     include/grpc++/support/byte_buffer.h \
     include/grpc++/support/channel_arguments.h \
     include/grpc++/support/config.h \
diff --git a/build.json b/build.json
index cec692bdb7d5121019d8775177daeae6cefa4b78..1e00771ee330079a93e423ad8c6f27df77ef3a9f 100644
--- a/build.json
+++ b/build.json
@@ -36,7 +36,6 @@
         "include/grpc++/client_context.h",
         "include/grpc++/completion_queue.h",
         "include/grpc++/create_channel.h",
-        "include/grpc++/credentials.h",
         "include/grpc++/generic/async_generic_service.h",
         "include/grpc++/generic/generic_stub.h",
         "include/grpc++/impl/call.h",
@@ -53,13 +52,15 @@
         "include/grpc++/impl/thd.h",
         "include/grpc++/impl/thd_cxx11.h",
         "include/grpc++/impl/thd_no_cxx11.h",
+        "include/grpc++/security/auth_context.h",
+        "include/grpc++/security/auth_metadata_processor.h",
+        "include/grpc++/security/credentials.h",
+        "include/grpc++/security/server_credentials.h",
         "include/grpc++/server.h",
         "include/grpc++/server_builder.h",
         "include/grpc++/server_context.h",
-        "include/grpc++/server_credentials.h",
         "include/grpc++/support/async_stream.h",
         "include/grpc++/support/async_unary_call.h",
-        "include/grpc++/support/auth_context.h",
         "include/grpc++/support/byte_buffer.h",
         "include/grpc++/support/channel_arguments.h",
         "include/grpc++/support/config.h",
diff --git a/include/grpc++/client_context.h b/include/grpc++/client_context.h
index 62e5260a180476d589bba414f5c1550833e2d3f7..917a1222a8e10a4ff53e433e00db550c8954511a 100644
--- a/include/grpc++/client_context.h
+++ b/include/grpc++/client_context.h
@@ -42,7 +42,7 @@
 #include <grpc/grpc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
-#include <grpc++/support/auth_context.h>
+#include <grpc++/security/auth_context.h>
 #include <grpc++/support/config.h>
 #include <grpc++/support/status.h>
 #include <grpc++/support/string_ref.h>
diff --git a/include/grpc++/create_channel.h b/include/grpc++/create_channel.h
index 916f3b0b97c0e133e539b0bccb59c5d5937d14cd..72f05174e18d52e12b620ba242fc25bce602631e 100644
--- a/include/grpc++/create_channel.h
+++ b/include/grpc++/create_channel.h
@@ -36,7 +36,7 @@
 
 #include <memory>
 
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 #include <grpc++/support/channel_arguments.h>
 #include <grpc++/support/config.h>
 
diff --git a/include/grpc++/support/auth_context.h b/include/grpc++/security/auth_context.h
similarity index 90%
rename from include/grpc++/support/auth_context.h
rename to include/grpc++/security/auth_context.h
index 67e3e66c05b3141a36638d7fff37e1ea79ee753b..fc2701e806c24f5351bf8a7e77ab28ae21665f9a 100644
--- a/include/grpc++/support/auth_context.h
+++ b/include/grpc++/security/auth_context.h
@@ -77,6 +77,9 @@ class AuthContext {
  public:
   virtual ~AuthContext() {}
 
+  // Returns true if the peer is authenticated.
+  virtual bool IsPeerAuthenticated() const = 0;
+
   // A peer identity, in general is one or more properties (in which case they
   // have the same name).
   virtual std::vector<grpc::string_ref> GetPeerIdentity() const = 0;
@@ -89,6 +92,11 @@ class AuthContext {
   // Iteration over all the properties.
   virtual AuthPropertyIterator begin() const = 0;
   virtual AuthPropertyIterator end() const = 0;
+
+  // Mutation functions: should only be used by an AuthMetadataProcessor.
+  virtual void AddProperty(const grpc::string& key,
+                           const grpc::string_ref& value) = 0;
+  virtual bool SetPeerIdentityPropertyName(const grpc::string& name) = 0;
 };
 
 }  // namespace grpc
diff --git a/include/grpc++/security/auth_metadata_processor.h b/include/grpc++/security/auth_metadata_processor.h
new file mode 100644
index 0000000000000000000000000000000000000000..18ad9223217334d068821e84fdbd3043075dfdd5
--- /dev/null
+++ b/include/grpc++/security/auth_metadata_processor.h
@@ -0,0 +1,74 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPCXX_AUTH_METADATA_PROCESSOR_H_
+#define GRPCXX_AUTH_METADATA_PROCESSOR_H_
+
+#include <map>
+
+#include <grpc++/security/auth_context.h>
+#include <grpc++/support/status.h>
+#include <grpc++/support/string_ref.h>
+
+namespace grpc {
+
+class AuthMetadataProcessor {
+ public:
+  typedef std::multimap<grpc::string_ref, grpc::string_ref> InputMetadata;
+  typedef std::multimap<grpc::string, grpc::string_ref> OutputMetadata;
+
+  virtual ~AuthMetadataProcessor() {}
+
+  // If this method returns true, the Process function will be scheduled in
+  // a different thread from the one processing the call.
+  virtual bool IsBlocking() const { return true; }
+
+  // context is read/write: it contains the properties of the channel peer and
+  // it is the job of the Process method to augment it with properties derived
+  // from the passed-in auth_metadata.
+  // consumed_auth_metadata needs to be filled with metadata that has been
+  // consumed by the processor and will be removed from the call.
+  // response_metadata is the metadata that will be sent as part of the
+  // response.
+  // If the return value is not Status::OK, the rpc call will be aborted with
+  // the error code and error message sent back to the client.
+  virtual Status Process(const InputMetadata& auth_metadata,
+                         AuthContext* context,
+                         OutputMetadata* consumed_auth_metadata,
+                         OutputMetadata* response_metadata) = 0;
+};
+
+}  // namespace grpc
+
+#endif  // GRPCXX_AUTH_METADATA_PROCESSOR_H_
+
diff --git a/include/grpc++/credentials.h b/include/grpc++/security/credentials.h
similarity index 100%
rename from include/grpc++/credentials.h
rename to include/grpc++/security/credentials.h
diff --git a/include/grpc++/server_credentials.h b/include/grpc++/security/server_credentials.h
similarity index 90%
rename from include/grpc++/server_credentials.h
rename to include/grpc++/security/server_credentials.h
index 16b78c08afcfd052fefc94817440701211825134..2094c7403c2b0a96e6861ed4c93fcc1c46caf3a8 100644
--- a/include/grpc++/server_credentials.h
+++ b/include/grpc++/security/server_credentials.h
@@ -37,6 +37,7 @@
 #include <memory>
 #include <vector>
 
+#include <grpc++/security/auth_metadata_processor.h>
 #include <grpc++/support/config.h>
 
 struct grpc_server;
@@ -49,6 +50,11 @@ class ServerCredentials {
  public:
   virtual ~ServerCredentials();
 
+  // This method is not thread-safe and has to be called before the server is
+  // started. The last call to this function wins.
+  virtual void SetAuthMetadataProcessor(
+      const std::shared_ptr<AuthMetadataProcessor>& processor) = 0;
+
  private:
   friend class ::grpc::Server;
 
diff --git a/include/grpc++/server.h b/include/grpc++/server.h
index c8979e433cbd2c9200c3a1ec536dfef66b3cc356..22d14ee6528886d58341f5231d7739f0f170478d 100644
--- a/include/grpc++/server.h
+++ b/include/grpc++/server.h
@@ -41,6 +41,7 @@
 #include <grpc++/impl/call.h>
 #include <grpc++/impl/grpc_library.h>
 #include <grpc++/impl/sync.h>
+#include <grpc++/security/server_credentials.h>
 #include <grpc++/support/config.h>
 #include <grpc++/support/status.h>
 
@@ -54,7 +55,6 @@ class AsyncGenericService;
 class RpcService;
 class RpcServiceMethod;
 class ServerAsyncStreamingInterface;
-class ServerCredentials;
 class ThreadPoolInterface;
 
 // Currently it only supports handling rpcs in a single thread.
diff --git a/include/grpc++/server_context.h b/include/grpc++/server_context.h
index 4b17a2804714a85f2086a02a70ac21ebe4a11caf..85f384d4773c87528ff440534ebcfd98cd0927af 100644
--- a/include/grpc++/server_context.h
+++ b/include/grpc++/server_context.h
@@ -39,7 +39,7 @@
 
 #include <grpc/compression.h>
 #include <grpc/support/time.h>
-#include <grpc++/support/auth_context.h>
+#include <grpc++/security/auth_context.h>
 #include <grpc++/support/config.h>
 #include <grpc++/support/string_ref.h>
 #include <grpc++/support/time.h>
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index 049ab3c4be5897670c8f4291a4397839307dc940..87bc25042961d10fe0c05dbcdecddd395fdf9e3c 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -275,10 +275,12 @@ typedef void (*grpc_process_auth_metadata_done_cb)(
 typedef struct {
   /* The context object is read/write: it contains the properties of the
      channel peer and it is the job of the process function to augment it with
-     properties derived from the passed-in metadata. */
+     properties derived from the passed-in metadata.
+     The lifetime of these objects is guaranteed until cb is invoked. */
   void (*process)(void *state, grpc_auth_context *context,
-                  const grpc_metadata *md, size_t md_count,
+                  const grpc_metadata *md, size_t num_md,
                   grpc_process_auth_metadata_done_cb cb, void *user_data);
+  void (*destroy)(void *state);
   void *state;
 } grpc_auth_metadata_processor;
 
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
index 1c665f1edea5599220751f45d676182576eb2c7f..a764413300fef3763c965cfc4b4a0ec38c07d104 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -87,7 +87,10 @@ grpc_credentials *grpc_credentials_ref(grpc_credentials *creds) {
 
 void grpc_credentials_unref(grpc_credentials *creds) {
   if (creds == NULL) return;
-  if (gpr_unref(&creds->refcount)) creds->vtable->destroy(creds);
+  if (gpr_unref(&creds->refcount)) {
+    creds->vtable->destruct(creds);
+    gpr_free(creds);
+  }
 }
 
 void grpc_credentials_release(grpc_credentials *creds) {
@@ -135,9 +138,26 @@ grpc_security_status grpc_credentials_create_security_connector(
       creds, target, args, request_metadata_creds, sc, new_args);
 }
 
-void grpc_server_credentials_release(grpc_server_credentials *creds) {
+grpc_server_credentials *grpc_server_credentials_ref(
+    grpc_server_credentials *creds) {
+  if (creds == NULL) return NULL;
+  gpr_ref(&creds->refcount);
+  return creds;
+}
+
+void grpc_server_credentials_unref(grpc_server_credentials *creds) {
   if (creds == NULL) return;
-  creds->vtable->destroy(creds);
+  if (gpr_unref(&creds->refcount)) {
+    creds->vtable->destruct(creds);
+    if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
+      creds->processor.destroy(creds->processor.state);
+    }
+    gpr_free(creds);
+  }
+}
+
+void grpc_server_credentials_release(grpc_server_credentials *creds) {
+  grpc_server_credentials_unref(creds);
 }
 
 grpc_security_status grpc_server_credentials_create_security_connector(
@@ -152,20 +172,22 @@ grpc_security_status grpc_server_credentials_create_security_connector(
 void grpc_server_credentials_set_auth_metadata_processor(
     grpc_server_credentials *creds, grpc_auth_metadata_processor processor) {
   if (creds == NULL) return;
+  if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
+    creds->processor.destroy(creds->processor.state);
+  }
   creds->processor = processor;
 }
 
 /* -- Ssl credentials. -- */
 
-static void ssl_destroy(grpc_credentials *creds) {
+static void ssl_destruct(grpc_credentials *creds) {
   grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
   if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
   if (c->config.pem_private_key != NULL) gpr_free(c->config.pem_private_key);
   if (c->config.pem_cert_chain != NULL) gpr_free(c->config.pem_cert_chain);
-  gpr_free(creds);
 }
 
-static void ssl_server_destroy(grpc_server_credentials *creds) {
+static void ssl_server_destruct(grpc_server_credentials *creds) {
   grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
   size_t i;
   for (i = 0; i < c->config.num_key_cert_pairs; i++) {
@@ -185,7 +207,6 @@ static void ssl_server_destroy(grpc_server_credentials *creds) {
     gpr_free(c->config.pem_cert_chains_sizes);
   }
   if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
-  gpr_free(creds);
 }
 
 static int ssl_has_request_metadata(const grpc_credentials *creds) { return 0; }
@@ -231,11 +252,11 @@ static grpc_security_status ssl_server_create_security_connector(
 }
 
 static grpc_credentials_vtable ssl_vtable = {
-    ssl_destroy, ssl_has_request_metadata, ssl_has_request_metadata_only, NULL,
+    ssl_destruct, ssl_has_request_metadata, ssl_has_request_metadata_only, NULL,
     ssl_create_security_connector};
 
 static grpc_server_credentials_vtable ssl_server_vtable = {
-    ssl_server_destroy, ssl_server_create_security_connector};
+    ssl_server_destruct, ssl_server_create_security_connector};
 
 static void ssl_copy_key_material(const char *input, unsigned char **output,
                                   size_t *output_size) {
@@ -316,9 +337,9 @@ grpc_server_credentials *grpc_ssl_server_credentials_create(
   grpc_ssl_server_credentials *c =
       gpr_malloc(sizeof(grpc_ssl_server_credentials));
   GPR_ASSERT(reserved == NULL);
-  memset(c, 0, sizeof(grpc_ssl_credentials));
   memset(c, 0, sizeof(grpc_ssl_server_credentials));
   c->base.type = GRPC_CREDENTIALS_TYPE_SSL;
+  gpr_ref_init(&c->base.refcount, 1);
   c->base.vtable = &ssl_server_vtable;
   ssl_build_server_config(pem_root_certs, pem_key_cert_pairs,
                           num_key_cert_pairs, force_client_auth, &c->config);
@@ -339,13 +360,12 @@ static void jwt_reset_cache(grpc_service_account_jwt_access_credentials *c) {
   c->cached.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
 }
 
-static void jwt_destroy(grpc_credentials *creds) {
+static void jwt_destruct(grpc_credentials *creds) {
   grpc_service_account_jwt_access_credentials *c =
       (grpc_service_account_jwt_access_credentials *)creds;
   grpc_auth_json_key_destruct(&c->key);
   jwt_reset_cache(c);
   gpr_mu_destroy(&c->cache_mu);
-  gpr_free(c);
 }
 
 static int jwt_has_request_metadata(const grpc_credentials *creds) { return 1; }
@@ -410,7 +430,7 @@ static void jwt_get_request_metadata(grpc_credentials *creds,
 }
 
 static grpc_credentials_vtable jwt_vtable = {
-    jwt_destroy, jwt_has_request_metadata, jwt_has_request_metadata_only,
+    jwt_destruct, jwt_has_request_metadata, jwt_has_request_metadata_only,
     jwt_get_request_metadata, NULL};
 
 grpc_credentials *
@@ -442,13 +462,12 @@ grpc_credentials *grpc_service_account_jwt_access_credentials_create(
 
 /* -- Oauth2TokenFetcher credentials -- */
 
-static void oauth2_token_fetcher_destroy(grpc_credentials *creds) {
+static void oauth2_token_fetcher_destruct(grpc_credentials *creds) {
   grpc_oauth2_token_fetcher_credentials *c =
       (grpc_oauth2_token_fetcher_credentials *)creds;
   grpc_credentials_md_store_unref(c->access_token_md);
   gpr_mu_destroy(&c->mu);
   grpc_httpcli_context_destroy(&c->httpcli_context);
-  gpr_free(c);
 }
 
 static int oauth2_token_fetcher_has_request_metadata(
@@ -621,7 +640,7 @@ static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c,
 /* -- GoogleComputeEngine credentials. -- */
 
 static grpc_credentials_vtable compute_engine_vtable = {
-    oauth2_token_fetcher_destroy, oauth2_token_fetcher_has_request_metadata,
+    oauth2_token_fetcher_destruct, oauth2_token_fetcher_has_request_metadata,
     oauth2_token_fetcher_has_request_metadata_only,
     oauth2_token_fetcher_get_request_metadata, NULL};
 
@@ -652,15 +671,15 @@ grpc_credentials *grpc_google_compute_engine_credentials_create(
 
 /* -- GoogleRefreshToken credentials. -- */
 
-static void refresh_token_destroy(grpc_credentials *creds) {
+static void refresh_token_destruct(grpc_credentials *creds) {
   grpc_google_refresh_token_credentials *c =
       (grpc_google_refresh_token_credentials *)creds;
   grpc_auth_refresh_token_destruct(&c->refresh_token);
-  oauth2_token_fetcher_destroy(&c->base.base);
+  oauth2_token_fetcher_destruct(&c->base.base);
 }
 
 static grpc_credentials_vtable refresh_token_vtable = {
-    refresh_token_destroy, oauth2_token_fetcher_has_request_metadata,
+    refresh_token_destruct, oauth2_token_fetcher_has_request_metadata,
     oauth2_token_fetcher_has_request_metadata_only,
     oauth2_token_fetcher_get_request_metadata, NULL};
 
@@ -713,10 +732,9 @@ grpc_credentials *grpc_google_refresh_token_credentials_create(
 
 /* -- Metadata-only credentials. -- */
 
-static void md_only_test_destroy(grpc_credentials *creds) {
+static void md_only_test_destruct(grpc_credentials *creds) {
   grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
   grpc_credentials_md_store_unref(c->md_store);
-  gpr_free(c);
 }
 
 static int md_only_test_has_request_metadata(const grpc_credentials *creds) {
@@ -757,7 +775,7 @@ static void md_only_test_get_request_metadata(grpc_credentials *creds,
 }
 
 static grpc_credentials_vtable md_only_test_vtable = {
-    md_only_test_destroy, md_only_test_has_request_metadata,
+    md_only_test_destruct, md_only_test_has_request_metadata,
     md_only_test_has_request_metadata_only, md_only_test_get_request_metadata,
     NULL};
 
@@ -778,10 +796,9 @@ grpc_credentials *grpc_md_only_test_credentials_create(const char *md_key,
 
 /* -- Oauth2 Access Token credentials. -- */
 
-static void access_token_destroy(grpc_credentials *creds) {
+static void access_token_destruct(grpc_credentials *creds) {
   grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
   grpc_credentials_md_store_unref(c->access_token_md);
-  gpr_free(c);
 }
 
 static int access_token_has_request_metadata(const grpc_credentials *creds) {
@@ -803,7 +820,7 @@ static void access_token_get_request_metadata(grpc_credentials *creds,
 }
 
 static grpc_credentials_vtable access_token_vtable = {
-    access_token_destroy, access_token_has_request_metadata,
+    access_token_destruct, access_token_has_request_metadata,
     access_token_has_request_metadata_only, access_token_get_request_metadata,
     NULL};
 
@@ -827,14 +844,14 @@ grpc_credentials *grpc_access_token_credentials_create(const char *access_token,
 
 /* -- Fake transport security credentials. -- */
 
-static void fake_transport_security_credentials_destroy(
+static void fake_transport_security_credentials_destruct(
     grpc_credentials *creds) {
-  gpr_free(creds);
+  /* Nothing to do here. */
 }
 
-static void fake_transport_security_server_credentials_destroy(
+static void fake_transport_security_server_credentials_destruct(
     grpc_server_credentials *creds) {
-  gpr_free(creds);
+  /* Nothing to do here. */
 }
 
 static int fake_transport_security_has_request_metadata(
@@ -863,14 +880,14 @@ fake_transport_security_server_create_security_connector(
 }
 
 static grpc_credentials_vtable fake_transport_security_credentials_vtable = {
-    fake_transport_security_credentials_destroy,
+    fake_transport_security_credentials_destruct,
     fake_transport_security_has_request_metadata,
     fake_transport_security_has_request_metadata_only, NULL,
     fake_transport_security_create_security_connector};
 
 static grpc_server_credentials_vtable
     fake_transport_security_server_credentials_vtable = {
-        fake_transport_security_server_credentials_destroy,
+        fake_transport_security_server_credentials_destruct,
         fake_transport_security_server_create_security_connector};
 
 grpc_credentials *grpc_fake_transport_security_credentials_create(void) {
@@ -887,6 +904,7 @@ grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
   grpc_server_credentials *c = gpr_malloc(sizeof(grpc_server_credentials));
   memset(c, 0, sizeof(grpc_server_credentials));
   c->type = GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
+  gpr_ref_init(&c->refcount, 1);
   c->vtable = &fake_transport_security_server_credentials_vtable;
   return c;
 }
@@ -903,14 +921,13 @@ typedef struct {
   grpc_credentials_metadata_cb cb;
 } grpc_composite_credentials_metadata_context;
 
-static void composite_destroy(grpc_credentials *creds) {
+static void composite_destruct(grpc_credentials *creds) {
   grpc_composite_credentials *c = (grpc_composite_credentials *)creds;
   size_t i;
   for (i = 0; i < c->inner.num_creds; i++) {
     grpc_credentials_unref(c->inner.creds_array[i]);
   }
   gpr_free(c->inner.creds_array);
-  gpr_free(creds);
 }
 
 static int composite_has_request_metadata(const grpc_credentials *creds) {
@@ -1026,7 +1043,7 @@ static grpc_security_status composite_create_security_connector(
 }
 
 static grpc_credentials_vtable composite_credentials_vtable = {
-    composite_destroy, composite_has_request_metadata,
+    composite_destruct, composite_has_request_metadata,
     composite_has_request_metadata_only, composite_get_request_metadata,
     composite_create_security_connector};
 
@@ -1125,10 +1142,9 @@ grpc_credentials *grpc_credentials_contains_type(
 
 /* -- IAM credentials. -- */
 
-static void iam_destroy(grpc_credentials *creds) {
+static void iam_destruct(grpc_credentials *creds) {
   grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
   grpc_credentials_md_store_unref(c->iam_md);
-  gpr_free(c);
 }
 
 static int iam_has_request_metadata(const grpc_credentials *creds) { return 1; }
@@ -1148,7 +1164,7 @@ static void iam_get_request_metadata(grpc_credentials *creds,
 }
 
 static grpc_credentials_vtable iam_vtable = {
-    iam_destroy, iam_has_request_metadata, iam_has_request_metadata_only,
+    iam_destruct, iam_has_request_metadata, iam_has_request_metadata_only,
     iam_get_request_metadata, NULL};
 
 grpc_credentials *grpc_google_iam_credentials_create(
diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h
index d9bd53adc27667c6a213e914c079b40e6b590cd5..8e4fed7615f4ea4d917a4d7c9be972e244d84c86 100644
--- a/src/core/security/credentials.h
+++ b/src/core/security/credentials.h
@@ -129,7 +129,7 @@ typedef void (*grpc_credentials_metadata_cb)(void *user_data,
                                              grpc_credentials_status status);
 
 typedef struct {
-  void (*destroy)(grpc_credentials *c);
+  void (*destruct)(grpc_credentials *c);
   int (*has_request_metadata)(const grpc_credentials *c);
   int (*has_request_metadata_only)(const grpc_credentials *c);
   void (*get_request_metadata)(grpc_credentials *c, grpc_pollset *pollset,
@@ -210,20 +210,28 @@ grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token(
 /* --- grpc_server_credentials. --- */
 
 typedef struct {
-  void (*destroy)(grpc_server_credentials *c);
+  void (*destruct)(grpc_server_credentials *c);
   grpc_security_status (*create_security_connector)(
       grpc_server_credentials *c, grpc_security_connector **sc);
 } grpc_server_credentials_vtable;
 
+
+/* TODO(jboeuf): Add a refcount. */
 struct grpc_server_credentials {
   const grpc_server_credentials_vtable *vtable;
   const char *type;
+  gpr_refcount refcount;
   grpc_auth_metadata_processor processor;
 };
 
 grpc_security_status grpc_server_credentials_create_security_connector(
     grpc_server_credentials *creds, grpc_security_connector **sc);
 
+grpc_server_credentials *grpc_server_credentials_ref(
+    grpc_server_credentials *creds);
+
+void grpc_server_credentials_unref(grpc_server_credentials *creds);
+
 /* -- Ssl credentials. -- */
 
 typedef struct {
diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c
index c1b434f3021fe248260959d533c1d12bb4ddf8ce..95d80ba122ff276fcf2e33335892baa12e895500 100644
--- a/src/core/security/security_context.c
+++ b/src/core/security/security_context.c
@@ -42,19 +42,6 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
-/* --- grpc_process_auth_metadata_func --- */
-
-static grpc_auth_metadata_processor server_processor = {NULL, NULL};
-
-grpc_auth_metadata_processor grpc_server_get_auth_metadata_processor(void) {
-  return server_processor;
-}
-
-void grpc_server_register_auth_metadata_processor(
-    grpc_auth_metadata_processor processor) {
-  server_processor = processor;
-}
-
 /* --- grpc_call --- */
 
 grpc_call_error grpc_call_set_credentials(grpc_call *call,
diff --git a/src/core/security/server_auth_filter.c b/src/core/security/server_auth_filter.c
index 6e831431fa218390da2b4a52bc474cccd2c944a5..b767f854987b59d8ecc91f9751891b245cc131ee 100644
--- a/src/core/security/server_auth_filter.c
+++ b/src/core/security/server_auth_filter.c
@@ -50,6 +50,7 @@ typedef struct call_data {
      handling it. */
   grpc_iomgr_closure auth_on_recv;
   grpc_transport_stream_op transport_op;
+  grpc_metadata_array md;
   const grpc_metadata *consumed_md;
   size_t num_consumed_md;
   grpc_stream_op *md_op;
@@ -90,13 +91,17 @@ static grpc_mdelem *remove_consumed_md(void *user_data, grpc_mdelem *md) {
   call_data *calld = elem->call_data;
   size_t i;
   for (i = 0; i < calld->num_consumed_md; i++) {
+    const grpc_metadata *consumed_md = &calld->consumed_md[i];
     /* Maybe we could do a pointer comparison but we do not have any guarantee
        that the metadata processor used the same pointers for consumed_md in the
        callback. */
-    if (memcmp(GPR_SLICE_START_PTR(md->key->slice), calld->consumed_md[i].key,
+    if (GPR_SLICE_LENGTH(md->key->slice) != strlen(consumed_md->key) ||
+        GPR_SLICE_LENGTH(md->value->slice) != consumed_md->value_length) {
+      continue;
+    }
+    if (memcmp(GPR_SLICE_START_PTR(md->key->slice), consumed_md->key,
                GPR_SLICE_LENGTH(md->key->slice)) == 0 &&
-        memcmp(GPR_SLICE_START_PTR(md->value->slice),
-               calld->consumed_md[i].value,
+        memcmp(GPR_SLICE_START_PTR(md->value->slice), consumed_md->value,
                GPR_SLICE_LENGTH(md->value->slice)) == 0) {
       return NULL; /* Delete. */
     }
@@ -134,6 +139,7 @@ static void on_md_processing_done(
     grpc_transport_stream_op_add_close(&calld->transport_op, status, &message);
     grpc_call_next_op(elem, &calld->transport_op);
   }
+  grpc_metadata_array_destroy(&calld->md);
 }
 
 static void auth_on_recv(void *user_data, int success) {
@@ -145,17 +151,15 @@ static void auth_on_recv(void *user_data, int success) {
     size_t nops = calld->recv_ops->nops;
     grpc_stream_op *ops = calld->recv_ops->ops;
     for (i = 0; i < nops; i++) {
-      grpc_metadata_array md_array;
       grpc_stream_op *op = &ops[i];
       if (op->type != GRPC_OP_METADATA || calld->got_client_metadata) continue;
       calld->got_client_metadata = 1;
       if (chand->processor.process == NULL) continue;
       calld->md_op = op;
-      md_array = metadata_batch_to_md_array(&op->data.metadata);
+      calld->md = metadata_batch_to_md_array(&op->data.metadata);
       chand->processor.process(chand->processor.state, calld->auth_context,
-                               md_array.metadata, md_array.count,
+                               calld->md.metadata, calld->md.count,
                                on_md_processing_done, elem);
-      grpc_metadata_array_destroy(&md_array);
       return;
     }
   }
diff --git a/src/core/security/server_secure_chttp2.c b/src/core/security/server_secure_chttp2.c
index 8d9d036d808d8500395f79830dc61e54259551a3..4749f5f516525326d5c999e7e480eadd41dc9f25 100644
--- a/src/core/security/server_secure_chttp2.c
+++ b/src/core/security/server_secure_chttp2.c
@@ -61,7 +61,7 @@ typedef struct grpc_server_secure_state {
   grpc_server *server;
   grpc_tcp_server *tcp;
   grpc_security_connector *sc;
-  grpc_auth_metadata_processor processor;
+  grpc_server_credentials *creds;
   tcp_endpoint_list *handshaking_tcp_endpoints;
   int is_shutdown;
   gpr_mu mu;
@@ -79,6 +79,7 @@ static void state_unref(grpc_server_secure_state *state) {
     gpr_mu_unlock(&state->mu);
     /* clean up */
     GRPC_SECURITY_CONNECTOR_UNREF(state->sc, "server");
+    grpc_server_credentials_unref(state->creds);
     gpr_free(state);
   }
 }
@@ -91,7 +92,8 @@ static void setup_transport(void *statep, grpc_transport *transport,
   grpc_channel_args *args_copy;
   grpc_arg args_to_add[2];
   args_to_add[0] = grpc_security_connector_to_arg(state->sc);
-  args_to_add[1] = grpc_auth_metadata_processor_to_arg(&state->processor);
+  args_to_add[1] =
+      grpc_auth_metadata_processor_to_arg(&state->creds->processor);
   args_copy = grpc_channel_args_copy_and_add(
       grpc_server_get_channel_args(state->server), args_to_add,
       GPR_ARRAY_SIZE(args_to_add));
@@ -262,7 +264,8 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
   state->server = server;
   state->tcp = tcp;
   state->sc = sc;
-  state->processor = creds->processor;
+  state->creds = grpc_server_credentials_ref(creds);
+
   state->handshaking_tcp_endpoints = NULL;
   state->is_shutdown = 0;
   gpr_mu_init(&state->mu);
diff --git a/src/cpp/client/channel.cc b/src/cpp/client/channel.cc
index 8bf2e4687e55b23ef3a5b4cb1ab588f3471bc255..dc8e3046648fae1acdb799e0ccf4ff75008cf091 100644
--- a/src/cpp/client/channel.cc
+++ b/src/cpp/client/channel.cc
@@ -40,7 +40,7 @@
 #include <grpc/support/slice.h>
 #include <grpc++/client_context.h>
 #include <grpc++/completion_queue.h>
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 #include <grpc++/impl/call.h>
 #include <grpc++/impl/rpc_method.h>
 #include <grpc++/support/channel_arguments.h>
diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc
index c4d7cf2e51467d1ccb735cbb9ac566cec7a13df3..574656a7e9b0a34ae1beb302732019b6fba34be3 100644
--- a/src/cpp/client/client_context.cc
+++ b/src/cpp/client/client_context.cc
@@ -36,7 +36,7 @@
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/string_util.h>
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 #include <grpc++/server_context.h>
 #include <grpc++/support/time.h>
 
diff --git a/src/cpp/client/create_channel.cc b/src/cpp/client/create_channel.cc
index 1dac9600170c0b419f61f5bc21caf0140c84b815..d2b2d30126c0d990fd46490e3af07237ca2e45ea 100644
--- a/src/cpp/client/create_channel.cc
+++ b/src/cpp/client/create_channel.cc
@@ -51,6 +51,7 @@ std::shared_ptr<Channel> CreateChannel(
 std::shared_ptr<Channel> CreateCustomChannel(
     const grpc::string& target, const std::shared_ptr<Credentials>& creds,
     const ChannelArguments& args) {
+  GrpcLibrary init_lib;  // We need to call init in case of a bad creds.
   ChannelArguments cp_args = args;
   std::ostringstream user_agent_prefix;
   user_agent_prefix << "grpc-c++/" << grpc_version_string();
diff --git a/src/cpp/client/credentials.cc b/src/cpp/client/credentials.cc
index e8062849887c0582f713b8fca79f1a6ab6923383..7a8149e9c7a06e31cb1715bdde76bc20303a66fb 100644
--- a/src/cpp/client/credentials.cc
+++ b/src/cpp/client/credentials.cc
@@ -31,7 +31,7 @@
  *
  */
 
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 
 namespace grpc {
 
diff --git a/src/cpp/client/insecure_credentials.cc b/src/cpp/client/insecure_credentials.cc
index 4a4d2cb97d4f831b8fd6289afada159ae9341d7b..c476f3ce95b4e5feb57148d09d45b0ba25550c98 100644
--- a/src/cpp/client/insecure_credentials.cc
+++ b/src/cpp/client/insecure_credentials.cc
@@ -31,7 +31,7 @@
  *
  */
 
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 
 #include <grpc/grpc.h>
 #include <grpc/support/log.h>
diff --git a/src/cpp/client/secure_credentials.h b/src/cpp/client/secure_credentials.h
index 62d31854776f425c8c00951656ba27841261cb7a..8deff856c4c0a513811b3a49fdfcea4c76e71abe 100644
--- a/src/cpp/client/secure_credentials.h
+++ b/src/cpp/client/secure_credentials.h
@@ -37,7 +37,7 @@
 #include <grpc/grpc_security.h>
 
 #include <grpc++/support/config.h>
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 
 namespace grpc {
 
diff --git a/src/cpp/common/auth_property_iterator.cc b/src/cpp/common/auth_property_iterator.cc
index fa6da9d7a8dafb51d661599f775d39f485fbef56..a47abaf4b8dc1952cb7ed8a01b9a126dde6057a6 100644
--- a/src/cpp/common/auth_property_iterator.cc
+++ b/src/cpp/common/auth_property_iterator.cc
@@ -31,7 +31,7 @@
  *
  */
 
-#include <grpc++/support/auth_context.h>
+#include <grpc++/security/auth_context.h>
 
 #include <grpc/grpc_security.h>
 
diff --git a/src/cpp/common/create_auth_context.h b/src/cpp/common/create_auth_context.h
index b4962bae4e3f5fd8200e10d47fcfe9c093541f6e..4f3da397badcb858442ea568673ff1bccc6d0752 100644
--- a/src/cpp/common/create_auth_context.h
+++ b/src/cpp/common/create_auth_context.h
@@ -33,7 +33,7 @@
 #include <memory>
 
 #include <grpc/grpc.h>
-#include <grpc++/support/auth_context.h>
+#include <grpc++/security/auth_context.h>
 
 namespace grpc {
 
diff --git a/src/cpp/common/insecure_create_auth_context.cc b/src/cpp/common/insecure_create_auth_context.cc
index fe80c1a80cde000fea2c5d7047e98ea8beacfeea..b2e153229a9d8df51c652b9efe92f4571ac33e6b 100644
--- a/src/cpp/common/insecure_create_auth_context.cc
+++ b/src/cpp/common/insecure_create_auth_context.cc
@@ -33,7 +33,7 @@
 #include <memory>
 
 #include <grpc/grpc.h>
-#include <grpc++/support/auth_context.h>
+#include <grpc++/security/auth_context.h>
 
 namespace grpc {
 
diff --git a/src/cpp/common/secure_auth_context.cc b/src/cpp/common/secure_auth_context.cc
index b18a8537c99ba0f2e388b3564b9f74acca4cfa9c..8615ac8aebcdfa7eba40dc20df2756477937548e 100644
--- a/src/cpp/common/secure_auth_context.cc
+++ b/src/cpp/common/secure_auth_context.cc
@@ -37,9 +37,13 @@
 
 namespace grpc {
 
-SecureAuthContext::SecureAuthContext(grpc_auth_context* ctx) : ctx_(ctx) {}
+SecureAuthContext::SecureAuthContext(grpc_auth_context* ctx,
+                                     bool take_ownership)
+    : ctx_(ctx), take_ownership_(take_ownership) {}
 
-SecureAuthContext::~SecureAuthContext() { grpc_auth_context_release(ctx_); }
+SecureAuthContext::~SecureAuthContext() {
+  if (take_ownership_) grpc_auth_context_release(ctx_);
+}
 
 std::vector<grpc::string_ref> SecureAuthContext::GetPeerIdentity() const {
   if (!ctx_) {
@@ -94,4 +98,21 @@ AuthPropertyIterator SecureAuthContext::end() const {
   return AuthPropertyIterator();
 }
 
+void SecureAuthContext::AddProperty(const grpc::string& key,
+                                    const grpc::string_ref& value) {
+  if (!ctx_) return;
+  grpc_auth_context_add_property(ctx_, key.c_str(), value.data(), value.size());
+}
+
+bool SecureAuthContext::SetPeerIdentityPropertyName(const grpc::string& name) {
+  if (!ctx_) return false;
+  return grpc_auth_context_set_peer_identity_property_name(ctx_,
+                                                           name.c_str()) != 0;
+}
+
+bool SecureAuthContext::IsPeerAuthenticated() const {
+  if (!ctx_) return false;
+  return grpc_auth_context_peer_is_authenticated(ctx_) != 0;
+}
+
 }  // namespace grpc
diff --git a/src/cpp/common/secure_auth_context.h b/src/cpp/common/secure_auth_context.h
index 7f622b890b4d3c32eedaa1645a1f177fc1edfc45..c9f1dad1319f8f8f5a2be031fce66d69842a67b0 100644
--- a/src/cpp/common/secure_auth_context.h
+++ b/src/cpp/common/secure_auth_context.h
@@ -34,7 +34,7 @@
 #ifndef GRPC_INTERNAL_CPP_COMMON_SECURE_AUTH_CONTEXT_H
 #define GRPC_INTERNAL_CPP_COMMON_SECURE_AUTH_CONTEXT_H
 
-#include <grpc++/support/auth_context.h>
+#include <grpc++/security/auth_context.h>
 
 struct grpc_auth_context;
 
@@ -42,10 +42,12 @@ namespace grpc {
 
 class SecureAuthContext GRPC_FINAL : public AuthContext {
  public:
-  SecureAuthContext(grpc_auth_context* ctx);
+  SecureAuthContext(grpc_auth_context* ctx, bool take_ownership);
 
   ~SecureAuthContext() GRPC_OVERRIDE;
 
+  bool IsPeerAuthenticated() const GRPC_OVERRIDE;
+
   std::vector<grpc::string_ref> GetPeerIdentity() const GRPC_OVERRIDE;
 
   grpc::string GetPeerIdentityPropertyName() const GRPC_OVERRIDE;
@@ -57,8 +59,15 @@ class SecureAuthContext GRPC_FINAL : public AuthContext {
 
   AuthPropertyIterator end() const GRPC_OVERRIDE;
 
+  void AddProperty(const grpc::string& key,
+                   const grpc::string_ref& value) GRPC_OVERRIDE;
+
+  virtual bool SetPeerIdentityPropertyName(const grpc::string& name)
+      GRPC_OVERRIDE;
+
  private:
   grpc_auth_context* ctx_;
+  bool take_ownership_;
 };
 
 }  // namespace grpc
diff --git a/src/cpp/common/secure_create_auth_context.cc b/src/cpp/common/secure_create_auth_context.cc
index f13d25a1dd6726a7010bdf484424739c6cb401a8..40bc298b6420ecbb862581fee3aa46bdf6e8644c 100644
--- a/src/cpp/common/secure_create_auth_context.cc
+++ b/src/cpp/common/secure_create_auth_context.cc
@@ -34,7 +34,7 @@
 
 #include <grpc/grpc.h>
 #include <grpc/grpc_security.h>
-#include <grpc++/support/auth_context.h>
+#include <grpc++/security/auth_context.h>
 #include "src/cpp/common/secure_auth_context.h"
 
 namespace grpc {
@@ -44,7 +44,7 @@ std::shared_ptr<const AuthContext> CreateAuthContext(grpc_call* call) {
     return std::shared_ptr<const AuthContext>();
   }
   return std::shared_ptr<const AuthContext>(
-      new SecureAuthContext(grpc_call_auth_context(call)));
+      new SecureAuthContext(grpc_call_auth_context(call), true));
 }
 
 }  // namespace grpc
diff --git a/src/cpp/server/insecure_server_credentials.cc b/src/cpp/server/insecure_server_credentials.cc
index 800cd36caaf9db643e559090779f1101354f54b9..ef3cae5fd720612b1ae6352a5004586cb8d53471 100644
--- a/src/cpp/server/insecure_server_credentials.cc
+++ b/src/cpp/server/insecure_server_credentials.cc
@@ -31,9 +31,10 @@
  *
  */
 
-#include <grpc++/server_credentials.h>
+#include <grpc++/security/server_credentials.h>
 
 #include <grpc/grpc.h>
+#include <grpc/support/log.h>
 
 namespace grpc {
 namespace {
@@ -43,6 +44,11 @@ class InsecureServerCredentialsImpl GRPC_FINAL : public ServerCredentials {
                       grpc_server* server) GRPC_OVERRIDE {
     return grpc_server_add_insecure_http2_port(server, addr.c_str());
   }
+  void SetAuthMetadataProcessor(
+      const std::shared_ptr<AuthMetadataProcessor>& processor) GRPC_OVERRIDE {
+    (void)processor;
+    GPR_ASSERT(0);  // Should not be called on InsecureServerCredentials.
+  }
 };
 }  // namespace
 
diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc
index 5bce9ca8b2ce33fd2fdafefbd278d2615e3330c8..dfa9229c98198d6c7c12478d589db48ae69763a5 100644
--- a/src/cpp/server/secure_server_credentials.cc
+++ b/src/cpp/server/secure_server_credentials.cc
@@ -31,15 +31,94 @@
  *
  */
 
+#include <functional>
+#include <map>
+#include <memory>
+
+
+#include "src/cpp/common/secure_auth_context.h"
 #include "src/cpp/server/secure_server_credentials.h"
 
+#include <grpc++/security/auth_metadata_processor.h>
+
 namespace grpc {
 
+void AuthMetadataProcessorAyncWrapper::Destroy(void *wrapper) {
+  auto* w = reinterpret_cast<AuthMetadataProcessorAyncWrapper*>(wrapper);
+  delete w;
+}
+
+void AuthMetadataProcessorAyncWrapper::Process(
+    void* wrapper, grpc_auth_context* context, const grpc_metadata* md,
+    size_t num_md, grpc_process_auth_metadata_done_cb cb, void* user_data) {
+  auto* w = reinterpret_cast<AuthMetadataProcessorAyncWrapper*>(wrapper);
+  if (w->processor_ == nullptr) {
+    // Early exit.
+    cb(user_data, nullptr, 0, nullptr, 0, GRPC_STATUS_OK, nullptr);
+    return;
+  }
+  if (w->processor_->IsBlocking()) {
+    w->thread_pool_->Add(
+        std::bind(&AuthMetadataProcessorAyncWrapper::InvokeProcessor, w,
+                  context, md, num_md, cb, user_data));
+  } else {
+    // invoke directly.
+    w->InvokeProcessor(context, md, num_md, cb, user_data);
+  }
+}
+
+void AuthMetadataProcessorAyncWrapper::InvokeProcessor(
+    grpc_auth_context* ctx,
+    const grpc_metadata* md, size_t num_md,
+    grpc_process_auth_metadata_done_cb cb, void* user_data) {
+  AuthMetadataProcessor::InputMetadata metadata;
+  for (size_t i = 0; i < num_md; i++) {
+    metadata.insert(std::make_pair(
+        md[i].key, grpc::string_ref(md[i].value, md[i].value_length)));
+  }
+  SecureAuthContext context(ctx, false);
+  AuthMetadataProcessor::OutputMetadata consumed_metadata;
+  AuthMetadataProcessor::OutputMetadata response_metadata;
+
+  Status status = processor_->Process(metadata, &context, &consumed_metadata,
+                                      &response_metadata);
+
+  std::vector<grpc_metadata> consumed_md;
+  for (auto it = consumed_metadata.begin(); it != consumed_metadata.end();
+       ++it) {
+    consumed_md.push_back({it->first.c_str(),
+                           it->second.data(),
+                           it->second.size(),
+                           0,
+                           {{nullptr, nullptr, nullptr, nullptr}}});
+  }
+  std::vector<grpc_metadata> response_md;
+  for (auto it = response_metadata.begin(); it != response_metadata.end();
+       ++it) {
+    response_md.push_back({it->first.c_str(),
+                           it->second.data(),
+                           it->second.size(),
+                           0,
+                           {{nullptr, nullptr, nullptr, nullptr}}});
+  }
+  cb(user_data, &consumed_md[0], consumed_md.size(), &response_md[0],
+     response_md.size(), static_cast<grpc_status_code>(status.error_code()),
+     status.error_message().c_str());
+}
+
 int SecureServerCredentials::AddPortToServer(const grpc::string& addr,
                                              grpc_server* server) {
   return grpc_server_add_secure_http2_port(server, addr.c_str(), creds_);
 }
 
+void SecureServerCredentials::SetAuthMetadataProcessor(
+    const std::shared_ptr<AuthMetadataProcessor>& processor) {
+  auto *wrapper = new AuthMetadataProcessorAyncWrapper(processor);
+  grpc_server_credentials_set_auth_metadata_processor(
+      creds_, {AuthMetadataProcessorAyncWrapper::Process,
+               AuthMetadataProcessorAyncWrapper::Destroy, wrapper});
+}
+
 std::shared_ptr<ServerCredentials> SslServerCredentials(
     const SslServerCredentialsOptions& options) {
   std::vector<grpc_ssl_pem_key_cert_pair> pem_key_cert_pairs;
diff --git a/src/cpp/server/secure_server_credentials.h b/src/cpp/server/secure_server_credentials.h
index d3d37b188df52d111e11254524f57ca53a1209d6..4f003c6b7e5ff9a33c6a3e7b912c50cca0423a75 100644
--- a/src/cpp/server/secure_server_credentials.h
+++ b/src/cpp/server/secure_server_credentials.h
@@ -34,12 +34,36 @@
 #ifndef GRPC_INTERNAL_CPP_SERVER_SECURE_SERVER_CREDENTIALS_H
 #define GRPC_INTERNAL_CPP_SERVER_SECURE_SERVER_CREDENTIALS_H
 
-#include <grpc++/server_credentials.h>
+#include <memory>
+
+#include <grpc++/security/server_credentials.h>
 
 #include <grpc/grpc_security.h>
 
+#include "src/cpp/server/thread_pool_interface.h"
+
 namespace grpc {
 
+class AuthMetadataProcessorAyncWrapper GRPC_FINAL {
+ public:
+  static void Destroy(void *wrapper);
+
+  static void Process(void* wrapper, grpc_auth_context* context,
+                      const grpc_metadata* md, size_t num_md,
+                      grpc_process_auth_metadata_done_cb cb, void* user_data);
+
+  AuthMetadataProcessorAyncWrapper(
+      const std::shared_ptr<AuthMetadataProcessor>& processor)
+      : thread_pool_(CreateDefaultThreadPool()), processor_(processor) {}
+
+ private:
+  void InvokeProcessor(grpc_auth_context* context, const grpc_metadata* md,
+                       size_t num_md, grpc_process_auth_metadata_done_cb cb,
+                       void* user_data);
+  std::unique_ptr<ThreadPoolInterface> thread_pool_;
+  std::shared_ptr<AuthMetadataProcessor> processor_;
+};
+
 class SecureServerCredentials GRPC_FINAL : public ServerCredentials {
  public:
   explicit SecureServerCredentials(grpc_server_credentials* creds)
@@ -51,8 +75,12 @@ class SecureServerCredentials GRPC_FINAL : public ServerCredentials {
   int AddPortToServer(const grpc::string& addr,
                       grpc_server* server) GRPC_OVERRIDE;
 
+  void SetAuthMetadataProcessor(
+      const std::shared_ptr<AuthMetadataProcessor>& processor) GRPC_OVERRIDE;
+
  private:
-  grpc_server_credentials* const creds_;
+  grpc_server_credentials* creds_;
+  std::unique_ptr<AuthMetadataProcessorAyncWrapper> processor_;
 };
 
 }  // namespace grpc
diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc
index bb83c7d887b5c3330a7e2d48eea7a9a7a46fd811..d67205e822f58ceac9c3ca3a6f7c6ef58ba516f3 100644
--- a/src/cpp/server/server.cc
+++ b/src/cpp/server/server.cc
@@ -43,7 +43,7 @@
 #include <grpc++/impl/rpc_service_method.h>
 #include <grpc++/impl/service_type.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
+#include <grpc++/security/server_credentials.h>
 #include <grpc++/support/time.h>
 
 #include "src/core/profiling/timers.h"
@@ -354,7 +354,7 @@ bool Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) {
       unknown_method_.reset(new RpcServiceMethod(
           "unknown", RpcMethod::BIDI_STREAMING, new UnknownMethodHandler));
       // Use of emplace_back with just constructor arguments is not accepted
-      // here by gcc-4.4 because it can't match the anonymous nullptr with a 
+      // here by gcc-4.4 because it can't match the anonymous nullptr with a
       // proper constructor implicitly. Construct the object and use push_back.
       sync_methods_->push_back(SyncRequest(unknown_method_.get(), nullptr));
     }
@@ -384,7 +384,7 @@ void Server::ShutdownInternal(gpr_timespec deadline) {
     // Spin, eating requests until the completion queue is completely shutdown.
     // If the deadline expires then cancel anything that's pending and keep
     // spinning forever until the work is actually drained.
-    // Since nothing else needs to touch state guarded by mu_, holding it 
+    // Since nothing else needs to touch state guarded by mu_, holding it
     // through this loop is fine.
     SyncRequest* request;
     bool ok;
diff --git a/src/cpp/server/server_credentials.cc b/src/cpp/server/server_credentials.cc
index be3a7425e0f31b67593a4a8ed0b483cdcdd3bc2f..84959161781eb10819d955038e6ac27c5de28b90 100644
--- a/src/cpp/server/server_credentials.cc
+++ b/src/cpp/server/server_credentials.cc
@@ -31,7 +31,7 @@
  *
  */
 
-#include <grpc++/server_credentials.h>
+#include <grpc++/security/server_credentials.h>
 
 namespace grpc {
 
diff --git a/test/core/end2end/fixtures/chttp2_fake_security.c b/test/core/end2end/fixtures/chttp2_fake_security.c
index b4a248fb52c93056cec811c3f677d26f6de28ef4..3e64cc08e88becae2078069c30f5d0bccd0f980f 100644
--- a/test/core/end2end/fixtures/chttp2_fake_security.c
+++ b/test/core/end2end/fixtures/chttp2_fake_security.c
@@ -128,7 +128,7 @@ static void chttp2_init_server_fake_secure_fullstack(
   grpc_server_credentials *fake_ts_creds =
       grpc_fake_transport_security_server_credentials_create();
   if (fail_server_auth_check(server_args)) {
-    grpc_auth_metadata_processor processor = {process_auth_failure, NULL};
+    grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL};
     grpc_server_credentials_set_auth_metadata_processor(fake_ts_creds,
                                                         processor);
   }
diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c
index 201d202dff9f5b0002c749f819c79acbfc5c9b24..9193a09b178c093f658331b23bfefdb9d080c3fa 100644
--- a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c
+++ b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c
@@ -138,7 +138,7 @@ static void chttp2_init_server_simple_ssl_secure_fullstack(
   grpc_server_credentials *ssl_creds =
       grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL);
   if (fail_server_auth_check(server_args)) {
-    grpc_auth_metadata_processor processor = {process_auth_failure, NULL};
+    grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL};
     grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor);
   }
   chttp2_init_server_secure_fullstack(f, server_args, ssl_creds);
diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c
index e7375f15e663c800560303cd0646b3b855584f39..2c605d1471c4d2968389466dd34d626ff601137e 100644
--- a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c
+++ b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c
@@ -138,7 +138,7 @@ static void chttp2_init_server_simple_ssl_secure_fullstack(
   grpc_server_credentials *ssl_creds =
       grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL);
   if (fail_server_auth_check(server_args)) {
-    grpc_auth_metadata_processor processor = {process_auth_failure, NULL};
+    grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL};
     grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor);
   }
   chttp2_init_server_secure_fullstack(f, server_args, ssl_creds);
diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_proxy.c b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_proxy.c
index be0dda25a640b7194e14100c45ef7bf063336ea4..8133a69a0cd343b36935cdbacacaad87a19dec2e 100644
--- a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_proxy.c
+++ b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_proxy.c
@@ -167,7 +167,7 @@ static void chttp2_init_server_simple_ssl_secure_fullstack(
   grpc_server_credentials *ssl_creds =
       grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL);
   if (fail_server_auth_check(server_args)) {
-    grpc_auth_metadata_processor processor = {process_auth_failure, NULL};
+    grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL};
     grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor);
   }
   chttp2_init_server_secure_fullstack(f, server_args, ssl_creds);
diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c b/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c
index 9a545b1e3d528cd4e56fdcb7f6dcb2fa454963eb..e61e276fff8bac6544676ab72a052facb3b26d9e 100644
--- a/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c
+++ b/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c
@@ -67,13 +67,21 @@ static const grpc_metadata *find_metadata(const grpc_metadata *md,
   return NULL;
 }
 
+typedef struct {
+  size_t pseudo_refcount;
+} test_processor_state;
+
 static void process_oauth2_success(void *state, grpc_auth_context *ctx,
                                    const grpc_metadata *md, size_t md_count,
                                    grpc_process_auth_metadata_done_cb cb,
                                    void *user_data) {
   const grpc_metadata *oauth2 =
       find_metadata(md, md_count, "Authorization", oauth2_md);
-  GPR_ASSERT(state == NULL);
+  test_processor_state *s;
+
+  GPR_ASSERT(state != NULL);
+  s = (test_processor_state *)state;
+  GPR_ASSERT(s->pseudo_refcount == 1);
   GPR_ASSERT(oauth2 != NULL);
   grpc_auth_context_add_cstring_property(ctx, client_identity_property_name,
                                          client_identity);
@@ -88,7 +96,10 @@ static void process_oauth2_failure(void *state, grpc_auth_context *ctx,
                                    void *user_data) {
   const grpc_metadata *oauth2 =
       find_metadata(md, md_count, "Authorization", oauth2_md);
-  GPR_ASSERT(state == NULL);
+  test_processor_state *s;
+  GPR_ASSERT(state != NULL);
+  s = (test_processor_state *)state;
+  GPR_ASSERT(s->pseudo_refcount == 1);
   GPR_ASSERT(oauth2 != NULL);
   cb(user_data, oauth2, 1, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL);
 }
@@ -171,20 +182,34 @@ static int fail_server_auth_check(grpc_channel_args *server_args) {
   return 0;
 }
 
+static void processor_destroy(void *state) {
+  test_processor_state *s = (test_processor_state *)state;
+  GPR_ASSERT((s->pseudo_refcount--) == 1);
+  gpr_free(s);
+}
+
+static grpc_auth_metadata_processor test_processor_create(int failing) {
+  test_processor_state *s = gpr_malloc(sizeof(*s));
+  grpc_auth_metadata_processor result;
+  s->pseudo_refcount = 1;
+  result.state = s;
+  result.destroy = processor_destroy;
+  if (failing) {
+    result.process = process_oauth2_failure;
+  } else {
+    result.process = process_oauth2_success;
+  }
+  return result;
+}
+
 static void chttp2_init_server_simple_ssl_secure_fullstack(
     grpc_end2end_test_fixture *f, grpc_channel_args *server_args) {
   grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key,
                                                   test_server1_cert};
   grpc_server_credentials *ssl_creds =
       grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1, 0, NULL);
-  grpc_auth_metadata_processor processor;
-  processor.state = NULL;
-  if (fail_server_auth_check(server_args)) {
-    processor.process = process_oauth2_failure;
-  } else {
-    processor.process = process_oauth2_success;
-  }
-  grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor);
+  grpc_server_credentials_set_auth_metadata_processor(
+      ssl_creds, test_processor_create(fail_server_auth_check(server_args)));
   chttp2_init_server_secure_fullstack(f, server_args, ssl_creds);
 }
 
diff --git a/test/cpp/client/credentials_test.cc b/test/cpp/client/credentials_test.cc
index 18fcffe7cd1976e42b09e8964d13e47567b19988..743ad065d13a797cce016e5202e8104150f2b4c5 100644
--- a/test/cpp/client/credentials_test.cc
+++ b/test/cpp/client/credentials_test.cc
@@ -31,7 +31,7 @@
  *
  */
 
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 
 #include <memory>
 
diff --git a/test/cpp/common/auth_property_iterator_test.cc b/test/cpp/common/auth_property_iterator_test.cc
index e6226d6a0931d45362d9502ecbe7b8fbc258bda9..a629ff5a904dee41d3e3b22a998b4410ce2b9b29 100644
--- a/test/cpp/common/auth_property_iterator_test.cc
+++ b/test/cpp/common/auth_property_iterator_test.cc
@@ -32,7 +32,7 @@
  */
 
 #include <grpc/grpc_security.h>
-#include <grpc++/support/auth_context.h>
+#include <grpc++/security/auth_context.h>
 #include <gtest/gtest.h>
 #include "src/cpp/common/secure_auth_context.h"
 #include "test/cpp/util/string_ref_helper.h"
diff --git a/test/cpp/common/secure_auth_context_test.cc b/test/cpp/common/secure_auth_context_test.cc
index 25538c18537e18b029a07b19f74abe8adc1a3a43..11de646999f31c5f10fa2e61da5b8b13502ba66e 100644
--- a/test/cpp/common/secure_auth_context_test.cc
+++ b/test/cpp/common/secure_auth_context_test.cc
@@ -32,7 +32,7 @@
  */
 
 #include <grpc/grpc_security.h>
-#include <grpc++/support/auth_context.h>
+#include <grpc++/security/auth_context.h>
 #include <gtest/gtest.h>
 #include "src/cpp/common/secure_auth_context.h"
 #include "test/cpp/util/string_ref_helper.h"
@@ -50,7 +50,7 @@ class SecureAuthContextTest : public ::testing::Test {};
 
 // Created with nullptr
 TEST_F(SecureAuthContextTest, EmptyContext) {
-  SecureAuthContext context(nullptr);
+  SecureAuthContext context(nullptr, true);
   EXPECT_TRUE(context.GetPeerIdentity().empty());
   EXPECT_TRUE(context.GetPeerIdentityPropertyName().empty());
   EXPECT_TRUE(context.FindPropertyValues("").empty());
@@ -60,12 +60,12 @@ TEST_F(SecureAuthContextTest, EmptyContext) {
 
 TEST_F(SecureAuthContextTest, Properties) {
   grpc_auth_context* ctx = grpc_auth_context_create(NULL);
-  grpc_auth_context_add_cstring_property(ctx, "name", "chapi");
-  grpc_auth_context_add_cstring_property(ctx, "name", "chapo");
-  grpc_auth_context_add_cstring_property(ctx, "foo", "bar");
-  EXPECT_EQ(1, grpc_auth_context_set_peer_identity_property_name(ctx, "name"));
+  SecureAuthContext context(ctx, true);
+  context.AddProperty("name", "chapi");
+  context.AddProperty("name", "chapo");
+  context.AddProperty("foo", "bar");
+  EXPECT_TRUE(context.SetPeerIdentityPropertyName("name"));
 
-  SecureAuthContext context(ctx);
   std::vector<grpc::string_ref> peer_identity = context.GetPeerIdentity();
   EXPECT_EQ(2u, peer_identity.size());
   EXPECT_EQ("chapi", ToString(peer_identity[0]));
@@ -78,12 +78,12 @@ TEST_F(SecureAuthContextTest, Properties) {
 
 TEST_F(SecureAuthContextTest, Iterators) {
   grpc_auth_context* ctx = grpc_auth_context_create(NULL);
-  grpc_auth_context_add_cstring_property(ctx, "name", "chapi");
-  grpc_auth_context_add_cstring_property(ctx, "name", "chapo");
-  grpc_auth_context_add_cstring_property(ctx, "foo", "bar");
-  EXPECT_EQ(1, grpc_auth_context_set_peer_identity_property_name(ctx, "name"));
+  SecureAuthContext context(ctx, true);
+  context.AddProperty("name", "chapi");
+  context.AddProperty("name", "chapo");
+  context.AddProperty("foo", "bar");
+  EXPECT_TRUE(context.SetPeerIdentityPropertyName("name"));
 
-  SecureAuthContext context(ctx);
   AuthPropertyIterator iter = context.begin();
   EXPECT_TRUE(context.end() != iter);
   AuthProperty p0 = *iter;
diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc
index bbcac9ba34343a4337515423918dd8d952240f37..686e7627b98a32e617e51c9f3e3afdc86ae9f7ef 100644
--- a/test/cpp/end2end/async_end2end_test.cc
+++ b/test/cpp/end2end/async_end2end_test.cc
@@ -39,11 +39,9 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include <gtest/gtest.h>
 
 #include "test/core/util/port.h"
diff --git a/test/cpp/end2end/client_crash_test.cc b/test/cpp/end2end/client_crash_test.cc
index 3a6e55216af29b670e3142eda72f912ead416ff4..058e6961666ccf9fa3be29dbe80270c654879a1d 100644
--- a/test/cpp/end2end/client_crash_test.cc
+++ b/test/cpp/end2end/client_crash_test.cc
@@ -37,11 +37,9 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include <gtest/gtest.h>
 
 #include "test/core/util/port.h"
diff --git a/test/cpp/end2end/client_crash_test_server.cc b/test/cpp/end2end/client_crash_test_server.cc
index 79a783287417e0fe852567083ef5ec481ed34538..7ffeecca701dd3810119fe6d3d9e751aff29a2a0 100644
--- a/test/cpp/end2end/client_crash_test_server.cc
+++ b/test/cpp/end2end/client_crash_test_server.cc
@@ -39,7 +39,6 @@
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include "test/cpp/util/echo.grpc.pb.h"
 
 DEFINE_string(address, "", "Address to bind to");
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index 5e2332cbe93b5559e03898b19a184bd9053699aa..10a4c5ac26c463d219df09d0dd1d0ed90b302ef7 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -40,11 +40,12 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
+#include <grpc++/security/auth_metadata_processor.h>
+#include <grpc++/security/credentials.h>
+#include <grpc++/security/server_credentials.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include <gtest/gtest.h>
 
 #include "src/core/security/credentials.h"
@@ -79,14 +80,23 @@ void MaybeEchoDeadline(ServerContext* context, const EchoRequest* request,
   }
 }
 
-void CheckServerAuthContext(const ServerContext* context) {
+void CheckServerAuthContext(const ServerContext* context,
+                            const grpc::string& expected_client_identity) {
   std::shared_ptr<const AuthContext> auth_ctx = context->auth_context();
   std::vector<grpc::string_ref> ssl =
       auth_ctx->FindPropertyValues("transport_security_type");
   EXPECT_EQ(1u, ssl.size());
   EXPECT_EQ("ssl", ToString(ssl[0]));
-  EXPECT_TRUE(auth_ctx->GetPeerIdentityPropertyName().empty());
-  EXPECT_TRUE(auth_ctx->GetPeerIdentity().empty());
+  if (expected_client_identity.length() == 0) {
+    EXPECT_TRUE(auth_ctx->GetPeerIdentityPropertyName().empty());
+    EXPECT_TRUE(auth_ctx->GetPeerIdentity().empty());
+    EXPECT_FALSE(auth_ctx->IsPeerAuthenticated());
+  } else {
+    auto identity = auth_ctx->GetPeerIdentity();
+    EXPECT_TRUE(auth_ctx->IsPeerAuthenticated());
+    EXPECT_EQ(1u, identity.size());
+    EXPECT_EQ(expected_client_identity, identity[0]);
+  }
 }
 
 bool CheckIsLocalhost(const grpc::string& addr) {
@@ -98,6 +108,54 @@ bool CheckIsLocalhost(const grpc::string& addr) {
          addr.substr(0, kIpv6.size()) == kIpv6;
 }
 
+class TestAuthMetadataProcessor : public AuthMetadataProcessor {
+ public:
+  static const char kGoodGuy[];
+
+  TestAuthMetadataProcessor(bool is_blocking) : is_blocking_(is_blocking) {}
+
+  std::shared_ptr<Credentials> GetCompatibleClientCreds() {
+    return AccessTokenCredentials(kGoodGuy);
+  }
+  std::shared_ptr<Credentials> GetIncompatibleClientCreds() {
+    return AccessTokenCredentials("Mr Hyde");
+  }
+
+  // Interface implementation
+  bool IsBlocking() const GRPC_OVERRIDE { return is_blocking_; }
+
+  Status Process(const InputMetadata& auth_metadata, AuthContext* context,
+                 OutputMetadata* consumed_auth_metadata,
+                 OutputMetadata* response_metadata) GRPC_OVERRIDE {
+    EXPECT_TRUE(consumed_auth_metadata != nullptr);
+    EXPECT_TRUE(context != nullptr);
+    EXPECT_TRUE(response_metadata != nullptr);
+    auto auth_md = auth_metadata.find(GRPC_AUTHORIZATION_METADATA_KEY);
+    EXPECT_NE(auth_md, auth_metadata.end());
+    string_ref auth_md_value = auth_md->second;
+    if (auth_md_value.ends_with(kGoodGuy)) {
+      context->AddProperty(kIdentityPropName, kGoodGuy);
+      context->SetPeerIdentityPropertyName(kIdentityPropName);
+      consumed_auth_metadata->insert(
+          std::make_pair(string(auth_md->first.data(), auth_md->first.length()),
+                         auth_md->second));
+      return Status::OK;
+    } else {
+      return Status(StatusCode::UNAUTHENTICATED,
+                    string("Invalid principal: ") +
+                        string(auth_md_value.data(), auth_md_value.length()));
+    }
+  }
+
+ protected:
+  static const char kIdentityPropName[];
+  bool is_blocking_;
+};
+
+const char TestAuthMetadataProcessor::kGoodGuy[] = "Dr Jekyll";
+const char TestAuthMetadataProcessor::kIdentityPropName[] = "novel identity";
+
+
 }  // namespace
 
 class Proxy : public ::grpc::cpp::test::util::TestService::Service {
@@ -162,8 +220,10 @@ class TestServiceImpl : public ::grpc::cpp::test::util::TestService::Service {
                                      ToString(iter->second));
       }
     }
-    if (request->has_param() && request->param().check_auth_context()) {
-      CheckServerAuthContext(context);
+    if (request->has_param() &&
+        (request->param().expected_client_identity().length() > 0 ||
+         request->param().check_auth_context())) {
+      CheckServerAuthContext(context, request->param().expected_client_identity());
     }
     if (request->has_param() &&
         request->param().response_message_length() > 0) {
@@ -259,9 +319,18 @@ class TestServiceImplDupPkg
 class End2endTest : public ::testing::TestWithParam<bool> {
  protected:
   End2endTest()
-      : kMaxMessageSize_(8192), special_service_("special") {}
+      : is_server_started_(false),
+        kMaxMessageSize_(8192),
+        special_service_("special") {}
+
+  void TearDown() GRPC_OVERRIDE {
+    if (is_server_started_) {
+      server_->Shutdown();
+      if (proxy_server_) proxy_server_->Shutdown();
+    }
+  }
 
-  void SetUp() GRPC_OVERRIDE {
+  void StartServer(const std::shared_ptr<AuthMetadataProcessor>& processor) {
     int port = grpc_pick_unused_port_or_die();
     server_address_ << "127.0.0.1:" << port;
     // Setup server
@@ -271,22 +340,23 @@ class End2endTest : public ::testing::TestWithParam<bool> {
     SslServerCredentialsOptions ssl_opts;
     ssl_opts.pem_root_certs = "";
     ssl_opts.pem_key_cert_pairs.push_back(pkcp);
-    builder.AddListeningPort(server_address_.str(),
-                             SslServerCredentials(ssl_opts));
+    auto server_creds = SslServerCredentials(ssl_opts);
+    server_creds->SetAuthMetadataProcessor(processor);
+    builder.AddListeningPort(server_address_.str(), server_creds);
     builder.RegisterService(&service_);
     builder.RegisterService("foo.test.youtube.com", &special_service_);
     builder.SetMaxMessageSize(
         kMaxMessageSize_);  // For testing max message size.
     builder.RegisterService(&dup_pkg_service_);
     server_ = builder.BuildAndStart();
-  }
-
-  void TearDown() GRPC_OVERRIDE {
-    server_->Shutdown();
-    if (proxy_server_) proxy_server_->Shutdown();
+    is_server_started_ = true;
   }
 
   void ResetChannel() {
+    if (!is_server_started_) {
+      StartServer(std::shared_ptr<AuthMetadataProcessor>());
+    }
+    EXPECT_TRUE(is_server_started_);
     SslCredentialsOptions ssl_opts = {test_root_cert, "", ""};
     ChannelArguments args;
     args.SetSslTargetNameOverride("foo.test.google.fr");
@@ -313,6 +383,7 @@ class End2endTest : public ::testing::TestWithParam<bool> {
     stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel_));
   }
 
+  bool is_server_started_;
   std::shared_ptr<Channel> channel_;
   std::unique_ptr<grpc::cpp::test::util::TestService::Stub> stub_;
   std::unique_ptr<Server> server_;
@@ -805,6 +876,82 @@ TEST_F(End2endTest, OverridePerCallCredentials) {
   EXPECT_TRUE(s.ok());
 }
 
+TEST_F(End2endTest, NonBlockingAuthMetadataProcessorSuccess) {
+  auto* processor = new TestAuthMetadataProcessor(false);
+  StartServer(std::shared_ptr<AuthMetadataProcessor>(processor));
+  ResetStub(false);
+  EchoRequest request;
+  EchoResponse response;
+  ClientContext context;
+  context.set_credentials(processor->GetCompatibleClientCreds());
+  request.set_message("Hello");
+  request.mutable_param()->set_echo_metadata(true);
+  request.mutable_param()->set_expected_client_identity(
+      TestAuthMetadataProcessor::kGoodGuy);
+
+  Status s = stub_->Echo(&context, request, &response);
+  EXPECT_EQ(request.message(), response.message());
+  EXPECT_TRUE(s.ok());
+
+  // Metadata should have been consumed by the processor.
+  EXPECT_FALSE(MetadataContains(
+      context.GetServerTrailingMetadata(), GRPC_AUTHORIZATION_METADATA_KEY,
+      grpc::string("Bearer ") + TestAuthMetadataProcessor::kGoodGuy));
+}
+
+TEST_F(End2endTest, NonBlockingAuthMetadataProcessorFailure) {
+  auto* processor = new TestAuthMetadataProcessor(false);
+  StartServer(std::shared_ptr<AuthMetadataProcessor>(processor));
+  ResetStub(false);
+  EchoRequest request;
+  EchoResponse response;
+  ClientContext context;
+  context.set_credentials(processor->GetIncompatibleClientCreds());
+  request.set_message("Hello");
+
+  Status s = stub_->Echo(&context, request, &response);
+  EXPECT_FALSE(s.ok());
+  EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
+}
+
+TEST_F(End2endTest, BlockingAuthMetadataProcessorSuccess) {
+  auto* processor = new TestAuthMetadataProcessor(true);
+  StartServer(std::shared_ptr<AuthMetadataProcessor>(processor));
+  ResetStub(false);
+  EchoRequest request;
+  EchoResponse response;
+  ClientContext context;
+  context.set_credentials(processor->GetCompatibleClientCreds());
+  request.set_message("Hello");
+  request.mutable_param()->set_echo_metadata(true);
+  request.mutable_param()->set_expected_client_identity(
+      TestAuthMetadataProcessor::kGoodGuy);
+
+  Status s = stub_->Echo(&context, request, &response);
+  EXPECT_EQ(request.message(), response.message());
+  EXPECT_TRUE(s.ok());
+
+  // Metadata should have been consumed by the processor.
+  EXPECT_FALSE(MetadataContains(
+      context.GetServerTrailingMetadata(), GRPC_AUTHORIZATION_METADATA_KEY,
+      grpc::string("Bearer ") + TestAuthMetadataProcessor::kGoodGuy));
+}
+
+TEST_F(End2endTest, BlockingAuthMetadataProcessorFailure) {
+  auto* processor = new TestAuthMetadataProcessor(true);
+  StartServer(std::shared_ptr<AuthMetadataProcessor>(processor));
+  ResetStub(false);
+  EchoRequest request;
+  EchoResponse response;
+  ClientContext context;
+  context.set_credentials(processor->GetIncompatibleClientCreds());
+  request.set_message("Hello");
+
+  Status s = stub_->Echo(&context, request, &response);
+  EXPECT_FALSE(s.ok());
+  EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
+}
+
 // Client sends 20 requests and the server returns CANCELLED status after
 // reading 10 requests.
 TEST_F(End2endTest, RequestStreamServerEarlyCancelTest) {
diff --git a/test/cpp/end2end/generic_end2end_test.cc b/test/cpp/end2end/generic_end2end_test.cc
index 7acbc711fb87d486e461b632bf1fdd3b5bfc623c..6a4691672871520e984f510b4832a2e61198cc1c 100644
--- a/test/cpp/end2end/generic_end2end_test.cc
+++ b/test/cpp/end2end/generic_end2end_test.cc
@@ -40,13 +40,11 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
 #include <grpc++/generic/async_generic_service.h>
 #include <grpc++/generic/generic_stub.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include <grpc++/support/slice.h>
 #include <gtest/gtest.h>
 
diff --git a/test/cpp/end2end/mock_test.cc b/test/cpp/end2end/mock_test.cc
index 077d21aa729444612cf45bb6884177cadd0ab798..4450e29f09fe4991bd3399d8b59125a25ccaefbf 100644
--- a/test/cpp/end2end/mock_test.cc
+++ b/test/cpp/end2end/mock_test.cc
@@ -39,11 +39,9 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include <gtest/gtest.h>
 
 #include "test/core/util/port.h"
diff --git a/test/cpp/end2end/server_crash_test.cc b/test/cpp/end2end/server_crash_test.cc
index 1a0f04e22b3e98ccf1f76492c44f4fa3f0a68936..4b6793abe60ac3746bfb3957a2512473e998462a 100644
--- a/test/cpp/end2end/server_crash_test.cc
+++ b/test/cpp/end2end/server_crash_test.cc
@@ -37,11 +37,9 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include <gtest/gtest.h>
 
 #include "test/core/util/port.h"
diff --git a/test/cpp/end2end/server_crash_test_client.cc b/test/cpp/end2end/server_crash_test_client.cc
index 6ff42fcb301a9d146336b7837dd39fd2a53640c4..17869362c2e70d81bd7807b9ff0a72ef55e76301 100644
--- a/test/cpp/end2end/server_crash_test_client.cc
+++ b/test/cpp/end2end/server_crash_test_client.cc
@@ -40,7 +40,6 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
 #include "test/cpp/util/echo.grpc.pb.h"
 
 DEFINE_string(address, "", "Address to connect to");
diff --git a/test/cpp/end2end/shutdown_test.cc b/test/cpp/end2end/shutdown_test.cc
index 59fec6ad40619ca07c6f64738009672fbf2d2ac8..a25f85cc75adc93f90a340c8de6021922b7c5f19 100644
--- a/test/cpp/end2end/shutdown_test.cc
+++ b/test/cpp/end2end/shutdown_test.cc
@@ -38,11 +38,9 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include <gtest/gtest.h>
 
 #include "src/core/support/env.h"
diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc
index 2a16481972581e301cf3f9813b8a254cfda8d514..539e141d396a39ec3c4af25e945607d6439a7849 100644
--- a/test/cpp/end2end/thread_stress_test.cc
+++ b/test/cpp/end2end/thread_stress_test.cc
@@ -40,11 +40,9 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include <gtest/gtest.h>
 
 #include "test/core/util/port.h"
diff --git a/test/cpp/end2end/zookeeper_test.cc b/test/cpp/end2end/zookeeper_test.cc
index 931541ca3442dbf8c051b842023bf89e3100f0e6..d4c7f0489fd09a3cdd47818375185e412c5752fe 100644
--- a/test/cpp/end2end/zookeeper_test.cc
+++ b/test/cpp/end2end/zookeeper_test.cc
@@ -34,11 +34,9 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include <gtest/gtest.h>
 #include <grpc/grpc.h>
 #include <grpc/grpc_zookeeper.h>
diff --git a/test/cpp/interop/client_helper.cc b/test/cpp/interop/client_helper.cc
index 7093463fa8ce5a4cf669860d8d6eb7af5775c1f4..f85aa6ad8eb7e0b8b17116390856d99c9b2c25d1 100644
--- a/test/cpp/interop/client_helper.cc
+++ b/test/cpp/interop/client_helper.cc
@@ -45,7 +45,7 @@
 #include <gflags/gflags.h>
 #include <grpc++/channel.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 
 #include "src/cpp/client/secure_credentials.h"
 #include "test/core/security/oauth2_utils.h"
diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc
index 73d1a143c40e29f5fc75611383458b9a42ac8e33..48ccf06da988c8d98c4321336906c1dfe2d5f9d4 100644
--- a/test/cpp/interop/interop_client.cc
+++ b/test/cpp/interop/interop_client.cc
@@ -44,7 +44,7 @@
 #include <grpc/support/useful.h>
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 
 #include "src/core/transport/stream_op.h"
 #include "test/cpp/interop/client_helper.h"
diff --git a/test/cpp/interop/reconnect_interop_server.cc b/test/cpp/interop/reconnect_interop_server.cc
index d4f171b1d0a98df01cceab8b5b248fe7253ef642..f52417bae0f1d5bbfd17a823dc4c3f2f2b04b13e 100644
--- a/test/cpp/interop/reconnect_interop_server.cc
+++ b/test/cpp/interop/reconnect_interop_server.cc
@@ -45,7 +45,6 @@
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 
 #include "test/core/util/reconnect_server.h"
 #include "test/cpp/util/test_config.h"
diff --git a/test/cpp/interop/server.cc b/test/cpp/interop/server.cc
index 4921fde9fad1a7046de37fe1fe29cd299330e6c6..03b6532447341db123aaeb8431f366a4f9a54596 100644
--- a/test/cpp/interop/server.cc
+++ b/test/cpp/interop/server.cc
@@ -46,7 +46,7 @@
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
+#include <grpc++/security/server_credentials.h>
 
 #include "test/cpp/interop/server_helper.h"
 #include "test/cpp/util/test_config.h"
diff --git a/test/cpp/interop/server_helper.cc b/test/cpp/interop/server_helper.cc
index e897f4ebf003106e6d6f4924cefe85d08c012951..015198354e9243443eb1c62981cda09bd6fae592 100644
--- a/test/cpp/interop/server_helper.cc
+++ b/test/cpp/interop/server_helper.cc
@@ -36,7 +36,7 @@
 #include <memory>
 
 #include <gflags/gflags.h>
-#include <grpc++/server_credentials.h>
+#include <grpc++/security/server_credentials.h>
 
 #include "src/core/surface/call.h"
 #include "test/core/end2end/data/ssl_test_data.h"
diff --git a/test/cpp/interop/server_helper.h b/test/cpp/interop/server_helper.h
index 7b6b12cd4d85437f144c0b5bc28a3a3c1d180956..dc0ae1dccd657e15b595ab654546ca3fa3c7f3ab 100644
--- a/test/cpp/interop/server_helper.h
+++ b/test/cpp/interop/server_helper.h
@@ -38,7 +38,7 @@
 
 #include <grpc/compression.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
+#include <grpc++/security/server_credentials.h>
 
 namespace grpc {
 namespace testing {
diff --git a/test/cpp/qps/perf_db_client.h b/test/cpp/qps/perf_db_client.h
index ae5d17074b1887b6aa8af1d9743bdae32cd767ed..72ebe79c3c9cd742aed0ebf68caf7d047b9798e8 100644
--- a/test/cpp/qps/perf_db_client.h
+++ b/test/cpp/qps/perf_db_client.h
@@ -41,7 +41,7 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 #include "test/cpp/qps/perf_db.grpc.pb.h"
 
 namespace grpc {
diff --git a/test/cpp/qps/qps_worker.cc b/test/cpp/qps/qps_worker.cc
index 51e955a80a45649fe6a0a6633e5b8e92230d8755..4b4ca1a0ce645b0cc755621b5a62cba146c23a6a 100644
--- a/test/cpp/qps/qps_worker.cc
+++ b/test/cpp/qps/qps_worker.cc
@@ -49,7 +49,7 @@
 #include <grpc++/client_context.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
-#include <grpc++/server_credentials.h>
+#include <grpc++/security/server_credentials.h>
 
 #include "test/core/util/grpc_profiler.h"
 #include "test/cpp/qps/qpstest.pb.h"
diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc
index 77415f42ce7bd4db6f2afed8e9ded8826a9fe646..4160392cbec63ddabd11f9984fb57dc8607687c6 100644
--- a/test/cpp/qps/server_async.cc
+++ b/test/cpp/qps/server_async.cc
@@ -49,7 +49,7 @@
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
+#include <grpc++/security/server_credentials.h>
 #include <gtest/gtest.h>
 
 #include "test/cpp/qps/qpstest.grpc.pb.h"
diff --git a/test/cpp/qps/server_sync.cc b/test/cpp/qps/server_sync.cc
index 29ec19cd4bca3cbc7155a6f1eadbd61db447c2ef..01ae3480f93cec4551a0df68e3889c3304c2cc9f 100644
--- a/test/cpp/qps/server_sync.cc
+++ b/test/cpp/qps/server_sync.cc
@@ -43,7 +43,7 @@
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
+#include <grpc++/security/server_credentials.h>
 
 #include "test/cpp/qps/qpstest.grpc.pb.h"
 #include "test/cpp/qps/server.h"
diff --git a/test/cpp/util/cli_call_test.cc b/test/cpp/util/cli_call_test.cc
index 0efa201622017f3065b94108598e17209a0bef6a..b4133aa71ac47e1ff7887939052feac9321ea767 100644
--- a/test/cpp/util/cli_call_test.cc
+++ b/test/cpp/util/cli_call_test.cc
@@ -37,11 +37,9 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include <gtest/gtest.h>
 
 #include "test/core/util/port.h"
diff --git a/test/cpp/util/create_test_channel.cc b/test/cpp/util/create_test_channel.cc
index e993d14e716c2582db8f2fc358e810dac54077e5..f0d5bfc7ebc1ba0cf28849a8174731771acacaa8 100644
--- a/test/cpp/util/create_test_channel.cc
+++ b/test/cpp/util/create_test_channel.cc
@@ -34,7 +34,7 @@
 #include "test/cpp/util/create_test_channel.h"
 
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 
 #include "test/core/end2end/data/ssl_test_data.h"
 
diff --git a/test/cpp/util/create_test_channel.h b/test/cpp/util/create_test_channel.h
index 1263d4ed68609c87e63a9d400466de20dc3527cc..a4750689a0c826fc8cfc46765eec6e2b02c2fbf9 100644
--- a/test/cpp/util/create_test_channel.h
+++ b/test/cpp/util/create_test_channel.h
@@ -36,7 +36,7 @@
 
 #include <memory>
 
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 
 namespace grpc {
 class Channel;
diff --git a/test/cpp/util/grpc_cli.cc b/test/cpp/util/grpc_cli.cc
index 22cac21f77e0f9c542b4869a6e0d6e61c61b4f2d..334b6efb6a54ef0745d7c866d18903f1723b935a 100644
--- a/test/cpp/util/grpc_cli.cc
+++ b/test/cpp/util/grpc_cli.cc
@@ -1,5 +1,5 @@
 /*
- *
+
  * Copyright 2015, Google Inc.
  * All rights reserved.
  *
@@ -67,7 +67,7 @@
 #include <grpc/grpc.h>
 #include <grpc++/channel.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 #include <grpc++/support/string_ref.h>
 
 #include "test/cpp/util/cli_call.h"
diff --git a/test/cpp/util/messages.proto b/test/cpp/util/messages.proto
index 359d1db74fa4310a9ae58aa5de7d18a6452d8cc6..a022707be988237f867018c2d740aeb6961aa2e6 100644
--- a/test/cpp/util/messages.proto
+++ b/test/cpp/util/messages.proto
@@ -40,6 +40,7 @@ message RequestParams {
   bool check_auth_context = 5;
   int32 response_message_length = 6;
   bool echo_peer = 7;
+  string expected_client_identity = 8;  // will force check_auth_context.
 }
 
 message EchoRequest {
diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++
index 887f6169af96a342dce97891b20f247699faf8d6..96708c062272e86b956ac13a4f54803546c92245 100644
--- a/tools/doxygen/Doxyfile.c++
+++ b/tools/doxygen/Doxyfile.c++
@@ -764,7 +764,6 @@ INPUT                  = include/grpc++/channel.h \
 include/grpc++/client_context.h \
 include/grpc++/completion_queue.h \
 include/grpc++/create_channel.h \
-include/grpc++/credentials.h \
 include/grpc++/generic/async_generic_service.h \
 include/grpc++/generic/generic_stub.h \
 include/grpc++/impl/call.h \
@@ -781,13 +780,15 @@ include/grpc++/impl/sync_no_cxx11.h \
 include/grpc++/impl/thd.h \
 include/grpc++/impl/thd_cxx11.h \
 include/grpc++/impl/thd_no_cxx11.h \
+include/grpc++/security/auth_context.h \
+include/grpc++/security/auth_metadata_processor.h \
+include/grpc++/security/credentials.h \
+include/grpc++/security/server_credentials.h \
 include/grpc++/server.h \
 include/grpc++/server_builder.h \
 include/grpc++/server_context.h \
-include/grpc++/server_credentials.h \
 include/grpc++/support/async_stream.h \
 include/grpc++/support/async_unary_call.h \
-include/grpc++/support/auth_context.h \
 include/grpc++/support/byte_buffer.h \
 include/grpc++/support/channel_arguments.h \
 include/grpc++/support/config.h \
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index 84b13f94a7e26ebfa7a7138c41d8c101204e1499..185d24720ceac7cb11335e4422fbb174b8fb25a4 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -764,7 +764,6 @@ INPUT                  = include/grpc++/channel.h \
 include/grpc++/client_context.h \
 include/grpc++/completion_queue.h \
 include/grpc++/create_channel.h \
-include/grpc++/credentials.h \
 include/grpc++/generic/async_generic_service.h \
 include/grpc++/generic/generic_stub.h \
 include/grpc++/impl/call.h \
@@ -781,13 +780,15 @@ include/grpc++/impl/sync_no_cxx11.h \
 include/grpc++/impl/thd.h \
 include/grpc++/impl/thd_cxx11.h \
 include/grpc++/impl/thd_no_cxx11.h \
+include/grpc++/security/auth_context.h \
+include/grpc++/security/auth_metadata_processor.h \
+include/grpc++/security/credentials.h \
+include/grpc++/security/server_credentials.h \
 include/grpc++/server.h \
 include/grpc++/server_builder.h \
 include/grpc++/server_context.h \
-include/grpc++/server_credentials.h \
 include/grpc++/support/async_stream.h \
 include/grpc++/support/async_unary_call.h \
-include/grpc++/support/auth_context.h \
 include/grpc++/support/byte_buffer.h \
 include/grpc++/support/channel_arguments.h \
 include/grpc++/support/config.h \
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index 7ce66decf777b764985d2f2fab8d9812926d7156..939261da650e8c26f235cc7133e6737316477301 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -13092,7 +13092,6 @@
       "include/grpc++/client_context.h", 
       "include/grpc++/completion_queue.h", 
       "include/grpc++/create_channel.h", 
-      "include/grpc++/credentials.h", 
       "include/grpc++/generic/async_generic_service.h", 
       "include/grpc++/generic/generic_stub.h", 
       "include/grpc++/impl/call.h", 
@@ -13109,13 +13108,15 @@
       "include/grpc++/impl/thd.h", 
       "include/grpc++/impl/thd_cxx11.h", 
       "include/grpc++/impl/thd_no_cxx11.h", 
+      "include/grpc++/security/auth_context.h", 
+      "include/grpc++/security/auth_metadata_processor.h", 
+      "include/grpc++/security/credentials.h", 
+      "include/grpc++/security/server_credentials.h", 
       "include/grpc++/server.h", 
       "include/grpc++/server_builder.h", 
       "include/grpc++/server_context.h", 
-      "include/grpc++/server_credentials.h", 
       "include/grpc++/support/async_stream.h", 
       "include/grpc++/support/async_unary_call.h", 
-      "include/grpc++/support/auth_context.h", 
       "include/grpc++/support/byte_buffer.h", 
       "include/grpc++/support/channel_arguments.h", 
       "include/grpc++/support/config.h", 
@@ -13143,7 +13144,6 @@
       "include/grpc++/client_context.h", 
       "include/grpc++/completion_queue.h", 
       "include/grpc++/create_channel.h", 
-      "include/grpc++/credentials.h", 
       "include/grpc++/generic/async_generic_service.h", 
       "include/grpc++/generic/generic_stub.h", 
       "include/grpc++/impl/call.h", 
@@ -13160,13 +13160,15 @@
       "include/grpc++/impl/thd.h", 
       "include/grpc++/impl/thd_cxx11.h", 
       "include/grpc++/impl/thd_no_cxx11.h", 
+      "include/grpc++/security/auth_context.h", 
+      "include/grpc++/security/auth_metadata_processor.h", 
+      "include/grpc++/security/credentials.h", 
+      "include/grpc++/security/server_credentials.h", 
       "include/grpc++/server.h", 
       "include/grpc++/server_builder.h", 
       "include/grpc++/server_context.h", 
-      "include/grpc++/server_credentials.h", 
       "include/grpc++/support/async_stream.h", 
       "include/grpc++/support/async_unary_call.h", 
-      "include/grpc++/support/auth_context.h", 
       "include/grpc++/support/byte_buffer.h", 
       "include/grpc++/support/channel_arguments.h", 
       "include/grpc++/support/config.h", 
@@ -13272,7 +13274,6 @@
       "include/grpc++/client_context.h", 
       "include/grpc++/completion_queue.h", 
       "include/grpc++/create_channel.h", 
-      "include/grpc++/credentials.h", 
       "include/grpc++/generic/async_generic_service.h", 
       "include/grpc++/generic/generic_stub.h", 
       "include/grpc++/impl/call.h", 
@@ -13289,13 +13290,15 @@
       "include/grpc++/impl/thd.h", 
       "include/grpc++/impl/thd_cxx11.h", 
       "include/grpc++/impl/thd_no_cxx11.h", 
+      "include/grpc++/security/auth_context.h", 
+      "include/grpc++/security/auth_metadata_processor.h", 
+      "include/grpc++/security/credentials.h", 
+      "include/grpc++/security/server_credentials.h", 
       "include/grpc++/server.h", 
       "include/grpc++/server_builder.h", 
       "include/grpc++/server_context.h", 
-      "include/grpc++/server_credentials.h", 
       "include/grpc++/support/async_stream.h", 
       "include/grpc++/support/async_unary_call.h", 
-      "include/grpc++/support/auth_context.h", 
       "include/grpc++/support/byte_buffer.h", 
       "include/grpc++/support/channel_arguments.h", 
       "include/grpc++/support/config.h", 
@@ -13320,7 +13323,6 @@
       "include/grpc++/client_context.h", 
       "include/grpc++/completion_queue.h", 
       "include/grpc++/create_channel.h", 
-      "include/grpc++/credentials.h", 
       "include/grpc++/generic/async_generic_service.h", 
       "include/grpc++/generic/generic_stub.h", 
       "include/grpc++/impl/call.h", 
@@ -13337,13 +13339,15 @@
       "include/grpc++/impl/thd.h", 
       "include/grpc++/impl/thd_cxx11.h", 
       "include/grpc++/impl/thd_no_cxx11.h", 
+      "include/grpc++/security/auth_context.h", 
+      "include/grpc++/security/auth_metadata_processor.h", 
+      "include/grpc++/security/credentials.h", 
+      "include/grpc++/security/server_credentials.h", 
       "include/grpc++/server.h", 
       "include/grpc++/server_builder.h", 
       "include/grpc++/server_context.h", 
-      "include/grpc++/server_credentials.h", 
       "include/grpc++/support/async_stream.h", 
       "include/grpc++/support/async_unary_call.h", 
-      "include/grpc++/support/auth_context.h", 
       "include/grpc++/support/byte_buffer.h", 
       "include/grpc++/support/channel_arguments.h", 
       "include/grpc++/support/config.h", 
diff --git a/vsprojects/grpc++/grpc++.vcxproj b/vsprojects/grpc++/grpc++.vcxproj
index 53930c1394352599641a97a0397403f43acbd7ad..5f8b7d8f4ca7e63d4036584dbdc092c51606f324 100644
--- a/vsprojects/grpc++/grpc++.vcxproj
+++ b/vsprojects/grpc++/grpc++.vcxproj
@@ -217,7 +217,6 @@
     <ClInclude Include="..\..\include\grpc++\client_context.h" />
     <ClInclude Include="..\..\include\grpc++\completion_queue.h" />
     <ClInclude Include="..\..\include\grpc++\create_channel.h" />
-    <ClInclude Include="..\..\include\grpc++\credentials.h" />
     <ClInclude Include="..\..\include\grpc++\generic\async_generic_service.h" />
     <ClInclude Include="..\..\include\grpc++\generic\generic_stub.h" />
     <ClInclude Include="..\..\include\grpc++\impl\call.h" />
@@ -234,13 +233,15 @@
     <ClInclude Include="..\..\include\grpc++\impl\thd.h" />
     <ClInclude Include="..\..\include\grpc++\impl\thd_cxx11.h" />
     <ClInclude Include="..\..\include\grpc++\impl\thd_no_cxx11.h" />
+    <ClInclude Include="..\..\include\grpc++\security\auth_context.h" />
+    <ClInclude Include="..\..\include\grpc++\security\auth_metadata_processor.h" />
+    <ClInclude Include="..\..\include\grpc++\security\credentials.h" />
+    <ClInclude Include="..\..\include\grpc++\security\server_credentials.h" />
     <ClInclude Include="..\..\include\grpc++\server.h" />
     <ClInclude Include="..\..\include\grpc++\server_builder.h" />
     <ClInclude Include="..\..\include\grpc++\server_context.h" />
-    <ClInclude Include="..\..\include\grpc++\server_credentials.h" />
     <ClInclude Include="..\..\include\grpc++\support\async_stream.h" />
     <ClInclude Include="..\..\include\grpc++\support\async_unary_call.h" />
-    <ClInclude Include="..\..\include\grpc++\support\auth_context.h" />
     <ClInclude Include="..\..\include\grpc++\support\byte_buffer.h" />
     <ClInclude Include="..\..\include\grpc++\support\channel_arguments.h" />
     <ClInclude Include="..\..\include\grpc++\support\config.h" />
diff --git a/vsprojects/grpc++/grpc++.vcxproj.filters b/vsprojects/grpc++/grpc++.vcxproj.filters
index 6bc9ed64d2eed77bb88355bf01aaeabe3afa0d9e..38b5e14e0b52a37baa2abe0aebfb5ac0a95642ad 100644
--- a/vsprojects/grpc++/grpc++.vcxproj.filters
+++ b/vsprojects/grpc++/grpc++.vcxproj.filters
@@ -111,9 +111,6 @@
     <ClInclude Include="..\..\include\grpc++\create_channel.h">
       <Filter>include\grpc++</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\include\grpc++\credentials.h">
-      <Filter>include\grpc++</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\include\grpc++\generic\async_generic_service.h">
       <Filter>include\grpc++\generic</Filter>
     </ClInclude>
@@ -162,6 +159,18 @@
     <ClInclude Include="..\..\include\grpc++\impl\thd_no_cxx11.h">
       <Filter>include\grpc++\impl</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\include\grpc++\security\auth_context.h">
+      <Filter>include\grpc++\security</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\grpc++\security\auth_metadata_processor.h">
+      <Filter>include\grpc++\security</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\grpc++\security\credentials.h">
+      <Filter>include\grpc++\security</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\grpc++\security\server_credentials.h">
+      <Filter>include\grpc++\security</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\include\grpc++\server.h">
       <Filter>include\grpc++</Filter>
     </ClInclude>
@@ -171,18 +180,12 @@
     <ClInclude Include="..\..\include\grpc++\server_context.h">
       <Filter>include\grpc++</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\include\grpc++\server_credentials.h">
-      <Filter>include\grpc++</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\include\grpc++\support\async_stream.h">
       <Filter>include\grpc++\support</Filter>
     </ClInclude>
     <ClInclude Include="..\..\include\grpc++\support\async_unary_call.h">
       <Filter>include\grpc++\support</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\include\grpc++\support\auth_context.h">
-      <Filter>include\grpc++\support</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\include\grpc++\support\byte_buffer.h">
       <Filter>include\grpc++\support</Filter>
     </ClInclude>
@@ -257,6 +260,9 @@
     <Filter Include="include\grpc++\impl">
       <UniqueIdentifier>{0da8cd95-314f-da1b-5ce7-7791a5be1f1a}</UniqueIdentifier>
     </Filter>
+    <Filter Include="include\grpc++\security">
+      <UniqueIdentifier>{a80eb32b-1be9-1187-5f40-30d92accecc8}</UniqueIdentifier>
+    </Filter>
     <Filter Include="include\grpc++\support">
       <UniqueIdentifier>{a5c10dae-f715-2a30-1066-d22f8bc94cb2}</UniqueIdentifier>
     </Filter>
diff --git a/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj
index 12fa1b781cb61e53bb97c38ca7351c2e90bc1b22..68154c67ec7f838737296b2c92e8aaba75697676 100644
--- a/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj
+++ b/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj
@@ -217,7 +217,6 @@
     <ClInclude Include="..\..\include\grpc++\client_context.h" />
     <ClInclude Include="..\..\include\grpc++\completion_queue.h" />
     <ClInclude Include="..\..\include\grpc++\create_channel.h" />
-    <ClInclude Include="..\..\include\grpc++\credentials.h" />
     <ClInclude Include="..\..\include\grpc++\generic\async_generic_service.h" />
     <ClInclude Include="..\..\include\grpc++\generic\generic_stub.h" />
     <ClInclude Include="..\..\include\grpc++\impl\call.h" />
@@ -234,13 +233,15 @@
     <ClInclude Include="..\..\include\grpc++\impl\thd.h" />
     <ClInclude Include="..\..\include\grpc++\impl\thd_cxx11.h" />
     <ClInclude Include="..\..\include\grpc++\impl\thd_no_cxx11.h" />
+    <ClInclude Include="..\..\include\grpc++\security\auth_context.h" />
+    <ClInclude Include="..\..\include\grpc++\security\auth_metadata_processor.h" />
+    <ClInclude Include="..\..\include\grpc++\security\credentials.h" />
+    <ClInclude Include="..\..\include\grpc++\security\server_credentials.h" />
     <ClInclude Include="..\..\include\grpc++\server.h" />
     <ClInclude Include="..\..\include\grpc++\server_builder.h" />
     <ClInclude Include="..\..\include\grpc++\server_context.h" />
-    <ClInclude Include="..\..\include\grpc++\server_credentials.h" />
     <ClInclude Include="..\..\include\grpc++\support\async_stream.h" />
     <ClInclude Include="..\..\include\grpc++\support\async_unary_call.h" />
-    <ClInclude Include="..\..\include\grpc++\support\auth_context.h" />
     <ClInclude Include="..\..\include\grpc++\support\byte_buffer.h" />
     <ClInclude Include="..\..\include\grpc++\support\channel_arguments.h" />
     <ClInclude Include="..\..\include\grpc++\support\config.h" />
diff --git a/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
index 17d9d5332f0f9ce4852231e99f18f167889872b9..52582d3aed67c8bef08e75ffac1ec27d493658e7 100644
--- a/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
+++ b/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
@@ -96,9 +96,6 @@
     <ClInclude Include="..\..\include\grpc++\create_channel.h">
       <Filter>include\grpc++</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\include\grpc++\credentials.h">
-      <Filter>include\grpc++</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\include\grpc++\generic\async_generic_service.h">
       <Filter>include\grpc++\generic</Filter>
     </ClInclude>
@@ -147,6 +144,18 @@
     <ClInclude Include="..\..\include\grpc++\impl\thd_no_cxx11.h">
       <Filter>include\grpc++\impl</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\include\grpc++\security\auth_context.h">
+      <Filter>include\grpc++\security</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\grpc++\security\auth_metadata_processor.h">
+      <Filter>include\grpc++\security</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\grpc++\security\credentials.h">
+      <Filter>include\grpc++\security</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\grpc++\security\server_credentials.h">
+      <Filter>include\grpc++\security</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\include\grpc++\server.h">
       <Filter>include\grpc++</Filter>
     </ClInclude>
@@ -156,18 +165,12 @@
     <ClInclude Include="..\..\include\grpc++\server_context.h">
       <Filter>include\grpc++</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\include\grpc++\server_credentials.h">
-      <Filter>include\grpc++</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\include\grpc++\support\async_stream.h">
       <Filter>include\grpc++\support</Filter>
     </ClInclude>
     <ClInclude Include="..\..\include\grpc++\support\async_unary_call.h">
       <Filter>include\grpc++\support</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\include\grpc++\support\auth_context.h">
-      <Filter>include\grpc++\support</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\include\grpc++\support\byte_buffer.h">
       <Filter>include\grpc++\support</Filter>
     </ClInclude>
@@ -233,6 +236,9 @@
     <Filter Include="include\grpc++\impl">
       <UniqueIdentifier>{dadc0002-f2ac-451b-a9b8-33b8de10b5fc}</UniqueIdentifier>
     </Filter>
+    <Filter Include="include\grpc++\security">
+      <UniqueIdentifier>{64bf60ff-9192-bb59-dcc8-8a0021e1d016}</UniqueIdentifier>
+    </Filter>
     <Filter Include="include\grpc++\support">
       <UniqueIdentifier>{0ebf8008-80b9-d6da-e1dc-854bf1ec2195}</UniqueIdentifier>
     </Filter>