Geode-4728: User Guide - improve authentication explanation
diff --git a/docs/geode-native-docs/security/SampleAuth.cpp b/docs/geode-native-docs/security/SampleAuth.cpp
new file mode 100644
index 0000000..026f86f
--- /dev/null
+++ b/docs/geode-native-docs/security/SampleAuth.cpp
@@ -0,0 +1,92 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one or more

+ * contributor license agreements.  See the NOTICE file distributed with

+ * this work for additional information regarding copyright ownership.

+ * The ASF licenses this file to You under the Apache License, Version 2.0

+ * (the "License"); you may not use this file except in compliance with

+ * the License.  You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+#include <iostream>

+

+#include <geode/CacheFactory.hpp>

+#include <geode/PoolManager.hpp>

+#include <geode/RegionFactory.hpp>

+#include <geode/RegionShortcut.hpp>

+#include <geode/AuthInitialize.hpp>

+

+using namespace apache::geode::client;

+

+constexpr auto SECURITY_USERNAME = "security-username";

+constexpr auto SECURITY_PASSWORD = "security-password";

+

+class UserPasswordAuthInit : public AuthInitialize {

+public:

+  UserPasswordAuthInit() = default;

+  

+  ~UserPasswordAuthInit() noexcept override = default;

+  

+  std::shared_ptr<Properties> getCredentials(

+    const std::shared_ptr<Properties> &securityprops,

+    const std::string &) override {

+    std::shared_ptr<Cacheable> userName;

+    if (securityprops == nullptr ||

+      (userName = securityprops->find(SECURITY_USERNAME)) == nullptr) {

+      throw AuthenticationFailedException(

+      "UserPasswordAuthInit: user name "

+      "property [SECURITY_USERNAME] not set.");

+    }

+  

+    auto credentials = Properties::create();

+    credentials->insert(SECURITY_USERNAME, userName->toString().c_str());

+    auto passwd = securityprops->find(SECURITY_PASSWORD);

+    if (passwd == nullptr) {

+      passwd = CacheableString::create("");

+    }

+    credentials->insert(SECURITY_PASSWORD, passwd->value().c_str());

+    return credentials;

+  }

+

+  void close() override { return; }

+};

+

+int main(int argc, char** argv) {

+  auto config = Properties::create();

+  config->insert(SECURITY_USERNAME, "root");

+  config->insert(SECURITY_PASSWORD, "root");

+

+  auto cacheFactory = CacheFactory(config);

+  auto authInitialize = std::make_shared<UserPasswordAuthInit>();

+  cacheFactory.set("log-level", "none");

+  cacheFactory.setAuthInitialize(authInitialize);

+

+  auto cache = cacheFactory.create();

+  auto poolFactory = cache.getPoolManager().createFactory();

+

+  poolFactory.addLocator("localhost", 10334);

+  auto pool = poolFactory.create("pool");

+  auto regionFactory = cache.createRegionFactory(RegionShortcut::PROXY);

+  auto region = regionFactory.setPoolName("pool").create("example_userinfo");

+

+  region->put("rtimmons", "Robert Timmons");

+  region->put("scharles", "Sylvia Charles");

+

+  auto user1 = region->get("rtimmons");

+  auto user2 = region->get("scharles");

+  std::cout << "  rtimmons = "

+            << std::dynamic_pointer_cast<CacheableString>(user1)->value()

+            << std::endl;

+  std::cout << "  scharles = "

+            << std::dynamic_pointer_cast<CacheableString>(user2)->value()

+            << std::endl;

+

+  cache.close();

+}

