auth.test.js 5.1 KB

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