title: NodeJS + Android SSL Authentication
body: <p>I have no idea how to debug this, been at this for a while now, any pointers would be appreciated.</p>
  
  <p>I am trying out ssl/tls authentication between an Android app and a Nodejs server. I am running into this error message when I run the android app:</p>
  
  <pre><code>10-31 23:33:58.260: D/ExampleActivity(26199): Response code: 401
  10-31 23:34:05.901: W/DefaultRequestDirector(26199): Authentication error: Unable to respond to any of these challenges: {}
  </code></pre>
  
  <p><strong>Note</strong> that I have commented out the client authentication parts, and just trying to get basic SSL authentication working. Even that gives me the same warning/error.</p>
  
  <h2>NodeJs - Server.js</h2>
  
  <pre><code>var https = require('https'),
      fs = require('fs');
  
  var options = {
      key: fs.readFileSync('certs/server_key.pem'),
      cert: fs.readFileSync('certs/server.pem'),
     // ca: [fs.readFileSync('certs/client.pem')],
      passphrase: '33333',
     // requestCert: true,
     // rejectUnauthorized: false
  };
  
  https.createServer(options, function (req, res) {
      if (req.client.authorized) {
          res.writeHead(200, {"Content-Type": "application/json"});
          res.end('{"status":"approved"}');
      } else {
          res.writeHead(401, {"Content-Type": "application/json"});
          res.end('{"status":"denied"}');
      }
  }).listen(8000);
  </code></pre>
  
  <h2>Android</h2>
  
  <pre><code>public class SecureHttpClient extends DefaultHttpClient {
      private String ks = "11111";
      private String ts = "22222";
      private Context context;
  
      public SecureHttpClient(final Context context) {
          super();
          this.context = context;
      }
  
      @Override
      protected ClientConnectionManager createClientConnectionManager() {
          SchemeRegistry registry = new SchemeRegistry();
          SSLSocketFactory factory = newSslSocketFactory();
          factory.setHostnameVerifier((X509HostnameVerifier) SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
  
          registry.register(new Scheme("https", factory, 443));
          HttpParams httpParams = new BasicHttpParams();
          return new SingleClientConnManager(httpParams, registry);
      }
  
      private SSLSocketFactory newSslSocketFactory() {
          try {
              KeyStore keyStore = KeyStore.getInstance("BKS");
              KeyStore trustStore = KeyStore.getInstance("BKS");
              InputStream inKey= context.getResources().openRawResource(R.raw.client);
              InputStream inTrust = context.getResources().openRawResource(R.raw.clienttruststore);
              try {
                  keyStore.load(inKey, ks.toCharArray());
                  trustStore.load(inTrust, ts.toCharArray());
              } finally {
                  inKey.close();
                  inTrust.close();
              }
              return new SSLSocketFactory(trustStore);
          } catch (Exception e) {
              throw new AssertionError(e);
          }
      }
  }
  </code></pre>
  
  <p>// MainActivity</p>
  
  <pre><code>public class MainActivity extends Activity {
  
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
  
          setStrictMode();
  
          final HttpClient client = new SecureHttpClient(this);
  
          // Provide ip or address to where your test server is runnning
          final HttpGet request = new HttpGet("https://192.168.0.105:8000/");
  
          HttpResponse response = null;
          try {
              response = client.execute(request);
          } catch (ClientProtocolException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          } catch (IOException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
  
          Log.d("ExampleActivity", "Response code: " + response.getStatusLine().getStatusCode());
      }
  
      @TargetApi(9) 
      private void setStrictMode() {
          StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
  
          StrictMode.setThreadPolicy(policy); 
      }
  
      @Override
      public boolean onCreateOptionsMenu(Menu menu) {
          getMenuInflater().inflate(R.menu.activity_main, menu);
          return true;
      }
  }
  </code></pre>