Completed UsergridClient.authenticateApp()
diff --git a/config.json b/config.json
index 898e61b..a4466ef 100644
--- a/config.json
+++ b/config.json
@@ -1,13 +1,11 @@
 {
-    "config": {
-        "usergrid": {
-            "appId": "sandbox",
-            "authFallback": "none",
-            "baseUrl": "https://api.usergrid.com",
-            "clientId": "YXA6GXSAACS2EeOYd20aP4G6Lw",
-            "clientSecret": "YXA66BeEvgNpJBwc4PAbvZZGTVS_SSw",
-            "orgId": "brandon.apigee",
-            "tokenTtl": 3600
-        }
+    "usergrid": {
+        "appId": "sandbox",
+        "authFallback": "none",
+        "baseUrl": "https://api.usergrid.com",
+        "clientId": "YXA6GXSAACS2EeOYd20aP4G6Lw",
+        "clientSecret": "YXA66BeEvgNpJBwc4PAbvZZGTVS_SSw",
+        "orgId": "brandon.apigee",
+        "tokenTtl": 3600
     }
 }
\ No newline at end of file
diff --git a/helpers/buildUrl.js b/helpers/buildUrl.js
new file mode 100644
index 0000000..1ad4ade
--- /dev/null
+++ b/helpers/buildUrl.js
@@ -0,0 +1,16 @@
+'use strict'
+
+var urljoin = require('url-join'),
+    ok = require('objectkit'),
+    config = require('../config.json')
+
+function buildUrl(opts) {
+    return urljoin(
+        ok(config).getIfExists('usergrid.baseUrl'),
+        opts.client.orgId,
+        opts.client.appId,
+        opts.type, (typeof opts.uuidOrName === 'string') ? opts.uuidOrName : ""
+    )
+}
+
+module.exports = buildUrl
\ No newline at end of file
diff --git a/helpers/index.js b/helpers/index.js
index 491ad4d..da72609 100644
--- a/helpers/index.js
+++ b/helpers/index.js
@@ -1,8 +1,12 @@
-var mutability = require('./mutability')
-var cb = require('./callbackCheck')
+var mutability = require('./mutability'),
+    cb = require('./callbackCheck'),
+    buildUrl = require('./buildUrl'),
+    userAgent = require('./userAgent')
 
 module.exports = {
     setImmutable: mutability.setImmutable,
     setMutable: mutability.setMutable,
-    cb: cb
+    cb: cb,
+    buildUrl: buildUrl,
+    userAgent: userAgent
 }
\ No newline at end of file
diff --git a/helpers/mutability.js b/helpers/mutability.js
index d70cb51..46c7c27 100644
--- a/helpers/mutability.js
+++ b/helpers/mutability.js
@@ -1,9 +1,9 @@
 function setImmutable(obj, key) {
-    return Object.defineProperty(obj, key, { configurable: false, writable: false });
+    return Object.defineProperty(obj, key, { configurable: false, writable: false })
 }
 
 function setMutable(obj, key) {
-    return Object.defineProperty(obj, key, { configurable: true, writable: true });
+    return Object.defineProperty(obj, key, { configurable: true, writable: true })
 }
 
 module.exports = {
diff --git a/helpers/userAgent.js b/helpers/userAgent.js
new file mode 100644
index 0000000..c5c6ee3
--- /dev/null
+++ b/helpers/userAgent.js
@@ -0,0 +1,8 @@
+'use strict'
+
+var util = require('util'),
+    version = require('../package.json').version
+
+module.exports = {
+    'User-Agent': util.format("usergrid-nodejs/v%s", version)
+}
\ No newline at end of file
diff --git a/lib/auth.js b/lib/auth.js
index 0447912..e223b37 100644
--- a/lib/auth.js
+++ b/lib/auth.js
@@ -5,14 +5,26 @@
 
 var UsergridAuth = function() {
     var self = this
-    self.accessToken = undefined
+    self.token = undefined
     self.expiry = 0
-    self.hasToken = false
-    self.tokenIsValid = false
+    helpers.setImmutable(self, 'hasToken')
+    helpers.setImmutable(self, 'isTokenValid')
     helpers.setImmutable(self, 'isExpired')
     return self
 }
 
+Object.defineProperty(UsergridAuth.prototype, "hasToken", {
+    get: function() {
+        return (typeof this.token === 'string' && this.token.length > 0) ? true : false
+    }
+})
+
+Object.defineProperty(UsergridAuth.prototype, "isTokenValid", {
+    get: function() {
+        return (new Date() >= this.expiry && this.hasToken) ? true : false
+    }
+})
+
 Object.defineProperty(UsergridAuth.prototype, "isExpired", {
     get: function() {
         return (new Date() >= this.expiry) ? true : false
diff --git a/lib/client.js b/lib/client.js
index 08e3bb6..47d7b13 100644
--- a/lib/client.js
+++ b/lib/client.js
@@ -1,8 +1,9 @@
 'use strict'
 
 var UsergridRequest = require('./request'),
+    request = require('request'),
     ok = require('objectkit'),
-    config = require('../config.json').config,
+    config = require('../config.json'),
     helpers = require('../helpers'),
     UsergridAuth = require('./auth'),
     UsergridAppAuth = require('./appAuth'),
@@ -102,10 +103,30 @@
 }
 
 UsergridClient.prototype.authenticateApp = function(opts, callback) {
-    callback = callback || opts
-    if (opts instanceof UsergridAuth) {
-        self.appAuth.accessToken = 'bob'
+    var self = this
+    callback = helpers.cb(callback || opts)
+    if (!(self.appAuth instanceof UsergridAppAuth)) {
+        throw new Error('App auth context was not defined when attempting to call .authenticateApp()')
     }
+    opts.type = 'token'
+    opts.client = self
+    request({
+        uri: helpers.buildUrl(opts),
+        headers: helpers.userAgent,
+        body: {
+            grant_type: "client_credentials",
+            client_id: opts.clientId || self.appAuth.clientId,
+            client_secret: opts.clientSecret || self.appAuth.clientSecret
+        },
+        method: 'POST',
+        json: true
+    }, function(error, response, body) {
+        var token = body.access_token || undefined
+        self.appAuth.token = token
+        var d = new Date()
+        self.appAuth.expiry = d.setSeconds(body.token_ttl || 0)
+        callback(error, response, token)
+    })
 }
 
 module.exports = UsergridClient
\ No newline at end of file
diff --git a/lib/request.js b/lib/request.js
index d3e71c7..620aab6 100644
--- a/lib/request.js
+++ b/lib/request.js
@@ -2,45 +2,25 @@
 
 var extend = require('extend'),
     request = require('request'),
-    config = require('../config.json').config,
+    config = require('../config.json'),
     version = require('../package.json').version,
     UsergridResponse = require('../lib/response'),
-    util = require('util'),
+    helpers = require('../helpers'),
     urljoin = require('url-join'),
     ok = require('objectkit')
 
 var UsergridRequest = function(opts, callback) {
-
+    callback = helpers.cb(callback)
     if (typeof opts.type !== 'string')
         throw new Error('\'type\' (or \'collection\') parameter is required when making a request')
-
-    // uuidOrName and body are optional and not always passed; setting callback to the last defined argument
-    var uri = urljoin(
-        ok(config).getIfExists('usergrid.baseUrl'),
-        opts.client.orgId,
-        opts.client.appId,
-        opts.type, (typeof opts.uuidOrName === 'string') ? opts.uuidOrName : ""
-    )
-
-    var params = request.initParams(uri, {
-        headers: {
-            'User-Agent': util.format("usergrid-nodejs/v%s", version),
-        },
+    request(helpers.buildUrl(opts), {
+        headers: helpers.userAgent,
         body: opts.body,
-        qs: (opts.client.clientId !== undefined && opts.client.clientSecret !== undefined) ? {
-            clientId: opts.client.clientId,
-            clientSecret: opts.client.clientSecret
-        } : undefined
-    }, callback)
-
-    params.method = opts.method
-
-    // default to using JSON, since we only ever do that with Usergrid
-    params.json = true
-
-    request(params, function(error, response) {
+        json: true,
+        method: opts.method
+    }, function(error, response) {
         response = new UsergridResponse(response)
-        params.callback(error, response)
+        callback(error, response)
     })
 }
 
diff --git a/tests/usergrid.js b/tests/usergrid.js
index f6ec968..3808435 100644
--- a/tests/usergrid.js
+++ b/tests/usergrid.js
@@ -2,7 +2,8 @@
 
 var should = require('should'),
     ok = require('objectkit'),
-    config = require('../config.json').config,
+    config = require('../config.json'),
+    helpers = require('../helpers'),
     Usergrid = require('../usergrid'),
     UsergridClient = require('../lib/client'),
     UsergridAuth = require('../lib/auth'),
@@ -70,6 +71,11 @@
             })
         })
 
+        it('should not fail when a callback function is not passed', function() {
+            // note: this test will NOT fail gracefully inside the Mocha event chain
+            _client.GET(_collection)
+        })
+
         it('should return a 200 ok', function() {
             response.statusCode.should.equal(200)
         })
@@ -96,7 +102,6 @@
         this.slow(1000)
         this.timeout(3000)
 
-
         var response
         before(function(done) {
             _client.POST(_collection, {
@@ -108,6 +113,11 @@
             })
         })
 
+        it('should not fail when a callback function is not passed', function() {
+            // note: this test will NOT fail gracefully inside the Mocha event chain
+            _client.POST(_collection, {})
+        })
+
         it('should return a 200 ok', function() {
             response.statusCode.should.equal(200)
         })
@@ -130,7 +140,6 @@
         this.slow(1000)
         this.timeout(3000)
 
-
         var response
         before(function(done) {
             _client.PUT(_collection, _uuid, {
@@ -141,6 +150,11 @@
             })
         })
 
+        it('should not fail when a callback function is not passed', function() {
+            // note: this test will NOT fail gracefully inside the Mocha event chain
+            _client.PUT(_collection, _uuid)
+        })
+
         it('should return a 200 ok', function() {
             response.statusCode.should.equal(200)
         })
@@ -173,6 +187,11 @@
             })
         })
 
