diff --git a/common/models/access-token.js b/common/models/access-token.js
index ae75051f..707ba4ce 100644
--- a/common/models/access-token.js
+++ b/common/models/access-token.js
@@ -149,11 +149,19 @@ module.exports = function(AccessToken) {
       assert(this.ttl, 'token.ttl must exist');
       assert(this.ttl >= -1, 'token.ttl must be >= -1');
 
+      var AccessToken = this.constructor;
+      var userRelation = AccessToken.relations.user; // may not be set up
+      var User = userRelation && userRelation.modelTo;
+
       var now = Date.now();
       var created = this.created.getTime();
       var elapsedSeconds = (now - created) / 1000;
       var secondsToLive = this.ttl;
-      var isValid = elapsedSeconds < secondsToLive;
+      var eternalTokensAllowed = !!(User && User.settings.allowEternalTokens);
+      var isEternalToken = secondsToLive === -1;
+      var isValid = isEternalToken ?
+        eternalTokensAllowed :
+        elapsedSeconds < secondsToLive;
 
       if (isValid) {
         cb(null, isValid);
diff --git a/test/access-token.test.js b/test/access-token.test.js
index 917994da..e86feca9 100644
--- a/test/access-token.test.js
+++ b/test/access-token.test.js
@@ -355,11 +355,38 @@ describe('AccessToken', function() {
     assert(Object.prototype.toString.call(this.token.created), '[object Date]');
   });
 
-  it('should be validateable', function(done) {
-    this.token.validate(function(err, isValid) {
-      assert(isValid);
+  describe('.validate()', function() {
+    it('accepts valid tokens', function(done) {
+      this.token.validate(function(err, isValid) {
+        assert(isValid);
+        done();
+      });
+    });
 
-      done();
+    it('rejects eternal TTL by default', function(done) {
+      this.token.ttl = -1;
+      this.token.validate(function(err, isValid) {
+        if (err) return done(err);
+        expect(isValid, 'isValid').to.equal(false);
+        done();
+      });
+    });
+
+    it('allows eternal tokens when enabled by User.allowEternalTokens',
+    function(done) {
+      var Token = givenLocalTokenModel();
+
+      // Overwrite User settings - enable eternal tokens
+      Token.app.models.User.settings.allowEternalTokens = true;
+
+      Token.create({ userId: '123', ttl: -1 }, function(err, token) {
+        if (err) return done(err);
+        token.validate(function(err, isValid) {
+          if (err) return done(err);
+          expect(isValid, 'isValid').to.equal(true);
+          done();
+        });
+      });
     });
   });
 
@@ -622,3 +649,16 @@ function createTestApp(testToken, settings, done) {
 
   return app;
 }
+
+function givenLocalTokenModel() {
+  var app = loopback({ localRegistry: true, loadBuiltinModels: true });
+  app.dataSource('db', { connector: 'memory' });
+
+  var User = app.registry.getModel('User');
+  app.model(User, { dataSource: 'db' });
+
+  var Token = app.registry.getModel('AccessToken');
+  app.model(Token, { dataSource: 'db' });
+
+  return Token;
+}