auth.test.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. const config = require('config')
  2. const fetch = require('node-fetch')
  3. const sinon = require('sinon')
  4. const { expect } = require('chai')
  5. const cleanup = require('../storage/support/cleanup')
  6. const expectResponse = require('./support/expect_response')
  7. const fixtures = require('../storage/support/fixtures')
  8. const HTTPStatus = require('http-status')
  9. const testServer = require('./support/test_server')
  10. describe('auth', function () {
  11. beforeEach(cleanup.everything)
  12. beforeEach(fixtures.create)
  13. beforeEach('Set up stubs', function () {
  14. sinon.stub(config, 'has').callThrough()
  15. sinon.stub(config, 'get').callThrough()
  16. })
  17. afterEach(sinon.restore)
  18. it('renders 401 on swagger docs endpoint without auth', async function () {
  19. const response = await fetch(testServer.url('/docs'))
  20. expect(response.status).to.equal(HTTPStatus.UNAUTHORIZED)
  21. expect(response.headers.get('www-authenticate')).to.match(/^Basic/)
  22. })
  23. it('renders swagger docs endpoint with auth', async function () {
  24. const response = await fetch(testServer.url('/docs'), {
  25. headers: {
  26. Authorization: testServer.basicAuthHeader,
  27. },
  28. })
  29. expect(response.ok).to.be.true
  30. })
  31. it('takes an old basic auth password during a password change', async function () {
  32. setMockConfig('basicHttpAuth.oldPassword', 'foo')
  33. // Primary should still work.
  34. const response1 = await fetch(testServer.url('/docs'), {
  35. headers: {
  36. Authorization: testServer.basicAuthHeader,
  37. },
  38. })
  39. expect(response1.ok).to.be.true
  40. // Old password should also work.
  41. const response2 = await fetch(testServer.url('/docs'), {
  42. headers: {
  43. Authorization: 'Basic ' + Buffer.from('staging:foo').toString('base64'),
  44. },
  45. })
  46. expect(response2.ok).to.be.true
  47. // Incorrect password should not work.
  48. const response3 = await fetch(testServer.url('/docs'), {
  49. header: {
  50. Authorization: 'Basic ' + Buffer.from('staging:bar').toString('base64'),
  51. },
  52. })
  53. expect(response3.status).to.equal(HTTPStatus.UNAUTHORIZED)
  54. })
  55. it('renders 401 on ProjectImport endpoints', async function () {
  56. const unauthenticatedClient = testServer.client
  57. try {
  58. await unauthenticatedClient.apis.ProjectImport.importSnapshot1({
  59. project_id: '1',
  60. snapshot: { files: {} },
  61. })
  62. expect.fail()
  63. } catch (err) {
  64. expectResponse.unauthorized(err)
  65. expect(err.response.headers['www-authenticate']).to.match(/^Basic/)
  66. }
  67. // check that the snapshot was not persisted even if the response was a 401
  68. const projectClient = await testServer.createClientForProject('1')
  69. try {
  70. await projectClient.apis.Project.getLatestHistory({ project_id: '1' })
  71. expect.fail()
  72. } catch (err) {
  73. expectResponse.notFound(err)
  74. }
  75. })
  76. it('renders 401 for JWT endpoints', function () {
  77. return testServer.client.apis.Project.getLatestHistory({
  78. project_id: '10000',
  79. })
  80. .then(() => {
  81. expect.fail()
  82. })
  83. .catch(err => {
  84. expectResponse.unauthorized(err)
  85. expect(err.response.headers['www-authenticate']).to.equal('Bearer')
  86. })
  87. })
  88. it('accepts basic auth in place of JWT (for now)', function () {
  89. const projectId = fixtures.docs.initializedProject.id
  90. return testServer.pseudoJwtBasicAuthClient.apis.Project.getLatestHistory({
  91. project_id: projectId,
  92. }).then(response => {
  93. expect(response.obj.chunk).to.exist
  94. })
  95. })
  96. it('uses JWT', function () {
  97. const projectId = fixtures.docs.initializedProject.id
  98. return testServer
  99. .createClientForProject(projectId)
  100. .then(client => {
  101. return client.apis.Project.getLatestHistory({
  102. project_id: projectId,
  103. })
  104. })
  105. .then(response => {
  106. expect(response.obj.chunk).to.exist
  107. })
  108. })
  109. it('checks for project id', function () {
  110. return testServer
  111. .createClientForProject('1')
  112. .then(client => {
  113. return client.apis.Project.getLatestHistory({
  114. project_id: '2',
  115. })
  116. })
  117. .then(() => {
  118. expect.fail()
  119. })
  120. .catch(expectResponse.forbidden)
  121. })
  122. it('does not accept jwt for ProjectUpdate endpoints', function () {
  123. return testServer.createClientForProject('1').then(client => {
  124. return client.apis.ProjectImport.importSnapshot1({
  125. project_id: '1',
  126. snapshot: {},
  127. })
  128. .then(() => {
  129. expect.fail()
  130. })
  131. .catch(expectResponse.unauthorized)
  132. })
  133. })
  134. describe('when an old JWT key is defined', function () {
  135. beforeEach(function () {
  136. setMockConfig('jwtAuth.oldKey', 'old-secret')
  137. })
  138. it('accepts the old key', async function () {
  139. const projectId = fixtures.docs.initializedProject.id
  140. const client = await testServer.createClientForProject(projectId, {
  141. jwtKey: 'old-secret',
  142. })
  143. const response = await client.apis.Project.getLatestHistory({
  144. project_id: projectId,
  145. })
  146. expect(response.obj.chunk).to.exist
  147. })
  148. it('accepts the new key', async function () {
  149. const projectId = fixtures.docs.initializedProject.id
  150. const client = await testServer.createClientForProject(projectId)
  151. const response = await client.apis.Project.getLatestHistory({
  152. project_id: projectId,
  153. })
  154. expect(response.obj.chunk).to.exist
  155. })
  156. it('rejects other keys', async function () {
  157. const projectId = fixtures.docs.initializedProject.id
  158. const client = await testServer.createClientForProject(projectId, {
  159. jwtKey: 'bad-secret',
  160. })
  161. try {
  162. await client.apis.Project.getLatestHistory({
  163. project_id: projectId,
  164. })
  165. expect.fail()
  166. } catch (err) {
  167. expectResponse.unauthorized(err)
  168. }
  169. })
  170. })
  171. })
  172. function setMockConfig(path, value) {
  173. config.has.withArgs(path).returns(true)
  174. config.get.withArgs(path).returns(value)
  175. }