diff --git a/include/grpc++/auth_metadata_processor.h b/include/grpc++/auth_metadata_processor.h
index 3caf3e84fdaa708f435d00710001a2e209c157ea..c0631bc11fabd7dd3056b30095d5aa67f7adc9f7 100644
--- a/include/grpc++/auth_metadata_processor.h
+++ b/include/grpc++/auth_metadata_processor.h
@@ -35,14 +35,18 @@
 #define GRPCXX_AUTH_METADATA_PROCESSOR_H_
 
 #include <map>
-#include <string>
 
 #include <grpc++/support/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
@@ -54,11 +58,11 @@ class AuthMetadataProcessor {
   // 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.
-  // Returns true if successful.
-  virtual bool Process(
-      const std::multimap<grpc::string, grpc::string>& auth_metadata,
-      AuthContext* context,
-      std::multimap<grpc::string, grpc::string>* consumed_auth_metadata) = 0;
+  // TODO(jboeuf).
+  virtual Status Process(const InputMetadata& auth_metadata,
+                         AuthContext* context,
+                         OutputMetadata* consumed_auth_metadata,
+                         OutputMetadata* response_metadata) = 0;
 };
 
 }  // namespace grpc
diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc
index a7d11856a01c2f0eaba05db9c9b53b3414ccf8cd..86c180e7e23d171b58362971d1780ff5737aebdc 100644
--- a/src/cpp/server/secure_server_credentials.cc
+++ b/src/cpp/server/secure_server_credentials.cc
@@ -66,28 +66,40 @@ 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) {
-  Metadata metadata;
+  AuthMetadataProcessor::InputMetadata metadata;
   for (size_t i = 0; i < num_md; i++) {
     metadata.insert(std::make_pair(
-        md[i].key, grpc::string(md[i].value, md[i].value_length)));
+        md[i].key, grpc::string_ref(md[i].value, md[i].value_length)));
   }
   SecureAuthContext context(ctx);
-  Metadata consumed_metadata;
-  bool ok = processor_->Process(metadata, &context, &consumed_metadata);
-  if (ok) {
-    std::vector<grpc_metadata> consumed_md(consumed_metadata.size());
-    for (const auto& entry : consumed_metadata) {
-      consumed_md.push_back({entry.first.c_str(),
-                             entry.second.data(),
-                             entry.second.size(),
-                             0,
-                             {{nullptr, nullptr, nullptr, nullptr}}});
-    }
-    cb(user_data, &consumed_md[0], consumed_md.size(), nullptr, 0,
-       GRPC_STATUS_OK, nullptr);
-  } else {
-    cb(user_data, nullptr, 0, nullptr, 0, GRPC_STATUS_UNAUTHENTICATED, nullptr);
+  AuthMetadataProcessor::OutputMetadata consumed_metadata;
+  AuthMetadataProcessor::OutputMetadata response_metadata;
+
+  Status status = processor_->Process(metadata, &context, &consumed_metadata,
+                                      &response_metadata);
+
+  std::vector<grpc_metadata> consumed_md(consumed_metadata.size());
+  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(response_metadata.size());
+  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,
diff --git a/src/cpp/server/secure_server_credentials.h b/src/cpp/server/secure_server_credentials.h
index e427280a376a0cf88fc31b6ab8acb0a2cf021965..d15b793b15d2b07732f5b509d629f177bf06aaf9 100644
--- a/src/cpp/server/secure_server_credentials.h
+++ b/src/cpp/server/secure_server_credentials.h
@@ -55,7 +55,6 @@ class AuthMetadataProcessorAyncWrapper GRPC_FINAL {
       : thread_pool_(CreateDefaultThreadPool()), processor_(processor) {}
 
  private:
-  typedef std::multimap<grpc::string, grpc::string> Metadata;
   void InvokeProcessor(grpc_auth_context* context, const grpc_metadata* md,
                        size_t num_md, grpc_process_auth_metadata_done_cb cb,
                        void* user_data);