diff --git a/docs/geode-native-docs/security/SampleAuth.cs b/docs/geode-native-docs/security/SampleAuth.cs
index 4b7181e..272b048 100644
--- a/docs/geode-native-docs/security/SampleAuth.cs
+++ b/docs/geode-native-docs/security/SampleAuth.cs
@@ -22,6 +22,32 @@
 {

   class Program

   {

+    class ExampleAuthInitialize : IAuthInitialize

+    {

+      public ExampleAuthInitialize()

+      {

+	  // TODO initialize your resources here

+	  Console.Out.WriteLine("ExampleAuthInitialize::ExampleAuthInitialize called");

+      }

+

+      public void Close()

+      {

+	  // TODO close your resources here

+	  Console.Out.WriteLine("ExampleAuthInitialize::Close called");

+      }

+

+      public Properties<string, object> GetCredentials(Properties<string, string> props, string server)

+      {

+	  // TODO get your username and password

+	  Console.Out.WriteLine("ExampleAuthInitialize::GetCredentials called");

+

+	  var credentials = new Properties<string, object>();

+	  credentials.Insert("username", "john");

+	  credentials.Insert("password", "secret");

+	  return credentials;

+      }

+    }

+

     static void Main(string[] args)

     {

       var cacheFactory = new CacheFactory()

@@ -48,30 +74,4 @@
       cache.Close();

     }

   }

-

-  class ExampleAuthInitialize : IAuthInitialize

-  {

-    public ExampleAuthInitialize()

-    {

-        // TODO initialize your resources here

-        Console.Out.WriteLine("ExampleAuthInitialize::ExampleAuthInitialize called");

-    }

-

-    public void Close()

-    {

-        // TODO close your resources here

-        Console.Out.WriteLine("ExampleAuthInitialize::Close called");

-    }

-

-    public Properties<string, object> GetCredentials(Properties<string, string> props, string server)

-    {

-        // TODO get your username and password

-        Console.Out.WriteLine("ExampleAuthInitialize::GetCredentials called");

-

-        var credentials = new Properties<string, object>();

-        credentials.Insert("username", "john");

-        credentials.Insert("password", "secret");

-        return credentials;

-    }

-  }

 }

diff --git a/docs/geode-native-docs/security/authentication.html.md.erb b/docs/geode-native-docs/security/authentication.html.md.erb
index 098527b..faca71b 100644
--- a/docs/geode-native-docs/security/authentication.html.md.erb
+++ b/docs/geode-native-docs/security/authentication.html.md.erb
@@ -21,12 +21,19 @@
 
 A client is authenticated when it connects, with valid credentials, to a <%=vars.product_name%> cache server that is configured with the client `Authenticator` callback.
 
-Examples of various implementations can be found in the Native Client source distribution's `../templates/security`` directory.
+Examples of various implementations can be found in the Native Client source distribution's `../templates/security` directory.
 
 An `AuthenticationRequiredException` is thrown when the server is configured with security and the
 client does not present its credentials while attempting to connect.
 
-The following excerpts are taken from the .NET example provided with your Native Client distribution in the `../examples/dotnet/AuthInitialize` directory.
+In your application, authentication credentials must be set when creating the cache. In practice,
+this means setting the authentication credentials when you create the CacheFactory.
+
+### .NET Authentication Example
+
+The following excerpt is taken from the .NET example provided with your Native Client distribution in the `../examples/dotnet/AuthInitialize` directory.
+In this C# authentication example, credentials are implemented in the GetCredentials member function of the ExampleAuthInitialize class, which implements the IAuthInitialize interface.
+
 
 ```cs
 using System;
@@ -36,6 +43,32 @@
 {
   class Program
   {
+    class ExampleAuthInitialize : IAuthInitialize
+    {
+	public ExampleAuthInitialize()
+	{
+	    // TODO initialize your resources here
+	    Console.Out.WriteLine("ExampleAuthInitialize::ExampleAuthInitialize called");
+	}
+
+	public void Close()
+	{
+	    // TODO close your resources here
+	    Console.Out.WriteLine("ExampleAuthInitialize::Close called");
+	}
+
+	public Properties<string, object> GetCredentials(Properties<string, string> props, string server)
+	{
+	    // TODO get your username and password
+	    Console.Out.WriteLine("ExampleAuthInitialize::GetCredentials called");
+
+	    var credentials = new Properties<string, object>();
+	    credentials.Insert("username", "john");
+	    credentials.Insert("password", "secret");
+	    return credentials;
+	}
+      }
+
     static void Main(string[] args)
     {
       var cacheFactory = new CacheFactory()
@@ -62,32 +95,88 @@
       cache.Close();
     }
   }
-
-  class ExampleAuthInitialize : IAuthInitialize
-  {
-    public ExampleAuthInitialize()
-    {
-        // TODO initialize your resources here
-        Console.Out.WriteLine("ExampleAuthInitialize::ExampleAuthInitialize called");
-    }
-
-    public void Close()
-    {
-        // TODO close your resources here
-        Console.Out.WriteLine("ExampleAuthInitialize::Close called");
-    }
-
-    public Properties<string, object> GetCredentials(Properties<string, string> props, string server)
-    {
-        // TODO get your username and password
-        Console.Out.WriteLine("ExampleAuthInitialize::GetCredentials called");
-
-        var credentials = new Properties<string, object>();
-        credentials.Insert("username", "john");
-        credentials.Insert("password", "secret");
-        return credentials;
-    }
-  }
 }
 
 ```