+        it('should not fail when a callback function is not passed', function() {
+            // note: this test will NOT fail gracefully inside the Mocha event chain
+            _client.DELETE(_collection, _uuid)
+        })
+
         it('should return a 200 ok', function() {
             // This should check for 404, but because of a Usergrid bug, it returns 401 instead of 404.
             // see https://issues.apache.org/jira/browse/USERGRID-1128
@@ -218,6 +237,38 @@
 
         it('should be a subclass of UsergridAuth', function() {
             _client.appAuth.should.be.instanceof(UsergridAuth)
-        })        
+        })
+    })
+
+    describe('.authenticateApp()', function() {
+
+        this.slow(1000)
+        this.timeout(6000)
+
+        var response, token
+        before(function(done) {
+            _client.authenticateApp(function(err, r, t) {
+                response = r
+                token = t
+                done()
+            })
+        })
+
+        it('should return a 200 ok', function() {
+            response.statusCode.should.equal(200)
+        })
+
+        it('should have a valid token', function() {
+            token.should.be.a.String
+            token.length.should.be.greaterThan(10)
+        })
+
+        it('should have token set in .appAuth instance', function() {
+            _client.appAuth.should.have.property('token').equal(token)
+        })
+
+        it('should have expiry set in .appAuth instance greater than current time', function() {
+            _client.appAuth.should.have.property('expiry').greaterThan(new Date().getSeconds())
+        })
     })
 })
\ No newline at end of file