auth context iterator
diff --git a/include/grpc++/auth_context.h b/include/grpc++/auth_context.h
index 158f8e3..394cb34 100644
--- a/include/grpc++/auth_context.h
+++ b/include/grpc++/auth_context.h
@@ -34,15 +34,43 @@
 #ifndef GRPCXX_AUTH_CONTEXT_H
 #define GRPCXX_AUTH_CONTEXT_H
 
+#include <iterator>
 #include <vector>
 
 #include <grpc++/config.h>
 
+struct grpc_auth_context;
+struct grpc_auth_property;
+struct grpc_auth_property_iterator;
+
 namespace grpc {
+class SecureAuthContext;
 
 class AuthContext {
  public:
   typedef std::pair<grpc::string, grpc::string> Property;
+  class PropertyIterator
+      : public std::iterator<std::input_iterator_tag, const Property> {
+   public:
+    ~PropertyIterator();
+    PropertyIterator& operator++();
+    PropertyIterator operator++(int);
+    bool operator==(const PropertyIterator& rhs) const;
+    bool operator!=(const PropertyIterator& rhs) const;
+    const Property operator*();
+
+   private:
+    friend SecureAuthContext;
+    PropertyIterator();
+    PropertyIterator(const grpc_auth_property* property,
+                     const grpc_auth_property_iterator* iter);
+    const grpc_auth_property* property_;
+    // The following items form a grpc_auth_property_iterator.
+    const grpc_auth_context* ctx_;
+    size_t index_;
+    const char* name_;
+  };
+  typedef PropertyIterator const_iterator;
 
   virtual ~AuthContext() {}
 
@@ -54,6 +82,10 @@
   // Returns all the property values with the given name.
   virtual std::vector<grpc::string> FindPropertyValues(
       const grpc::string& name) const = 0;
+
+  // Iteration over all the properties.
+  virtual const_iterator begin() const = 0;
+  virtual const_iterator end() const = 0;
 };
 
 }  // namespace grpc
diff --git a/src/cpp/common/secure_auth_context.cc b/src/cpp/common/secure_auth_context.cc
index 4513723..53b940f 100644
--- a/src/cpp/common/secure_auth_context.cc
+++ b/src/cpp/common/secure_auth_context.cc
@@ -77,4 +77,67 @@
   return values;
 }
 
+AuthContext::PropertyIterator::PropertyIterator()
+    : property_(nullptr), ctx_(nullptr), index_(0), name_(nullptr) {}
+
+AuthContext::PropertyIterator::PropertyIterator(
+    const grpc_auth_property* property, const grpc_auth_property_iterator* iter)
+    : property_(property),
+      ctx_(iter->ctx),
+      index_(iter->index),
+      name_(iter->name) {}
+
+AuthContext::PropertyIterator::~PropertyIterator() {}
+
+AuthContext::PropertyIterator& AuthContext::PropertyIterator::operator++() {
+  grpc_auth_property_iterator iter = {ctx_, index_, name_};
+  property_ = grpc_auth_property_iterator_next(&iter);
+  ctx_ = iter.ctx;
+  index_ = iter.index;
+  name_ = iter.name;
+  return *this;
+}
+
+AuthContext::PropertyIterator AuthContext::PropertyIterator::operator++(int) {
+  PropertyIterator tmp(*this);
+  operator++();
+  return tmp;
+}
+
+bool AuthContext::PropertyIterator::operator==(
+    const AuthContext::PropertyIterator& rhs) const {
+  if (property_ == nullptr || rhs.property_ == nullptr) {
+    return property_ == rhs.property_;
+  } else {
+    return index_ == rhs.index_;
+  }
+}
+
+bool AuthContext::PropertyIterator::operator!=(
+    const AuthContext::PropertyIterator& rhs) const {
+  return !operator==(rhs);
+}
+
+const AuthContext::Property AuthContext::PropertyIterator::operator*() {
+  return std::make_pair<grpc::string, grpc::string>(
+      grpc::string(property_->name),
+      grpc::string(property_->value, property_->value_length));
+}
+
+SecureAuthContext::const_iterator SecureAuthContext::begin() const {
+  if (ctx_) {
+    grpc_auth_property_iterator iter =
+        grpc_auth_context_property_iterator(ctx_);
+    const grpc_auth_property* property =
+        grpc_auth_property_iterator_next(&iter);
+    return AuthContext::PropertyIterator(property, &iter);
+  } else {
+    return end();
+  }
+}
+
+SecureAuthContext::const_iterator SecureAuthContext::end() const {
+  return AuthContext::PropertyIterator();
+}
+
 }  // namespace grpc
diff --git a/src/cpp/common/secure_auth_context.h b/src/cpp/common/secure_auth_context.h
index bba4680..9ea4eb1 100644
--- a/src/cpp/common/secure_auth_context.h
+++ b/src/cpp/common/secure_auth_context.h
@@ -53,6 +53,10 @@
   std::vector<grpc::string> FindPropertyValues(const grpc::string& name) const
       GRPC_OVERRIDE;
 
+  const_iterator begin() const GRPC_OVERRIDE;
+
+  const_iterator end() const GRPC_OVERRIDE;
+
  private:
   grpc_auth_context* ctx_;
 };
diff --git a/test/cpp/common/secure_auth_context_test.cc b/test/cpp/common/secure_auth_context_test.cc
index a1819dc..6cc271f 100644
--- a/test/cpp/common/secure_auth_context_test.cc
+++ b/test/cpp/common/secure_auth_context_test.cc
@@ -48,6 +48,7 @@
   EXPECT_TRUE(context.GetPeerIdentityPropertyName().empty());
   EXPECT_TRUE(context.FindPropertyValues("").empty());
   EXPECT_TRUE(context.FindPropertyValues("whatever").empty());
+  EXPECT_TRUE(context.begin() == context.end());
 }
 
 TEST_F(SecureAuthContextTest, Properties) {
@@ -68,6 +69,31 @@
   EXPECT_EQ("bar", bar[0]);
 }
 
+TEST_F(SecureAuthContextTest, Iterators) {
+  grpc_auth_context* ctx = grpc_auth_context_create(NULL, 3);
+  ctx->properties[0] = grpc_auth_property_init_from_cstring("name", "chapi");
+  ctx->properties[1] = grpc_auth_property_init_from_cstring("name", "chapo");
+  ctx->properties[2] = grpc_auth_property_init_from_cstring("foo", "bar");
+  ctx->peer_identity_property_name = ctx->properties[0].name;
+
+  SecureAuthContext context(ctx);
+  AuthContext::const_iterator iter = context.begin();
+  EXPECT_TRUE(context.end() != iter);
+  AuthContext::Property p0 = *iter;
+  ++iter;
+  AuthContext::Property p1 = *iter;
+  iter++;
+  AuthContext::Property p2 = *iter;
+  EXPECT_EQ("name", p0.first);
+  EXPECT_EQ("chapi", p0.second);
+  EXPECT_EQ("name", p1.first);
+  EXPECT_EQ("chapo", p1.second);
+  EXPECT_EQ("foo", p2.first);
+  EXPECT_EQ("bar", p2.second);
+  ++iter;
+  EXPECT_EQ(context.end(), iter);
+}
+
 }  // namespace
 }  // namespace grpc