+
+### C++ Authentication Example
+
+In this C++ authentication example, credentials are implemented in the getCredentials member function of the AuthInitialize abstract class.
+
+```cpp
+#include <iostream>
+
+#include <geode/CacheFactory.hpp>
+#include <geode/PoolManager.hpp>
+#include <geode/RegionFactory.hpp>
+#include <geode/RegionShortcut.hpp>
+#include <geode/AuthInitialize.hpp>
+
+using namespace apache::geode::client;
+
+constexpr auto SECURITY_USERNAME = "security-username";
+constexpr auto SECURITY_PASSWORD = "security-password";
+
+class UserPasswordAuthInit : public AuthInitialize {
+public:
+  UserPasswordAuthInit() = default;
+  
+  ~UserPasswordAuthInit() noexcept override = default;
+  
+  std::shared_ptr<Properties> getCredentials(
+    const std::shared_ptr<Properties> &securityprops,
+    const std::string &) override {
+    std::shared_ptr<Cacheable> userName;
+    if (securityprops == nullptr ||
+      (userName = securityprops->find(SECURITY_USERNAME)) == nullptr) {
+      throw AuthenticationFailedException(
+      "UserPasswordAuthInit: user name "
+      "property [SECURITY_USERNAME] not set.");
+    }
+  
+    auto credentials = Properties::create();
+    credentials->insert(SECURITY_USERNAME, userName->toString().c_str());
+    auto passwd = securityprops->find(SECURITY_PASSWORD);
+    if (passwd == nullptr) {
+      passwd = CacheableString::create("");
+    }
+    credentials->insert(SECURITY_PASSWORD, passwd->value().c_str());
+    return credentials;
+  }
+
+  void close() override { return; }
+};
+
+int main(int argc, char** argv) {
+  auto config = Properties::create();
+  config->insert(SECURITY_USERNAME, "root");
+  config->insert(SECURITY_PASSWORD, "root");
+
+  auto cacheFactory = CacheFactory(config);
+  auto authInitialize = std::make_shared<UserPasswordAuthInit>();
+  cacheFactory.set("log-level", "none");
+  cacheFactory.setAuthInitialize(authInitialize);
+
+  auto cache = cacheFactory.create();
+  auto poolFactory = cache.getPoolManager().createFactory();
+
+  poolFactory.addLocator("localhost", 10334);
+  auto pool = poolFactory.create("pool");
+  auto regionFactory = cache.createRegionFactory(RegionShortcut::PROXY);
+  auto region = regionFactory.setPoolName("pool").create("example_userinfo");
+
+  region->put("rtimmons", "Robert Timmons");
+  region->put("scharles", "Sylvia Charles");
+
+  auto user1 = region->get("rtimmons");
+  auto user2 = region->get("scharles");
+  std::cout << "  rtimmons = "
+            << std::dynamic_pointer_cast<CacheableString>(user1)->value()
+            << std::endl;
+  std::cout << "  scharles = "
+            << std::dynamic_pointer_cast<CacheableString>(user2)->value()
+            << std::endl;
+
+  cache.close();
+}
+```