<h1 id="heading-security-reference"><a name="heading-security-reference">Security Reference</a></h1><p>This API project by default has built-in security through the use of a pre-generated unique set of API keys.  These keys can be changed at any time by setting them in your configuration file location in the <code>conf</code> directory. However, make sure that you generated sufficiently random values.  Do not share these keys with other API projects and be careful with these keys since they control access to your API.  By default, two keys were generated: one for production and one for development.  When you are running locally (running outside of the Appcelerator Cloud) the server will use the value of the <code>apikey_development</code> key.  When you publish your project to the Appcelerator Cloud, it will run in production and use the value of the <code>apikey_production</code> key.   To simulate running in production, set the environment variable NODE_ENV to <code>production</code> before running such as <code>NODE_ENV=production appc run</code>.  If you want to only use one key, you can set the value of the API Key to <code>apikey</code> in your configuration.</p>
<h2 id="heading-authentication-strategies"><a name="heading-authentication-strategies">Authentication Strategies</a></h2><p>Arrow supports 4 different authentication strategies.</p>
<ul>
<li><strong>HTTP Basic Authentication</strong> (default).  The client will use the HTTP <code>Authorization</code> header to send an encoded version of the API Key using the <a href="http://en.wikipedia.org/wiki/Basic_access_authentication">HTTP Basic Authentication</a> standard. The username part is the value of the API Key and the password part should be blank (empty string). Use the value <code>basic</code> for the key <code>APIKeyAuthType</code> to use this strategy.</li>
<li><strong>HTTP Header Authentication</strong>. The client will set the HTTP <code>APIKey</code> header to the value of the API Key.  In this scenario, the server MUST only support HTTPS only endpoints so that the key is not passed in plain text. Use the value <code>apikey</code> for the key <code>APIKeyAuthType</code> to use this strategy.</li>
<li><strong>LDAP Authentication</strong>. The client will use the HTTP <code>Authorization</code> header to send an encoded version of the API Key using the <a href="http://en.wikipedia.org/wiki/Basic_access_authentication">HTTP Basic Authentication</a> standard. The username and password will be sent to the configured LDAP server for authentication. Use the value <code>ldap</code> for the key <code>APIKeyAuthType</code> to use this strategy.  See the example below for using LDAP configuration.</li>
<li><strong>No Authentication</strong>.  The client does not need any authentication to access these APIs.  In this case, all client requests will be accepted without any security. Use the value <code>none</code> for the key <code>APIKeyAuthType</code> to use this strategy.</li>
<li><strong>Custom Plugin</strong>.  Using the plugin strategy, you can extend the authentication to use any third-party or custom API authentication.  To build your own plugin, set the value <code>plugin</code> for the key <code>APIKeyAuthType</code> to use this strategy and then set the key <code>APIKeyAuthPlugin</code> to the location of your plugin.  The location can either be a file path (relative to the current work directory of your server project directory) or the name of the module package available in the standard <code>node_modules</code> location.</li>
</ul>
<h2 id="heading-authentication-plugin-api"><a name="heading-authentication-plugin-api">Authentication Plugin API</a></h2><p>The Plugin must return a JavaScript Class Constructor (function) that can be instantiated to handle authentication requests for every incoming API.  The following is a basic API example:</p>
<pre class="highlight javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Plugin</span>(<span class="hljs-params">server</span>) </span>{
    <span class="hljs-keyword">this</span>.config = server.config;
}

Plugin.prototype.matchURL = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req</span>) </span>{
    <span class="hljs-comment">// match all requests that aren't for our admin</span>
    <span class="hljs-keyword">return</span> req.url.indexOf(<span class="hljs-keyword">this</span>.config.admin.prefix)!==<span class="hljs-number">0</span>;
};

Plugin.prototype.validateRequest = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req, resp</span>) </span>{
    <span class="hljs-comment">// check the value of the incoming request</span>
    <span class="hljs-keyword">return</span> req.headers.foo === <span class="hljs-string">'bar'</span>;
};

Plugin.prototype.applyCredentialsForTest = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">opts</span>) </span>{
    <span class="hljs-comment">// when testing, use our header key/value</span>
    opts.headers.foo = <span class="hljs-string">'bar'</span>;
};

<span class="hljs-built_in">module</span>.exports = Plugin;</pre><p>The <code>matchURL</code> function is optional. If not provided, all requests will be forwarded to <code>validateRequest</code>.</p>
<p>The <code>validateRequest</code> function can either be synchronous or asyncronous.  To use a synchronous implementation, you just define your function with either one or two parameters (<code>req</code> for the HTTP request and/or <code>resp</code> for the HTTP response).  The return value must either be <code>true</code> (passed) or <code>false</code> (failed).  You can also throw and exception if you would prefer to provide an Error to the client.  To use an asynchronous implementation, you must define all 3 function parameters (same as above with the addition of the 3rd parameter which is a function callback to call when you have completed).  This is useful in cases where you need to perform some tasks which may not be synchronous.  In the asynchoronous callback you must call the callback with 2 parameters.  The first parameter is an Error if you want to return an error to the client.  The second is a boolean success value (same as above).</p>
<p>The <code>applyCredentialsForTest</code> function will be called by the internal test framework before forwarding the request to your API.  This is useful when you have a custom plugin and you need to setup the HTTP request used during testing (from the documentation page for the API).</p>
<h3 id="heading-ldap-authentication-plugin"><a name="heading-ldap-authentication-plugin">LDAP Authentication Plugin</a></h3><p>To configure the LDAP Authentication plugin, you must set the following in your configuration:</p>
<pre class="highlight javascript">ldap: {
    <span class="hljs-attr">url</span>: <span class="hljs-string">'url_to_ldap_server'</span>,
    <span class="hljs-attr">adminDn</span>: <span class="hljs-string">'admin-dn'</span>,
    <span class="hljs-attr">adminPassword</span>: <span class="hljs-string">'password'</span>,
    <span class="hljs-attr">searchBase</span>: <span class="hljs-string">'dc=example,dc=com'</span>,
    <span class="hljs-attr">searchFitler</span>: <span class="hljs-string">'(uid={{username}})'</span>
}</pre><p>To test the LDAP configuration, you can use the Open LDAP server with the following configuration:</p>
<pre class="highlight javascript">APIKeyAuthType: <span class="hljs-string">'ldap'</span>,
<span class="hljs-attr">ldap</span>: {
    <span class="hljs-attr">url</span>: <span class="hljs-string">"ldap://ldap.forumsys.com:389"</span>,
    <span class="hljs-attr">adminDn</span>: <span class="hljs-string">"cn=read-only-admin,dc=example,dc=com"</span>,
    <span class="hljs-attr">adminPassword</span>: <span class="hljs-string">"password"</span>,
    <span class="hljs-attr">searchBase</span>: <span class="hljs-string">"dc=example,dc=com"</span>,
    <span class="hljs-attr">searchFilter</span>: <span class="hljs-string">"(uid={{username}})"</span>
},</pre><p>Then use the username <code>einstein</code> and the password <code>password</code> when using the API.</p>
