Check for expired oauth tokens (#264)

diff --git a/scripts/lua/oauth/app-id.lua b/scripts/lua/oauth/app-id.lua
index e0d15ef..7b5af21 100644
--- a/scripts/lua/oauth/app-id.lua
+++ b/scripts/lua/oauth/app-id.lua
@@ -55,10 +55,17 @@
     request.err(401, 'AppId key signature verification failed.')
     return nil
   end
-  jwt_obj = cjson.decode(cjose.getJWSInfo(token))
+  local jwt_obj = cjson.decode(cjose.getJWSInfo(token))
+  local expireTime = jwt_obj['exp']
+  if expireTime < os.time() then
+    request.err(401, 'Access token expired.')
+    return nil
+  end
   ngx.header['X-OIDC-Email'] = jwt_obj['email']
   ngx.header['X-OIDC-Sub'] = jwt_obj['sub']
-  dataStore:saveOAuthToken('appId', token, cjson.encode(jwt_obj), jwt_obj['exp'])
+  -- keep token in cache until it expires
+  local ttl = expireTime - os.time()
+  dataStore:saveOAuthToken('appId', token, cjson.encode(jwt_obj), ttl)
   return jwt_obj
 end
 
diff --git a/scripts/lua/oauth/facebook.lua b/scripts/lua/oauth/facebook.lua
index 2de6f09..f23ddf9 100644
--- a/scripts/lua/oauth/facebook.lua
+++ b/scripts/lua/oauth/facebook.lua
@@ -30,11 +30,7 @@
     return nil
   end
 
-  local result = dataStore:getOAuthToken('facebook', token)
-  if result ~= ngx.null then
-    return cjson.decode(result)
-  end
-  result = dataStore:getOAuthToken('facebook', utils.concatStrings({token, facebookAppToken}))
+  local result = dataStore:getOAuthToken('facebook', utils.concatStrings({token, facebookAppToken}))
   if result ~= ngx.null then
     return cjson.decode(result)
   end
@@ -64,13 +60,16 @@
     return
   end
   local json_resp = cjson.decode(res.body)
+  if json_resp['error'] ~= nil then
+    return nil
+  end
 
   if (json_resp['error']) then
     return nil
   end
-  -- convert Facebook's response
-  -- Read more about the fields at: https://developers.google.com/identity/protocols/OpenIDConnect#obtainuserinfo
-  dataStore:saveOAuthToken('facebook', utils.concatStrings({token, facebookAppToken}), cjson.encode(json_resp), json_resp['expires_at'])
+  -- keep token in cache until it expires
+  local ttl = json_resp.data['expires_at'] - os.time()
+  dataStore:saveOAuthToken('facebook', utils.concatStrings({token, facebookAppToken}), cjson.encode(json_resp), ttl)
   return json_resp
 end
 
diff --git a/scripts/lua/oauth/github.lua b/scripts/lua/oauth/github.lua
index aa7035e..f4f2e9b 100644
--- a/scripts/lua/oauth/github.lua
+++ b/scripts/lua/oauth/github.lua
@@ -58,7 +58,9 @@
     return nil
   end
 
-  dataStore:saveOAuthToken('github', token, cjson.encode(json_resp))
+  -- Github tokens do not expire; keep token in cache and clean up after 7 days
+  local ttl = 604800
+  dataStore:saveOAuthToken('github', token, cjson.encode(json_resp), ttl)
   -- convert Github's response
   -- Read more about the fields at: https://developers.google.com/identity/protocols/OpenIDConnect#obtainuserinfo
   return json_resp
diff --git a/scripts/lua/oauth/google.lua b/scripts/lua/oauth/google.lua
index 78f48dd..b6892b3 100644
--- a/scripts/lua/oauth/google.lua
+++ b/scripts/lua/oauth/google.lua
@@ -58,7 +58,9 @@
     return nil
   end
 
-  dataStore:saveOAuthToken('google', token, cjson.encode(json_resp), json_resp['expires'])
+  -- keep token in cache until it expires
+  local ttl = json_resp['expires_in']
+  dataStore:saveOAuthToken('google', token, cjson.encode(json_resp), ttl)
   -- convert Google's response
   -- Read more about the fields at: https://developers.google.com/identity/protocols/OpenIDConnect#obtainuserinfo
   ngx.header['X-OIDC-Sub'] = json_resp['sub']
diff --git a/tests/scripts/lua/security.lua b/tests/scripts/lua/security.lua
index 2b8cf52..89533fd 100644
--- a/tests/scripts/lua/security.lua
+++ b/tests/scripts/lua/security.lua
@@ -237,33 +237,6 @@
     assert.same(red:exists('oauth:providers:mock:tokens:bad'), 0)
     assert.falsy(result)
   end)
-  it('Loads a facebook token from the cache without a valid app id', function()
-    local red = fakeredis.new()
-    local ds = require "lib/dataStore"
-    local dataStore = ds.initWithDriver(red)
-    local token = "test"
-    local ngxattrs = [[
-      {
-        "http_Authorization":"]] .. token .. [[",
-        "http_x_facebook_app_token":"nothing",
-        "tenant":"1234",
-        "gatewayPath":"v1/test"
-      }
-    ]]
-    local ngx = fakengx.new()
-    ngx.var = cjson.decode(ngxattrs)
-    _G.ngx = ngx
-    local securityObj = [[
-      {
-        "type":"oauth2",
-        "provider":"facebook",
-        "scope":"resource"
-      }
-    ]]
-    red:set('oauth:providers:facebook:tokens:test', '{ "token":"good"}')
-    local result = oauth.process(dataStore, cjson.decode(securityObj))
-    assert.truthy(result)
-  end)
   it('Loads a facebook token from the cache with a valid app id', function()
     local red = fakeredis.new()
     local ds = require "lib/dataStore"
diff --git a/tools/travis/build.sh b/tools/travis/build.sh
index 8b5dbaf..a9654bf 100755
--- a/tools/travis/build.sh
+++ b/tools/travis/build.sh
@@ -57,4 +57,4 @@
 sleep 60
 TERM=dumb ./gradlew tests:test --tests whisk.core.apigw.* ${WSK_TESTS_DEPS_EXCLUDE}
 sleep 60
-TERM=dumb ./gradlew tests:test --tests whisk.core.cli.test.ApiGwTests ${WSK_TESTS_DEPS_EXCLUDE}
+TERM=dumb ./gradlew tests:test --tests whisk.core.cli.test.ApiGwRestTests ${WSK_TESTS_DEPS_EXCLUDE}