Merge pull request #9706 from opf/fix/cors-header-oauth

If CORS is enabled, also output headers for OAauth endpoints
pull/9688/head
ulferts 3 years ago committed by GitHub
commit 77be71ad02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      config/initializers/rack-cors.rb
  2. 8
      docs/system-admin-guide/system-settings/api-settings/README.md
  3. 56
      spec/requests/api/v3/cors_header_spec.rb

@ -35,5 +35,11 @@ Rails.application.config.middleware.insert_after Rails::Rack::Logger, Rack::Cors
methods: :any,
credentials: true,
if: proc { ::API::V3::CORS.enabled? }
resource '/oauth/*',
headers: :any,
methods: :any,
credentials: true,
if: proc { ::API::V3::CORS.enabled? }
end
end

@ -1,6 +1,6 @@
---
sidebar_navigation:
title: API settings
title: API settings
description: Settings for API functionality of OpenProject
robots: index, follow
keywords: API settings
@ -8,12 +8,12 @@ keywords: API settings
# API system settings
In the API settings, you can selectively control whether foreign applications may access your OpenProject
API endpoints from within the browser.
API endpoints from within the browser.
## Cross-Origin Resource Sharing (CORS)
To enable CORS headers being returned by the [OpenProject APIv3](https://docs.openproject.org/api/),
enable the check box on this page.
To enable CORS headers being returned by the [OpenProject APIv3](../../../api/),
enable the check box on this page. This will also enable it for dependent authentication endpoints, such as OAuth endpoints `/oauth/token` and the like.
You will then have to enter the allowed values for the Origin header that OpenProject will allow access to.
This is necessary, since authenticated resources of OpenProject cannot be accessible to all origins with the `*` header value.

@ -36,35 +36,43 @@ describe 'API v3 CORS headers',
include Capybara::RSpecMatchers
include API::V3::Utilities::PathHelper
shared_examples 'outputs CORS headers' do |request_path|
it 'outputs CORS headers', :aggregate_failures do
options request_path,
nil,
'HTTP_ORIGIN' => 'https://foo.example.com',
'HTTP_ACCESS_CONTROL_REQUEST_METHOD' => 'GET',
'HTTP_ACCESS_CONTROL_REQUEST_HEADERS' => 'test'
expect(last_response.headers['Access-Control-Allow-Origin']).to eq('https://foo.example.com')
expect(last_response.headers['Access-Control-Allow-Methods']).to eq('GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS')
expect(last_response.headers['Access-Control-Allow-Headers']).to eq('test')
expect(last_response.headers).to have_key('Access-Control-Max-Age')
end
it 'rejects CORS headers for invalid origin' do
options request_path,
nil,
'HTTP_ORIGIN' => 'invalid.example.com',
'HTTP_ACCESS_CONTROL_REQUEST_METHOD' => 'GET',
'HTTP_ACCESS_CONTROL_REQUEST_HEADERS' => 'test'
expect(last_response.headers).not_to have_key 'Access-Control-Allow-Origin'
expect(last_response.headers).not_to have_key 'Access-Control-Allow-Methods'
expect(last_response.headers).not_to have_key 'Access-Control-Allow-Headers'
expect(last_response.headers).not_to have_key 'Access-Control-Max-Age'
end
end
context 'with setting enabled',
with_settings: { apiv3_cors_enabled: true } do
context 'with allowed origin set to specific values',
with_settings: { apiv3_cors_origins: %w[https://foo.example.com bla.test] } do
it 'outputs CORS headers', :aggregate_failures do
options '/api/v3',
nil,
'HTTP_ORIGIN' => 'https://foo.example.com',
'HTTP_ACCESS_CONTROL_REQUEST_METHOD' => 'GET',
'HTTP_ACCESS_CONTROL_REQUEST_HEADERS' => 'test'
expect(last_response.headers['Access-Control-Allow-Origin']).to eq('https://foo.example.com')
expect(last_response.headers['Access-Control-Allow-Methods']).to eq('GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS')
expect(last_response.headers['Access-Control-Allow-Headers']).to eq('test')
expect(last_response.headers).to have_key('Access-Control-Max-Age')
end
it 'rejects CORS headers for invalid origin' do
options '/api/v3',
nil,
'HTTP_ORIGIN' => 'invalid.example.com',
'HTTP_ACCESS_CONTROL_REQUEST_METHOD' => 'GET',
'HTTP_ACCESS_CONTROL_REQUEST_HEADERS' => 'test'
expect(last_response.headers).not_to have_key 'Access-Control-Allow-Origin'
expect(last_response.headers).not_to have_key 'Access-Control-Allow-Methods'
expect(last_response.headers).not_to have_key 'Access-Control-Allow-Headers'
expect(last_response.headers).not_to have_key 'Access-Control-Max-Age'
end
it_behaves_like 'outputs CORS headers', '/api/v3'
it_behaves_like 'outputs CORS headers', '/oauth/token'
it_behaves_like 'outputs CORS headers', '/oauth/authorize'
it_behaves_like 'outputs CORS headers', '/oauth/revoke'
# CORS needs to output headers even if you're unauthorized to allow authentication
# to happen

Loading…
Cancel
Save