diff --git a/.travis.yml b/.travis.yml
index 7f2f9aa..498d61d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,9 @@
 language: node_js
 sudo: false
 node_js:
+  - "11"
+  - "10"
+  - "9"
   - "8"
   - "7"
   - "6"
diff --git a/README.md b/README.md
index 6e653d3..5b47aff 100644
--- a/README.md
+++ b/README.md
@@ -339,9 +339,12 @@ alg Parameter Value | Digital Signature or MAC Algorithm
 HS256 | HMAC using SHA-256 hash algorithm
 HS384 | HMAC using SHA-384 hash algorithm
 HS512 | HMAC using SHA-512 hash algorithm
-RS256 | RSASSA using SHA-256 hash algorithm
-RS384 | RSASSA using SHA-384 hash algorithm
-RS512 | RSASSA using SHA-512 hash algorithm
+RS256 | RSASSA-PKCS1-v1_5 using SHA-256 hash algorithm
+RS384 | RSASSA-PKCS1-v1_5 using SHA-384 hash algorithm
+RS512 | RSASSA-PKCS1-v1_5 using SHA-512 hash algorithm
+PS256 | RSASSA-PSS using SHA-256 hash algorithm (only node ^6.12.0 || >=8.0.0)
+PS384 | RSASSA-PSS using SHA-384 hash algorithm (only node ^6.12.0 || >=8.0.0)
+PS512 | RSASSA-PSS using SHA-512 hash algorithm (only node ^6.12.0 || >=8.0.0)
 ES256 | ECDSA using P-256 curve and SHA-256 hash algorithm
 ES384 | ECDSA using P-384 curve and SHA-384 hash algorithm
 ES512 | ECDSA using P-521 curve and SHA-512 hash algorithm
diff --git a/lib/psSupported.js b/lib/psSupported.js
new file mode 100644
index 0000000..8c04144
--- /dev/null
+++ b/lib/psSupported.js
@@ -0,0 +1,3 @@
+var semver = require('semver');
+
+module.exports = semver.satisfies(process.version, '^6.12.0 || >=8.0.0');
diff --git a/package.json b/package.json
index f019a61..e099b78 100644
--- a/package.json
+++ b/package.json
@@ -36,7 +36,7 @@
     "url": "https://github.com/auth0/node-jsonwebtoken/issues"
   },
   "dependencies": {
-    "jws": "^3.1.5",
+    "jws": "^3.2.1",
     "lodash.includes": "^4.3.0",
     "lodash.isboolean": "^3.0.3",
     "lodash.isinteger": "^4.0.4",
@@ -44,7 +44,8 @@
     "lodash.isplainobject": "^4.0.6",
     "lodash.isstring": "^4.0.1",
     "lodash.once": "^4.0.0",
-    "ms": "^2.1.1"
+    "ms": "^2.1.1",
+    "semver": "^5.6.0"
   },
   "devDependencies": {
     "atob": "^2.1.2",
diff --git a/sign.js b/sign.js
index de80b02..985a9a0 100644
--- a/sign.js
+++ b/sign.js
@@ -1,4 +1,5 @@
 var timespan = require('./lib/timespan');
+var PS_SUPPORTED = require('./lib/psSupported');
 var jws = require('jws');
 var includes = require('lodash.includes');
 var isBoolean = require('lodash.isboolean');
@@ -8,11 +9,16 @@ var isPlainObject = require('lodash.isplainobject');
 var isString = require('lodash.isstring');
 var once = require('lodash.once');
 
+var SUPPORTED_ALGS = ['RS256', 'RS384', 'RS512', 'ES256', 'ES384', 'ES512', 'HS256', 'HS384', 'HS512', 'none']
+if (PS_SUPPORTED) {
+  SUPPORTED_ALGS.splice(3, 0, 'PS256', 'PS384', 'PS512');
+}
+
 var sign_options_schema = {
   expiresIn: { isValid: function(value) { return isInteger(value) || (isString(value) && value); }, message: '"expiresIn" should be a number of seconds or string representing a timespan' },
   notBefore: { isValid: function(value) { return isInteger(value) || (isString(value) && value); }, message: '"notBefore" should be a number of seconds or string representing a timespan' },
   audience: { isValid: function(value) { return isString(value) || Array.isArray(value); }, message: '"audience" must be a string or array' },
-  algorithm: { isValid: includes.bind(null, ['RS256', 'RS384', 'RS512', 'ES256', 'ES384', 'ES512', 'HS256', 'HS384', 'HS512', 'none']), message: '"algorithm" must be a valid string enum value' },
+  algorithm: { isValid: includes.bind(null, SUPPORTED_ALGS), message: '"algorithm" must be a valid string enum value' },
   header: { isValid: isPlainObject, message: '"header" must be an object' },
   encoding: { isValid: isString, message: '"encoding" must be a string' },
   issuer: { isValid: isString, message: '"issuer" must be a string' },
diff --git a/test/async_sign.tests.js b/test/async_sign.tests.js
index b0948d3..6eb7dc7 100644
--- a/test/async_sign.tests.js
+++ b/test/async_sign.tests.js
@@ -1,6 +1,7 @@
 var jwt = require('../index');
 var expect = require('chai').expect;
 var jws = require('jws');
+var PS_SUPPORTED = require('../lib/psSupported');
 
 describe('signing a token asynchronously', function() {
 
@@ -58,6 +59,16 @@ describe('signing a token asynchronously', function() {
       });
     });
 
+    if (PS_SUPPORTED) {
+      it('should return error when secret is not a cert for PS256', function(done) {
+        //this throw an error because the secret is not a cert and PS256 requires a cert.
+        jwt.sign({ foo: 'bar' }, secret, { algorithm: 'PS256' }, function (err) {
+          expect(err).to.be.ok;
+          done();
+        });
+      });
+    }
+
     it('should return error on wrong arguments', function(done) {
       //this throw an error because the secret is not a cert and RS256 requires a cert.
       jwt.sign({ foo: 'bar' }, secret, { notBefore: {} }, function (err) {
diff --git a/test/jwt.asymmetric_signing.tests.js b/test/jwt.asymmetric_signing.tests.js
index 49b9ed0..c56eea3 100644
--- a/test/jwt.asymmetric_signing.tests.js
+++ b/test/jwt.asymmetric_signing.tests.js
@@ -1,4 +1,5 @@
 var jwt = require('../index');
+var PS_SUPPORTED = require('../lib/psSupported');
 var fs = require('fs');
 var path = require('path');
 
@@ -25,6 +26,15 @@ var algorithms = {
   }
 };
 
+if (PS_SUPPORTED) {
+  algorithms.PS256 = {
+    pub_key: loadKey('pub.pem'),
+    priv_key: loadKey('priv.pem'),
+    invalid_pub_key: loadKey('invalid_pub.pem')
+  };
+}
+
+
 describe('Asymmetric Algorithms', function(){
 
   Object.keys(algorithms).forEach(function (algorithm) {
diff --git a/test/rsa-public-key.tests.js b/test/rsa-public-key.tests.js
index e2044fc..6abafb8 100644
--- a/test/rsa-public-key.tests.js
+++ b/test/rsa-public-key.tests.js
@@ -1,8 +1,9 @@
 var jwt = require('../');
+var PS_SUPPORTED = require('../lib/psSupported');
 
 describe('public key start with BEGIN RSA PUBLIC KEY', function () {
 
-  it('should work', function (done) {
+  it('should work for RS family of algorithms', function (done) {
     var fs = require('fs');
     var cert_pub = fs.readFileSync(__dirname + '/rsa-public-key.pem');
     var cert_priv = fs.readFileSync(__dirname + '/rsa-private.pem');
@@ -12,4 +13,16 @@ describe('public key start with BEGIN RSA PUBLIC KEY', function () {
     jwt.verify(token, cert_pub, done);
   });
 
+  if (PS_SUPPORTED) {
+    it('should work for PS family of algorithms', function (done) {
+      var fs = require('fs');
+      var cert_pub = fs.readFileSync(__dirname + '/rsa-public-key.pem');
+      var cert_priv = fs.readFileSync(__dirname + '/rsa-private.pem');
+
+      var token = jwt.sign({ foo: 'bar' }, cert_priv, { algorithm: 'PS256'});
+
+      jwt.verify(token, cert_pub, done);
+    });
+  }
+
 });
diff --git a/test/schema.tests.js b/test/schema.tests.js
index 887b59f..742d29e 100644
--- a/test/schema.tests.js
+++ b/test/schema.tests.js
@@ -1,6 +1,7 @@
 var jwt = require('../index');
 var expect = require('chai').expect;
 var fs = require('fs');
+var PS_SUPPORTED = require('../lib/psSupported');
 
 describe('schema', function() {
 
@@ -21,6 +22,11 @@ describe('schema', function() {
       sign({algorithm: 'RS256'});
       sign({algorithm: 'RS384'});
       sign({algorithm: 'RS512'});
+      if (PS_SUPPORTED) {
+        sign({algorithm: 'PS256'});
+        sign({algorithm: 'PS384'});
+        sign({algorithm: 'PS512'});
+      }
       sign({algorithm: 'ES256'});
       sign({algorithm: 'ES384'});
       sign({algorithm: 'ES512'});
diff --git a/test/wrong_alg.tests.js b/test/wrong_alg.tests.js
index 04ce48e..8b6e245 100644
--- a/test/wrong_alg.tests.js
+++ b/test/wrong_alg.tests.js
@@ -2,6 +2,7 @@ var fs = require('fs');
 var path = require('path');
 var jwt = require('../index');
 var JsonWebTokenError = require('../lib/JsonWebTokenError');
+var PS_SUPPORTED = require('../lib/psSupported');
 var expect = require('chai').expect;
 
 
@@ -29,6 +30,16 @@ describe('when setting a wrong `header.alg`', function () {
     });
   });
 
+  if (PS_SUPPORTED) {
+    describe('signing with pub key as HS256 and whitelisting only PS256', function () {
+      it('should not verify', function () {
+        expect(function () {
+          jwt.verify(TOKEN, pub, {algorithms: ['PS256']});
+        }).to.throw(JsonWebTokenError, /invalid algorithm/);
+      });
+    });
+  }
+
   describe('signing with HS256 and checking with HS384', function () {
     it('should not verify', function () {
       expect(function () {
diff --git a/verify.js b/verify.js
index fa1339a..fb36aa1 100644
--- a/verify.js
+++ b/verify.js
@@ -3,8 +3,18 @@ var NotBeforeError    = require('./lib/NotBeforeError');
 var TokenExpiredError = require('./lib/TokenExpiredError');
 var decode            = require('./decode');
 var timespan          = require('./lib/timespan');
+var PS_SUPPORTED      = require('./lib/psSupported');
 var jws               = require('jws');
 
+var PUB_KEY_ALGS = ['RS256', 'RS384', 'RS512', 'ES256', 'ES384', 'ES512'];
+var RSA_KEY_ALGS = ['RS256', 'RS384', 'RS512'];
+var HS_ALGS = ['HS256', 'HS384', 'HS512'];
+
+if (PS_SUPPORTED) {
+  PUB_KEY_ALGS.splice(3, 0, 'PS256', 'PS384', 'PS512');
+  RSA_KEY_ALGS.splice(3, 0, 'PS256', 'PS384', 'PS512');
+}
+
 module.exports = function (jwtString, secretOrPublicKey, options, callback) {
   if ((typeof options === 'function') && !callback) {
     callback = options;
@@ -102,11 +112,8 @@ module.exports = function (jwtString, secretOrPublicKey, options, callback) {
 
     if (!options.algorithms) {
       options.algorithms = ~secretOrPublicKey.toString().indexOf('BEGIN CERTIFICATE') ||
-          ~secretOrPublicKey.toString().indexOf('BEGIN PUBLIC KEY') ?
-        ['RS256', 'RS384', 'RS512', 'ES256', 'ES384', 'ES512'] :
-        ~secretOrPublicKey.toString().indexOf('BEGIN RSA PUBLIC KEY') ?
-          ['RS256', 'RS384', 'RS512'] :
-          ['HS256', 'HS384', 'HS512'];
+        ~secretOrPublicKey.toString().indexOf('BEGIN PUBLIC KEY') ? PUB_KEY_ALGS :
+        ~secretOrPublicKey.toString().indexOf('BEGIN RSA PUBLIC KEY') ? RSA_KEY_ALGS : HS_ALGS;
 
     }