signature_verification_spec.rb 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. # frozen_string_literal: true
  2. require 'rails_helper'
  3. describe ApplicationController, type: :controller do
  4. controller do
  5. include SignatureVerification
  6. def success
  7. head 200
  8. end
  9. def alternative_success
  10. head 200
  11. end
  12. end
  13. before do
  14. routes.draw { match via: [:get, :post], 'success' => 'anonymous#success' }
  15. end
  16. context 'without signature header' do
  17. before do
  18. get :success
  19. end
  20. describe '#signed_request?' do
  21. it 'returns false' do
  22. expect(controller.signed_request?).to be false
  23. end
  24. end
  25. describe '#signed_request_account' do
  26. it 'returns nil' do
  27. expect(controller.signed_request_account).to be_nil
  28. end
  29. end
  30. end
  31. context 'with signature header' do
  32. let!(:author) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/actor') }
  33. context 'without body' do
  34. before do
  35. get :success
  36. fake_request = Request.new(:get, request.url)
  37. fake_request.on_behalf_of(author)
  38. request.headers.merge!(fake_request.headers)
  39. end
  40. describe '#signed_request?' do
  41. it 'returns true' do
  42. expect(controller.signed_request?).to be true
  43. end
  44. end
  45. describe '#signed_request_account' do
  46. it 'returns an account' do
  47. expect(controller.signed_request_account).to eq author
  48. end
  49. it 'returns nil when path does not match' do
  50. request.path = '/alternative-path'
  51. expect(controller.signed_request_account).to be_nil
  52. end
  53. it 'returns nil when method does not match' do
  54. post :success
  55. expect(controller.signed_request_account).to be_nil
  56. end
  57. end
  58. end
  59. context 'with request older than a day' do
  60. before do
  61. get :success
  62. fake_request = Request.new(:get, request.url)
  63. fake_request.add_headers({ 'Date' => 2.days.ago.utc.httpdate })
  64. fake_request.on_behalf_of(author)
  65. request.headers.merge!(fake_request.headers)
  66. end
  67. describe '#signed_request?' do
  68. it 'returns true' do
  69. expect(controller.signed_request?).to be true
  70. end
  71. end
  72. describe '#signed_request_account' do
  73. it 'returns nil' do
  74. expect(controller.signed_request_account).to be_nil
  75. end
  76. end
  77. end
  78. context 'with inaccessible key' do
  79. before do
  80. get :success
  81. author = Fabricate(:account, domain: 'localhost:5000', uri: 'http://localhost:5000/actor')
  82. fake_request = Request.new(:get, request.url)
  83. fake_request.on_behalf_of(author)
  84. author.destroy
  85. request.headers.merge!(fake_request.headers)
  86. stub_request(:get, 'http://localhost:5000/actor#main-key').to_raise(Mastodon::HostValidationError)
  87. end
  88. describe '#signed_request?' do
  89. it 'returns true' do
  90. expect(controller.signed_request?).to be true
  91. end
  92. end
  93. describe '#signed_request_account' do
  94. it 'returns nil' do
  95. expect(controller.signed_request_account).to be_nil
  96. end
  97. end
  98. end
  99. context 'with body' do
  100. before do
  101. post :success, body: 'Hello world'
  102. fake_request = Request.new(:post, request.url, body: 'Hello world')
  103. fake_request.on_behalf_of(author)
  104. request.headers.merge!(fake_request.headers)
  105. end
  106. describe '#signed_request?' do
  107. it 'returns true' do
  108. expect(controller.signed_request?).to be true
  109. end
  110. end
  111. describe '#signed_request_account' do
  112. it 'returns an account' do
  113. expect(controller.signed_request_account).to eq author
  114. end
  115. it 'returns nil when path does not match' do
  116. request.path = '/alternative-path'
  117. expect(controller.signed_request_account).to be_nil
  118. end
  119. it 'returns nil when method does not match' do
  120. get :success
  121. expect(controller.signed_request_account).to be_nil
  122. end
  123. it 'returns nil when body has been tampered' do
  124. post :success, body: 'doo doo doo'
  125. expect(controller.signed_request_account).to be_nil
  126. end
  127. end
  128. end
  129. end
  130. end