Commit c3d21c44 authored by Vitali Tatarintev's avatar Vitali Tatarintev

Merge branch 'sh-openid-connect-discovery-cors' into 'master'

Enable CORS headers for OpenID Connect discovery endpoints

See merge request gitlab-org/gitlab!63276
parents 3ce04f18 fdfb3420
......@@ -312,11 +312,33 @@ module Gitlab
end
# Cross-origin requests must be enabled for the Authorization code with PKCE OAuth flow when used from a browser.
%w(/oauth/token /oauth/revoke).each do |oauth_path|
allow do
origins '*'
resource oauth_path,
headers: %w(Authorization),
credentials: false,
methods: %i(post)
end
end
# These are routes from doorkeeper-openid_connect:
# https://github.com/doorkeeper-gem/doorkeeper-openid_connect#routes
allow do
origins '*'
resource '/oauth/token',
resource '/oauth/userinfo',
headers: %w(Authorization),
credentials: false,
methods: [:post]
methods: %i(get head post)
end
%w(/oauth/discovery/keys /.well-known/openid-configuration /.well-known/webfinger).each do |openid_path|
allow do
origins '*'
resource openid_path,
credentials: false,
methods: %i(get head)
end
end
end
......
......@@ -44,6 +44,14 @@ Rails.application.routes.draw do
draw :oauth
use_doorkeeper_openid_connect
# Add OPTIONS method for CORS preflight requests
match '/oauth/userinfo' => 'doorkeeper/openid_connect/userinfo#show', via: :options
match '/oauth/discovery/keys' => 'doorkeeper/openid_connect/discovery#keys', via: :options
match '/.well-known/openid-configuration' => 'doorkeeper/openid_connect/discovery#provider', via: :options
match '/.well-known/webfinger' => 'doorkeeper/openid_connect/discovery#webfinger', via: :options
match '/oauth/token' => 'oauth/tokens#create', via: :options
match '/oauth/revoke' => 'oauth/tokens#revoke', via: :options
# Sign up
scope path: '/users/sign_up', module: :registrations, as: :users_sign_up do
......
......@@ -3,12 +3,71 @@
require 'spec_helper'
RSpec.describe Oauth::TokensController do
it 'allows cross-origin POST requests' do
post '/oauth/token', headers: { 'Origin' => 'http://notgitlab.com' }
let(:cors_request_headers) { { 'Origin' => 'http://notgitlab.com' } }
let(:other_headers) { {} }
let(:headers) { cors_request_headers.merge(other_headers)}
expect(response.headers['Access-Control-Allow-Origin']).to eq '*'
expect(response.headers['Access-Control-Allow-Methods']).to eq 'POST'
expect(response.headers['Access-Control-Allow-Headers']).to be_nil
expect(response.headers['Access-Control-Allow-Credentials']).to be_nil
shared_examples 'cross-origin POST request' do
it 'allows cross-origin requests' do
expect(response.headers['Access-Control-Allow-Origin']).to eq '*'
expect(response.headers['Access-Control-Allow-Methods']).to eq 'POST'
expect(response.headers['Access-Control-Allow-Headers']).to be_nil
expect(response.headers['Access-Control-Allow-Credentials']).to be_nil
end
end
shared_examples 'CORS preflight OPTIONS request' do
it 'returns 200' do
expect(response).to have_gitlab_http_status(:ok)
end
it 'allows cross-origin requests' do
expect(response.headers['Access-Control-Allow-Origin']).to eq '*'
expect(response.headers['Access-Control-Allow-Methods']).to eq 'POST'
expect(response.headers['Access-Control-Allow-Headers']).to eq 'Authorization'
expect(response.headers['Access-Control-Allow-Credentials']).to be_nil
end
end
describe 'POST /oauth/token' do
before do
post '/oauth/token', headers: headers
end
it_behaves_like 'cross-origin POST request'
end
describe 'OPTIONS /oauth/token' do
let(:other_headers) { { 'Access-Control-Request-Headers' => 'Authorization', 'Access-Control-Request-Method' => 'POST' } }
before do
options '/oauth/token', headers: headers
end
it_behaves_like 'CORS preflight OPTIONS request'
end
describe 'POST /oauth/revoke' do
let(:other_headers) { { 'Content-Type' => 'application/x-www-form-urlencoded' } }
before do
post '/oauth/revoke', headers: headers, params: { token: '12345' }
end
it 'returns 200' do
expect(response).to have_gitlab_http_status(:ok)
end
it_behaves_like 'cross-origin POST request'
end
describe 'OPTIONS /oauth/revoke' do
let(:other_headers) { { 'Access-Control-Request-Headers' => 'Authorization', 'Access-Control-Request-Method' => 'POST' } }
before do
options '/oauth/revoke', headers: headers
end
it_behaves_like 'CORS preflight OPTIONS request'
end
end
......@@ -41,6 +41,8 @@ RSpec.describe 'OpenID Connect requests' do
}
end
let(:cors_request_headers) { { 'Origin' => 'http://notgitlab.com' } }
def request_access_token!
login_as user
......@@ -81,6 +83,24 @@ RSpec.describe 'OpenID Connect requests' do
end
end
shared_examples 'cross-origin GET request' do
it 'allows cross-origin request' do
expect(response.headers['Access-Control-Allow-Origin']).to eq '*'
expect(response.headers['Access-Control-Allow-Methods']).to eq 'GET, HEAD'
expect(response.headers['Access-Control-Allow-Headers']).to be_nil
expect(response.headers['Access-Control-Allow-Credentials']).to be_nil
end
end
shared_examples 'cross-origin GET and POST request' do
it 'allows cross-origin request' do
expect(response.headers['Access-Control-Allow-Origin']).to eq '*'
expect(response.headers['Access-Control-Allow-Methods']).to eq 'GET, HEAD, POST'
expect(response.headers['Access-Control-Allow-Headers']).to be_nil
expect(response.headers['Access-Control-Allow-Credentials']).to be_nil
end
end
context 'Application with OpenID scope' do
let(:application) { create :oauth_application, scopes: 'openid' }
......@@ -180,6 +200,51 @@ RSpec.describe 'OpenID Connect requests' do
expect(response).to redirect_to('/users/sign_in')
end
end
context 'OpenID Discovery keys' do
context 'with a cross-origin request' do
before do
get '/oauth/discovery/keys', headers: cors_request_headers
end
it 'returns data' do
expect(response).to have_gitlab_http_status(:ok)
end
it_behaves_like 'cross-origin GET request'
end
context 'with a cross-origin preflight OPTIONS request' do
before do
options '/oauth/discovery/keys', headers: cors_request_headers
end
it_behaves_like 'cross-origin GET request'
end
end
context 'OpenID WebFinger endpoint' do
context 'with a cross-origin request' do
before do
get '/.well-known/webfinger', headers: cors_request_headers, params: { resource: 'user@example.com' }
end
it 'returns data' do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['subject']).to eq('user@example.com')
end
it_behaves_like 'cross-origin GET request'
end
end
context 'with a cross-origin preflight OPTIONS request' do
before do
options '/.well-known/webfinger', headers: cors_request_headers, params: { resource: 'user@example.com' }
end
it_behaves_like 'cross-origin GET request'
end
end
context 'OpenID configuration information' do
......@@ -191,6 +256,27 @@ RSpec.describe 'OpenID Connect requests' do
expect(json_response['jwks_uri']).to eq('http://www.example.com/oauth/discovery/keys')
expect(json_response['scopes_supported']).to eq(%w[api read_user read_api read_repository write_repository sudo openid profile email])
end
context 'with a cross-origin request' do
before do
get '/.well-known/openid-configuration', headers: cors_request_headers
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['issuer']).to eq('http://localhost')
expect(json_response['jwks_uri']).to eq('http://www.example.com/oauth/discovery/keys')
expect(json_response['scopes_supported']).to eq(%w[api read_user read_api read_repository write_repository sudo openid profile email])
end
it_behaves_like 'cross-origin GET request'
end
context 'with a cross-origin preflight OPTIONS request' do
before do
options '/.well-known/openid-configuration', headers: cors_request_headers
end
it_behaves_like 'cross-origin GET request'
end
end
context 'Application with OpenID and email scopes' do
......@@ -218,6 +304,30 @@ RSpec.describe 'OpenID Connect requests' do
it 'has true in email_verified claim' do
expect(json_response['email_verified']).to eq(true)
end
context 'with a cross-origin request' do
before do
get '/oauth/userinfo', headers: cors_request_headers
end
it_behaves_like 'cross-origin GET and POST request'
end
context 'with a cross-origin POST request' do
before do
post '/oauth/userinfo', headers: cors_request_headers
end
it_behaves_like 'cross-origin GET and POST request'
end
context 'with a cross-origin preflight OPTIONS request' do
before do
options '/oauth/userinfo', headers: cors_request_headers
end
it_behaves_like 'cross-origin GET and POST request'
end
end
context 'ID token payload' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment