mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-09-24 08:56:17 +08:00
Merge pull request #4582 from okriuchykhin/ok_SCI_7284
Update Omniauth, Azure and Okta strategies [SCI-7284]
This commit is contained in:
commit
ed86368146
15
Gemfile
15
Gemfile
|
@ -7,7 +7,7 @@ ruby '2.7.6'
|
|||
gem 'bootsnap', require: false
|
||||
gem 'bootstrap-sass', '~> 3.4.1'
|
||||
gem 'bootstrap_form', '~> 2.7.0'
|
||||
gem 'devise', '~> 4.7.1'
|
||||
gem 'devise', '~> 4.8.1'
|
||||
gem 'devise_invitable'
|
||||
gem 'figaro'
|
||||
gem 'pg', '~> 1.1'
|
||||
|
@ -19,18 +19,15 @@ gem 'recaptcha', require: 'recaptcha/rails'
|
|||
gem 'sanitize', '~> 6.0'
|
||||
gem 'sassc-rails'
|
||||
gem 'webpacker', '~> 4.0.0'
|
||||
gem 'yomu', git: 'https://github.com/biosistemika/yomu', branch: 'master'
|
||||
gem 'yomu', git: 'https://github.com/biosistemika/yomu', branch: 'tika_1_28_1'
|
||||
|
||||
# Gems for OAuth2 subsystem
|
||||
gem 'doorkeeper', '>= 4.6'
|
||||
gem 'omniauth'
|
||||
gem 'omniauth-azure-activedirectory'
|
||||
gem 'omniauth', '~> 2.1'
|
||||
gem 'omniauth-azure-activedirectory-v2'
|
||||
gem 'omniauth-linkedin-oauth2'
|
||||
gem 'omniauth-okta'
|
||||
|
||||
# TODO: remove this when omniauth gem resolves CVE issues
|
||||
# Prevents CVE-2015-9284 (https://github.com/omniauth/omniauth/wiki/FAQ#cve-2015-9284-warnings)
|
||||
gem 'omniauth-rails_csrf_protection', '~> 0.1'
|
||||
gem 'omniauth-okta', git: 'https://github.com/scinote-eln/omniauth-okta', branch: 'org_auth_server_support'
|
||||
gem 'omniauth-rails_csrf_protection', '~> 1.0'
|
||||
|
||||
# Gems for API implementation
|
||||
gem 'active_model_serializers', '~> 0.10.7'
|
||||
|
|
81
Gemfile.lock
81
Gemfile.lock
|
@ -39,6 +39,15 @@ GIT
|
|||
devise-async (0.10.2)
|
||||
devise (>= 4.0)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/scinote-eln/omniauth-okta
|
||||
revision: fc4d833532dec050a3c6296691d631b64de1ee19
|
||||
branch: org_auth_server_support
|
||||
specs:
|
||||
omniauth-okta (2.0.0)
|
||||
omniauth (~> 2.0)
|
||||
omniauth-oauth2 (~> 1.7, >= 1.7.1)
|
||||
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
|
@ -164,7 +173,7 @@ GEM
|
|||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
backports (3.20.2)
|
||||
base62 (1.0.0)
|
||||
bcrypt (3.1.16)
|
||||
bcrypt (3.1.18)
|
||||
better_errors (2.9.1)
|
||||
coderay (>= 1.0.0)
|
||||
erubi (>= 1.0.0)
|
||||
|
@ -256,7 +265,7 @@ GEM
|
|||
delayed_job_active_record (4.1.5)
|
||||
activerecord (>= 3.0, < 6.2)
|
||||
delayed_job (>= 3.0, < 5)
|
||||
devise (4.7.3)
|
||||
devise (4.8.1)
|
||||
bcrypt (~> 3.0)
|
||||
orm_adapter (~> 0.1)
|
||||
railties (>= 4.1.0)
|
||||
|
@ -273,7 +282,7 @@ GEM
|
|||
railties (>= 5)
|
||||
down (5.2.0)
|
||||
addressable (~> 2.5)
|
||||
erubi (1.10.0)
|
||||
erubi (1.11.0)
|
||||
et-orbi (1.2.4)
|
||||
tzinfo
|
||||
execjs (2.7.0)
|
||||
|
@ -284,11 +293,10 @@ GEM
|
|||
railties (>= 5.0.0)
|
||||
faker (2.15.1)
|
||||
i18n (>= 1.6, < 2)
|
||||
faraday (1.3.0)
|
||||
faraday-net_http (~> 1.0)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ruby2_keywords
|
||||
faraday-net_http (1.0.1)
|
||||
faraday (2.5.2)
|
||||
faraday-net_http (>= 2.0, < 3.1)
|
||||
ruby2_keywords (>= 0.0.4)
|
||||
faraday-net_http (3.0.0)
|
||||
fastimage (2.2.1)
|
||||
ffi (1.15.5)
|
||||
figaro (1.2.0)
|
||||
|
@ -308,7 +316,7 @@ GEM
|
|||
httparty (0.17.3)
|
||||
mime-types (~> 3.0)
|
||||
multi_xml (>= 0.5.2)
|
||||
i18n (1.11.0)
|
||||
i18n (1.12.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
i18n-js (3.8.0)
|
||||
i18n (>= 0.6.6)
|
||||
|
@ -370,14 +378,13 @@ GEM
|
|||
mini_magick (4.11.0)
|
||||
mini_mime (1.1.2)
|
||||
mini_portile2 (2.8.0)
|
||||
minitest (5.16.2)
|
||||
minitest (5.16.3)
|
||||
momentjs-rails (2.17.1)
|
||||
railties (>= 3.1)
|
||||
msgpack (1.4.2)
|
||||
multi_json (1.15.0)
|
||||
multi_test (0.1.2)
|
||||
multi_xml (0.6.0)
|
||||
multipart-post (2.1.1)
|
||||
nested_form_fields (0.8.4)
|
||||
coffee-rails (>= 3.2.1)
|
||||
jquery-rails
|
||||
|
@ -387,29 +394,27 @@ GEM
|
|||
nokogiri (1.13.10)
|
||||
mini_portile2 (~> 2.8.0)
|
||||
racc (~> 1.4)
|
||||
oauth2 (1.4.4)
|
||||
faraday (>= 0.8, < 2.0)
|
||||
oauth2 (2.0.9)
|
||||
faraday (>= 0.17.3, < 3.0)
|
||||
jwt (>= 1.0, < 3.0)
|
||||
multi_json (~> 1.3)
|
||||
multi_xml (~> 0.5)
|
||||
rack (>= 1.2, < 3)
|
||||
omniauth (1.9.2)
|
||||
rack (>= 1.2, < 4)
|
||||
snaky_hash (~> 2.0)
|
||||
version_gem (~> 1.1)
|
||||
omniauth (2.1.0)
|
||||
hashie (>= 3.4.6)
|
||||
rack (>= 1.6.2, < 3)
|
||||
omniauth-azure-activedirectory (1.0.0)
|
||||
jwt (~> 1.5)
|
||||
omniauth (~> 1.1)
|
||||
rack (>= 2.2.3)
|
||||
rack-protection
|
||||
omniauth-azure-activedirectory-v2 (2.0.0)
|
||||
omniauth-oauth2 (~> 1.8)
|
||||
omniauth-linkedin-oauth2 (1.0.0)
|
||||
omniauth-oauth2
|
||||
omniauth-oauth2 (1.7.1)
|
||||
oauth2 (~> 1.4)
|
||||
omniauth (>= 1.9, < 3)
|
||||
omniauth-okta (0.1.3)
|
||||
omniauth (~> 1.5)
|
||||
omniauth-oauth2 (>= 1.6.0, < 2.0)
|
||||
omniauth-rails_csrf_protection (0.1.2)
|
||||
omniauth-oauth2 (1.8.0)
|
||||
oauth2 (>= 1.4, < 3)
|
||||
omniauth (~> 2.0)
|
||||
omniauth-rails_csrf_protection (1.0.1)
|
||||
actionpack (>= 4.2)
|
||||
omniauth (>= 1.3.1)
|
||||
omniauth (~> 2.0)
|
||||
orm_adapter (0.5.0)
|
||||
overcommit (0.57.0)
|
||||
childprocess (>= 0.6.3, < 5)
|
||||
|
@ -447,6 +452,8 @@ GEM
|
|||
rack (>= 1.0, < 3)
|
||||
rack-cors (1.1.1)
|
||||
rack (>= 2.0.0)
|
||||
rack-protection (3.0.1)
|
||||
rack
|
||||
rack-proxy (0.6.5)
|
||||
rack
|
||||
rack-test (2.0.2)
|
||||
|
@ -545,7 +552,7 @@ GEM
|
|||
ruby-progressbar (1.11.0)
|
||||
ruby-vips (2.1.4)
|
||||
ffi (~> 1.12)
|
||||
ruby2_keywords (0.0.4)
|
||||
ruby2_keywords (0.0.5)
|
||||
rubyzip (1.3.0)
|
||||
rufus-scheduler (3.7.0)
|
||||
fugit (~> 1.1, >= 1.1.6)
|
||||
|
@ -577,6 +584,9 @@ GEM
|
|||
simplecov_json_formatter (~> 0.1)
|
||||
simplecov-html (0.12.3)
|
||||
simplecov_json_formatter (0.1.2)
|
||||
snaky_hash (2.0.1)
|
||||
hashie
|
||||
version_gem (~> 1.1, >= 1.1.1)
|
||||
spinjs-rails (1.4)
|
||||
rails (>= 3.1)
|
||||
sprockets (4.1.1)
|
||||
|
@ -596,13 +606,14 @@ GEM
|
|||
turbolinks (5.1.1)
|
||||
turbolinks-source (~> 5.1)
|
||||
turbolinks-source (5.2.0)
|
||||
tzinfo (2.0.4)
|
||||
tzinfo (2.0.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
uglifier (4.2.0)
|
||||
execjs (>= 0.3.0, < 3)
|
||||
underscore-rails (1.8.3)
|
||||
unicode-display_width (1.7.0)
|
||||
uniform_notifier (1.13.2)
|
||||
version_gem (1.1.1)
|
||||
view_component (2.28.0)
|
||||
activesupport (>= 5.0.0, < 7.0)
|
||||
warden (1.2.9)
|
||||
|
@ -659,7 +670,7 @@ DEPENDENCIES
|
|||
database_cleaner
|
||||
deface (~> 1.0)
|
||||
delayed_job_active_record
|
||||
devise (~> 4.7.1)
|
||||
devise (~> 4.8.1)
|
||||
devise-async!
|
||||
devise_invitable
|
||||
discard (~> 1.0)
|
||||
|
@ -690,11 +701,11 @@ DEPENDENCIES
|
|||
nested_form_fields
|
||||
newrelic_rpm
|
||||
nokogiri (~> 1.13.10)
|
||||
omniauth
|
||||
omniauth-azure-activedirectory
|
||||
omniauth (~> 2.1)
|
||||
omniauth-azure-activedirectory-v2
|
||||
omniauth-linkedin-oauth2
|
||||
omniauth-okta
|
||||
omniauth-rails_csrf_protection (~> 0.1)
|
||||
omniauth-okta!
|
||||
omniauth-rails_csrf_protection (~> 1.0)
|
||||
overcommit
|
||||
pg (~> 1.1)
|
||||
pg_search
|
||||
|
|
|
@ -17,7 +17,7 @@ module Users
|
|||
|
||||
def customazureactivedirectory
|
||||
auth = request.env['omniauth.auth']
|
||||
provider_id = auth.dig(:extra, :raw_info, :id_token_claims, :aud)
|
||||
provider_id = auth.dig(:extra, :raw_info, :aud)
|
||||
provider_conf = Rails.configuration.x.azure_ad_apps[provider_id]
|
||||
raise StandardError, 'No matching Azure AD provider config found' if provider_conf.blank?
|
||||
|
||||
|
|
|
@ -8,6 +8,16 @@ Rails.application.configure do
|
|||
app_name = name.sub('_AZURE_AD_APP_ID', '')
|
||||
config.x.azure_ad_apps[value] = {}
|
||||
|
||||
tenant_id = ENV["#{app_name}_AZURE_AD_TENANT_ID"]
|
||||
raise StandardError, "No Tenant ID for #{app_name} Azure app" unless tenant_id
|
||||
|
||||
config.x.azure_ad_apps[value][:tenant_id] = tenant_id
|
||||
|
||||
client_secret = ENV["#{app_name}_AZURE_AD_CLIENT_SECRET"]
|
||||
raise StandardError, "No Client Secret for #{app_name} Azure app" unless client_secret
|
||||
|
||||
config.x.azure_ad_apps[value][:client_secret] = client_secret
|
||||
|
||||
iss = ENV["#{app_name}_AZURE_AD_ISS"]
|
||||
raise StandardError, "No ISS for #{app_name} Azure app" unless iss
|
||||
|
||||
|
@ -46,6 +56,12 @@ Rails.application.configure do
|
|||
app_id = azure_ad_app['app_id']
|
||||
Rails.logger.error('No app_id present for the entry in Azure app settings') && next unless app_id
|
||||
|
||||
app_config[:tenant_id] = azure_ad_app['tenant_id']
|
||||
Rails.logger.error("No tenant id for #{app_id} Azure app") && next unless app_config[:tenant_id]
|
||||
|
||||
app_config[:client_secret] = azure_ad_app['client_secret']
|
||||
Rails.logger.error("No client secret for #{app_id} Azure app") && next unless app_config[:client_secret]
|
||||
|
||||
app_config[:iss] = azure_ad_app['iss']
|
||||
Rails.logger.error("No iss for #{app_id} Azure app") && next unless app_config[:iss]
|
||||
|
||||
|
|
|
@ -301,19 +301,32 @@ Devise.setup do |config|
|
|||
|
||||
Rails.application.config.x.disable_local_passwords = ENV['DISABLE_LOCAL_PASSWORDS'] == 'true'
|
||||
|
||||
if [ENV['OKTA_CLIENT_ID'], ENV['OKTA_CLIENT_SECRET'], ENV['OKTA_DOMAIN'], ENV['OKTA_AUTH_SERVER_ID']].all?(&:present?)
|
||||
if [ENV['OKTA_CLIENT_ID'], ENV['OKTA_CLIENT_SECRET'], ENV['OKTA_DOMAIN']].all?(&:present?)
|
||||
OKTA_OAUTH2_BASE_URL =
|
||||
if ENV['OKTA_AUTH_SERVER_ID'].blank?
|
||||
"https://#{ENV['OKTA_DOMAIN']}/oauth2"
|
||||
else
|
||||
"https://#{ENV['OKTA_DOMAIN']}/oauth2/#{ENV['OKTA_AUTH_SERVER_ID']}"
|
||||
end
|
||||
client_options = {
|
||||
site: "https://#{ENV['OKTA_DOMAIN']}",
|
||||
authorize_url: "#{OKTA_OAUTH2_BASE_URL}/v1/authorize",
|
||||
token_url: "#{OKTA_OAUTH2_BASE_URL}/v1/token",
|
||||
user_info_url: "#{OKTA_OAUTH2_BASE_URL}/v1/userinfo"
|
||||
}
|
||||
client_options[:audience] = ENV['OKTA_CLIENT_ID'] if ENV['OKTA_AUDIENCE'].present?
|
||||
if ENV['OKTA_AUTH_SERVER_ID'].present?
|
||||
client_options[:authorization_server] = ENV['OKTA_AUTH_SERVER_ID']
|
||||
else
|
||||
client_options[:use_org_auth_server] = true
|
||||
end
|
||||
config.omniauth(
|
||||
:okta,
|
||||
ENV['OKTA_CLIENT_ID'],
|
||||
ENV['OKTA_CLIENT_SECRET'],
|
||||
scope: 'openid profile email',
|
||||
fields: %w(profile email),
|
||||
client_options: {
|
||||
site: "https://#{ENV['OKTA_DOMAIN']}",
|
||||
authorize_url: "https://#{ENV['OKTA_DOMAIN']}/oauth2/#{ENV['OKTA_AUTH_SERVER_ID']}/v1/authorize",
|
||||
token_url: "https://#{ENV['OKTA_DOMAIN']}/oauth2/#{ENV['OKTA_AUTH_SERVER_ID']}/v1/token",
|
||||
user_info_url: "https://#{ENV['OKTA_DOMAIN']}/oauth2/#{ENV['OKTA_AUTH_SERVER_ID']}/v1/userinfo"
|
||||
},
|
||||
client_options: client_options,
|
||||
strategy_class: OmniAuth::Strategies::Okta
|
||||
)
|
||||
end
|
||||
|
|
|
@ -24,10 +24,11 @@ AZURE_SETUP_PROC = lambda do |env|
|
|||
|
||||
provider_id ||= providers.keys.first
|
||||
provider_conf = providers[provider_id]
|
||||
|
||||
env['omniauth.strategy'].options[:client_id] = provider_id
|
||||
env['omniauth.strategy'].options[:openid_config_url] = provider_conf[:conf_url]
|
||||
env['omniauth.strategy'].options[:client_id] = provider_id.to_s
|
||||
env['omniauth.strategy'].options[:client_secret] = provider_conf[:client_secret]
|
||||
env['omniauth.strategy'].options[:tenant_id] = provider_conf[:tenant_id]
|
||||
env['omniauth.strategy'].options[:sign_in_policy] = provider_conf[:sign_in_policy]
|
||||
env['omniauth.strategy'].options[:name] = 'customazureactivedirectory'
|
||||
end
|
||||
|
||||
Rails.application.config.middleware.use OmniAuth::Builder do
|
||||
|
|
|
@ -2,42 +2,19 @@
|
|||
|
||||
module OmniAuth
|
||||
module Strategies
|
||||
class CustomAzureActiveDirectory < AzureActiveDirectory
|
||||
class CustomAzureActiveDirectory < AzureActivedirectoryV2
|
||||
include OmniAuth::Strategy
|
||||
|
||||
option :openid_config_url
|
||||
option :sign_in_policy
|
||||
option :name, 'customazureactivedirectory'
|
||||
|
||||
# Azure doesn't allow query params in callback URL
|
||||
def callback_url
|
||||
full_host + script_name + callback_path
|
||||
end
|
||||
def raw_info
|
||||
if @raw_info.nil?
|
||||
id_token_data = ::JWT.decode(access_token.params['id_token'], nil, false).first rescue {}
|
||||
auth_token_data = ::JWT.decode(access_token.token, nil, false).first rescue {}
|
||||
@raw_info = auth_token_data.merge(id_token_data)
|
||||
end
|
||||
|
||||
def openid_config_url
|
||||
options[:openid_config_url]
|
||||
end
|
||||
|
||||
def authorize_endpoint_url
|
||||
uri = URI(openid_config['authorization_endpoint'])
|
||||
params = {
|
||||
client_id: client_id,
|
||||
redirect_uri: callback_url,
|
||||
response_mode: response_mode,
|
||||
response_type: response_type,
|
||||
nonce: new_nonce,
|
||||
scope: 'openid profile email'
|
||||
}
|
||||
params[:p] = options[:sign_in_policy] if options[:sign_in_policy].present?
|
||||
|
||||
uri.query = URI.encode_www_form(params)
|
||||
uri.to_s
|
||||
end
|
||||
|
||||
def validate_and_parse_id_token(id_token)
|
||||
jwt_claims, jwt_header = Api::AzureJwt.decode(id_token)
|
||||
return jwt_claims, jwt_header if jwt_claims['nonce'] == read_nonce
|
||||
|
||||
raise JWT::DecodeError, 'Returned nonce did not match.'
|
||||
@raw_info
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue