strategy.test.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. var chai = require('chai');
  2. var sinon = require('sinon');
  3. var Strategy = require('../lib/strategy');
  4. describe('Strategy', function() {
  5. it('should be named ethereum', function() {
  6. var strategy = new Strategy(function(){});
  7. expect(strategy.name).to.equal('ethereum');
  8. });
  9. it('should verify address', function(done) {
  10. chai.passport.use(new Strategy(function(address, cb) {
  11. expect(address).to.equal('0xCC6F4DF4B758C4DE3203e8842E2d8CAc564D7758');
  12. return cb(null, { id: '248289761001' });
  13. }))
  14. .request(function(req) {
  15. req.connection = {};
  16. req.headers.host = 'localhost:3000';
  17. req.body = {
  18. message: 'localhost:3000 wants you to sign in with your Ethereum account:\n' +
  19. '0xCC6F4DF4B758C4DE3203e8842E2d8CAc564D7758\n' +
  20. '\n' +
  21. 'Sign in with Ethereum to the app.\n' +
  22. '\n' +
  23. 'URI: http://localhost:3000\n' +
  24. 'Version: 1\n' +
  25. 'Chain ID: 1\n' +
  26. 'Nonce: VjglqeaSMDbPSYe0K\n' +
  27. 'Issued At: 2022-06-07T16:28:10.957Z',
  28. signature: '0xb303d03782c532e2371e3d75a8b2b093c2dceb5faed5d07d6506be96be783245515db6ad55ad6d598ebdf1f7e1c5cb0d24e7147bbad47d3b9d8dfbcfab2ddcc71b'
  29. };
  30. req.session = {
  31. messages: [],
  32. 'ethereum:siwe': {
  33. nonce: 'VjglqeaSMDbPSYe0K'
  34. }
  35. };
  36. })
  37. .success(function(user, info) {
  38. expect(user).to.deep.equal({ id: '248289761001' });
  39. expect(info).to.be.undefined;
  40. expect(this.session).to.deep.equal({
  41. messages: []
  42. });
  43. done();
  44. })
  45. .error(done)
  46. .authenticate();
  47. }); // should verify address
  48. it('should fail when URI is invalid', function(done) {
  49. chai.passport.use(new Strategy(function(address, cb) {
  50. expect(address).to.equal('0xCC6F4DF4B758C4DE3203e8842E2d8CAc564D7758');
  51. return cb(null, { id: '248289761001' });
  52. }))
  53. .request(function(req) {
  54. req.connection = {};
  55. req.headers.host = 'localhost:3999';
  56. req.body = {
  57. message: 'localhost:3000 wants you to sign in with your Ethereum account:\n' +
  58. '0xCC6F4DF4B758C4DE3203e8842E2d8CAc564D7758\n' +
  59. '\n' +
  60. 'Sign in with Ethereum to the app.\n' +
  61. '\n' +
  62. 'URI: http://localhost:3000\n' +
  63. 'Version: 1\n' +
  64. 'Chain ID: 1\n' +
  65. 'Nonce: VjglqeaSMDbPSYe0K\n' +
  66. 'Issued At: 2022-06-07T16:28:10.957Z',
  67. signature: '0xb303d03782c532e2371e3d75a8b2b093c2dceb5faed5d07d6506be96be783245515db6ad55ad6d598ebdf1f7e1c5cb0d24e7147bbad47d3b9d8dfbcfab2ddcc71b'
  68. };
  69. req.session = {
  70. messages: [],
  71. 'ethereum:siwe': {
  72. nonce: 'VjglqeaSMDbPSYe0K'
  73. }
  74. };
  75. })
  76. .fail(function(challenge, status) {
  77. expect(challenge).to.deep.equal({ message: 'URI mismatch.' });
  78. expect(status).to.equal(403);
  79. done();
  80. })
  81. .error(done)
  82. .authenticate();
  83. }); // should fail when URI is invalid
  84. it('should fail when message is expired', function(done) {
  85. chai.passport.use(new Strategy(function(address, cb) {
  86. expect(address).to.equal('0xCC6F4DF4B758C4DE3203e8842E2d8CAc564D7758');
  87. return cb(null, { id: '248289761001' });
  88. }))
  89. .request(function(req) {
  90. req.connection = {};
  91. req.headers.host = 'localhost:3000';
  92. req.body = {
  93. message: 'localhost:3000 wants you to sign in with your Ethereum account:\n' +
  94. '0xCC6F4DF4B758C4DE3203e8842E2d8CAc564D7758\n' +
  95. '\n' +
  96. 'Sign in with Ethereum to the app.\n' +
  97. '\n' +
  98. 'URI: http://localhost:3000\n' +
  99. 'Version: 1\n' +
  100. 'Chain ID: 1\n' +
  101. 'Nonce: GFRz6rD1XKFyYyQT\n' +
  102. 'Issued At: 2022-06-07T22:19:22.065Z\n' +
  103. 'Expiration Time: 2022-06-07T22:20:22.065Z',
  104. signature: '0xc5050e9144943695d2ab233e3d5f205687e29735b07f4e99ef6738ff5512f249582c2b8c105c5c8b9cd9c7910e971765532a55071e0dfd2bbd13e931a024e4991c'
  105. };
  106. req.session = {
  107. messages: [],
  108. 'ethereum:siwe': {
  109. nonce: 'GFRz6rD1XKFyYyQT'
  110. }
  111. };
  112. })
  113. .fail(function(challenge, status) {
  114. expect(challenge).to.deep.equal({ message: 'Expired message.' });
  115. expect(status).to.equal(403);
  116. done();
  117. })
  118. .error(done)
  119. .authenticate();
  120. }); // should fail when message is expired
  121. it('should fail when address is missing from message', function(done) {
  122. chai.passport.use(new Strategy(function(address, cb) {
  123. expect(address).to.equal('0xCC6F4DF4B758C4DE3203e8842E2d8CAc564D7758');
  124. return cb(null, { id: '248289761001' });
  125. }))
  126. .request(function(req) {
  127. req.connection = {};
  128. req.headers.host = 'localhost:3000';
  129. req.body = {
  130. message: 'localhost:3000 wants you to sign in with your Ethereum account:\n' +
  131. '\n' +
  132. 'Sign in with Ethereum to the app.\n' +
  133. '\n' +
  134. 'URI: http://localhost:3000\n' +
  135. 'Version: 1\n' +
  136. 'Chain ID: 1\n' +
  137. 'Nonce: VjglqeaSMDbPSYe0K\n' +
  138. 'Issued At: 2022-06-07T16:28:10.957Z',
  139. signature: '0xb303d03782c532e2371e3d75a8b2b093c2dceb5faed5d07d6506be96be783245515db6ad55ad6d598ebdf1f7e1c5cb0d24e7147bbad47d3b9d8dfbcfab2ddcc71b'
  140. };
  141. req.session = {
  142. messages: [],
  143. 'ethereum:siwe': {
  144. nonce: 'VjglqeaSMDbPSYe0K'
  145. }
  146. };
  147. })
  148. .fail(function(challenge, status) {
  149. expect(challenge).to.deep.equal({ message: 'Invalid message.' });
  150. expect(status).to.equal(403);
  151. done();
  152. })
  153. .error(done)
  154. .authenticate();
  155. }); // should fail when address is missing from message
  156. it('should fail when missing message', function(done) {
  157. chai.passport.use(new Strategy(function(address, cb) {
  158. throw new Error('verify function should not be called');
  159. }))
  160. .request(function(req) {
  161. req.connection = {};
  162. req.headers.host = 'localhost:3000';
  163. req.body = {
  164. signature: '0xb303d03782c532e2371e3d75a8b2b093c2dceb5faed5d07d6506be96be783245515db6ad55ad6d598ebdf1f7e1c5cb0d24e7147bbad47d3b9d8dfbcfab2ddcc71b'
  165. };
  166. req.session = {
  167. messages: []
  168. };
  169. })
  170. .fail(function(challenge, status) {
  171. expect(challenge).to.deep.equal({ message: 'Missing message.' });
  172. expect(status).to.equal(400);
  173. done();
  174. })
  175. .error(done)
  176. .authenticate();
  177. });
  178. it('should fail when missing signature', function(done) {
  179. chai.passport.use(new Strategy(function(address, cb) {
  180. throw new Error('verify function should not be called');
  181. }))
  182. .request(function(req) {
  183. req.connection = {};
  184. req.headers.host = 'localhost:3000';
  185. req.body = {
  186. message: 'localhost:3000 wants you to sign in with your Ethereum account:\n' +
  187. '0xCC6F4DF4B758C4DE3203e8842E2d8CAc564D7758\n' +
  188. '\n' +
  189. 'Sign in with Ethereum to the app.\n' +
  190. '\n' +
  191. 'URI: http://localhost:3000\n' +
  192. 'Version: 1\n' +
  193. 'Chain ID: 1\n' +
  194. 'Nonce: VjglqeaSMDbPSYe0K\n' +
  195. 'Issued At: 2022-06-07T16:28:10.957Z'
  196. };
  197. req.session = {
  198. messages: []
  199. };
  200. })
  201. .fail(function(challenge, status) {
  202. expect(challenge).to.deep.equal({ message: 'Missing signature.' });
  203. expect(status).to.equal(400);
  204. done();
  205. })
  206. .error(done)
  207. .authenticate();
  208. });
  209. });