Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Add multi provider Authentication #318

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ gem 'inline_svg'
gem "lookbook", '~> 1.5.5'
gem 'ontologies_api_client', git: 'https://github.com/ontoportal-lirmm/ontologies_api_ruby_client.git', branch: 'development'

# Multi-Provider Authentication
gem 'omniauth'
gem "omniauth-rails_csrf_protection"
gem 'omniauth-github'
gem 'omniauth-google-oauth2'
gem 'omniauth-orcid'
gem 'omniauth-keycloak'

group :staging, :production, :appliance do
# application monitoring
Expand Down
55 changes: 52 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,14 @@ GEM
tzinfo (~> 2.0)
addressable (2.8.5)
public_suffix (>= 2.0.2, < 6.0)
aes_key_wrap (1.1.0)
airbrussh (1.4.1)
sshkit (>= 1.6.1, != 1.7.0)
ast (2.4.2)
autoprefixer-rails (10.4.13.0)
execjs (~> 2)
bcrypt_pbkdf (1.1.0)
bindata (2.4.15)
bindex (0.8.1)
bootsnap (1.16.0)
msgpack (~> 1.2)
Expand Down Expand Up @@ -153,6 +155,8 @@ GEM
faraday-excon (2.0.0)
excon (>= 0.27.4)
faraday (~> 2.0.0.alpha.pre.2)
faraday-follow_redirects (0.3.0)
faraday (>= 1, < 3)
faraday-multipart (1.0.4)
multipart-post (~> 2)
faraday-net_http (2.1.0)
Expand All @@ -167,6 +171,7 @@ GEM
haml (5.2.2)
temple (>= 0.8.0)
tilt
hashie (5.0.0)
html2haml (2.3.0)
erubis (~> 2.7.0)
haml (>= 4.0)
Expand Down Expand Up @@ -198,6 +203,13 @@ GEM
jsbundling-rails (1.1.2)
railties (>= 6.0.0)
json (2.6.3)
json-jwt (1.16.3)
activesupport (>= 4.2)
aes_key_wrap
bindata
faraday (~> 2.0)
faraday-follow_redirects
jwt (2.7.1)
language_server-protocol (3.17.0.3)
listen (3.8.0)
rb-fsevent (~> 0.10, >= 0.10.3)
Expand Down Expand Up @@ -235,6 +247,7 @@ GEM
minitest (5.19.0)
msgpack (1.7.2)
multi_json (1.15.0)
multi_xml (0.6.0)
multipart-post (2.3.0)
mysql2 (0.5.3)
net-ftp (0.2.0)
Expand All @@ -257,12 +270,41 @@ GEM
netrc (0.11.0)
newrelic_rpm (9.3.1)
nio4r (2.5.9)
nokogiri (1.15.3)
mini_portile2 (~> 2.8.2)
nokogiri (1.15.3-x86_64-darwin)
racc (~> 1.4)
nokogiri (1.15.3-x86_64-linux)
racc (~> 1.4)
oauth2 (1.4.11)
faraday (>= 0.17.3, < 3.0)
jwt (>= 1.0, < 3.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 4)
oj (3.15.1)
omniauth (1.9.2)
hashie (>= 3.4.6)
rack (>= 1.6.2, < 3)
omniauth-github (1.4.0)
omniauth (~> 1.5)
omniauth-oauth2 (>= 1.4.0, < 2.0)
omniauth-google-oauth2 (0.8.2)
jwt (>= 2.0)
oauth2 (~> 1.1)
omniauth (~> 1.1)
omniauth-oauth2 (>= 1.6)
omniauth-keycloak (1.2.1)
json-jwt (~> 1.12)
omniauth (~> 1.9.0)
omniauth-oauth2 (~> 1.6.0)
omniauth-oauth2 (1.6.0)
oauth2 (~> 1.1)
omniauth (~> 1.9)
omniauth-orcid (2.1.1)
omniauth-oauth2 (~> 1.3)
ruby_dig (~> 0.0.2)
omniauth-rails_csrf_protection (0.1.2)
actionpack (>= 4.2)
omniauth (>= 1.3.1)
open_uri_redirections (0.2.1)
parallel (1.23.0)
parser (3.2.2.3)
Expand Down Expand Up @@ -370,6 +412,7 @@ GEM
parser (>= 3.2.1.0)
ruby-progressbar (1.13.0)
ruby2_keywords (0.0.5)
ruby_dig (0.0.2)
ruby_parser (3.20.3)
sexp_processor (~> 4.16)
rubyzip (2.3.2)
Expand Down Expand Up @@ -453,7 +496,7 @@ GEM
zeitwerk (2.6.11)

PLATFORMS
ruby
x86_64-darwin-21
x86_64-linux

DEPENDENCIES
Expand Down Expand Up @@ -492,6 +535,12 @@ DEPENDENCIES
net-http
newrelic_rpm
oj
omniauth
omniauth-github
omniauth-google-oauth2
omniauth-keycloak
omniauth-orcid
omniauth-rails_csrf_protection
ontologies_api_client!
open_uri_redirections
pry
Expand Down
4 changes: 4 additions & 0 deletions app/assets/images/icons/github.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions app/assets/images/icons/google.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions app/assets/images/icons/keycloak.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions app/assets/images/icons/orcid.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 5 additions & 4 deletions app/assets/stylesheets/login.scss
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
.login-form{
margin-top: 30px;
padding: 37px 41px;
box-shadow: rgba(0, 0, 0, 0.08) 0px 20px 50px;
border-radius: 14px;
margin-top: 30px;
padding: 37px 41px;
box-shadow: rgba(0, 0, 0, 0.08) 0px 20px 50px;
border-radius: 14px;
max-width: 439px;
}

.login-input{
Expand Down
22 changes: 22 additions & 0 deletions app/controllers/login_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,28 @@ def create
end
end


def create_omniauth
auth_data = request.env['omniauth.auth']
auth_code = auth_data.credentials.token
token_provider = helpers.omniauth_token_provider(params[:provider])

logged_in_user = LinkedData::Client::HTTP.post("#{LinkedData::Client.settings.rest_url}/users/authenticate", { access_token: auth_code , token_provider: token_provider})
if logged_in_user && !logged_in_user.errors
login(logged_in_user)
redirect = "/"

if session[:redirect]
redirect = CGI.unescape(session[:redirect])
end

redirect_to redirect
else
@errors = ["#{params[:provider]} authentication failed"]
render :action => 'index'
end
end

# Login as the provided username (only for admin users)
def login_as
unless session[:user] && session[:user].admin?
Expand Down
12 changes: 12 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ def get_apikey
end
end

def omniauth_providers_info
$OMNIAUTH_PROVIDERS
end

def omniauth_provider_info(strategy)
omniauth_providers_info.select {|k,v| v[:strategy].eql?(strategy.to_sym)}
end

def omniauth_token_provider(strategy)
omniauth_provider_info(strategy).keys.first
end

def isOwner?(id)
unless session[:user].nil?
if session[:user].admin?
Expand Down
27 changes: 18 additions & 9 deletions app/views/login/index.html.haml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
- @title = "Login"
= form_for(:user, :url => {:controller => 'login',:action=>'create'}) do |f|
- unless @errors.nil?
%div{:style => "color:red;"}
Errors On Form
%ul
- for error in @errors
%li= error
.d-flex.justify-content-center
.login-form
- unless @errors.nil?
%div{:style => "color:red;"}
Errors On Form
%ul
- for error in @errors
%li= error
.d-flex.justify-content-center
.login-form
= form_for(:user, :url => {:controller => 'login',:action=>'create'}) do |f|
%p.login-input-title Username or Email
= text_field 'user', 'username', class: "login-input email-input", placeholder: "Enter your email"
%p.login-input-title Password
Expand All @@ -18,3 +18,12 @@
%p.dont-have-account
Don't have an account?
%a.text-decoration-none{:href => new_user_path} Register
%hr.divider.w-100
%div.d-flex.justify-content-center.flew-wrap
- omniauth_providers_info.each do |provider, config|
= button_to "/auth/#{config[:name] || config[:strategy] || provider}",
class: 'btn btn-lg', style:'width: 70px', title: "Login with #{provider.to_s.humanize}", 'data-turbo': false do
- if config[:icon]
= inline_svg config[:icon]
- else
= provider.to_s.humanize
28 changes: 28 additions & 0 deletions config/bioportal_config_env.rb.sample
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,34 @@ $ANNOUNCE_LIST||= "users-list@test"
# Where "ncbo" is the namespace used as key in the interportal_hash
$INTERPORTAL_HASH = {}

# OAuth2 authentication
$OMNIAUTH_PROVIDERS = {
github: {
client_id: 'CLIENT_ID',
client_secret: 'CLIENT_SECRET',
icon: 'icons/github.svg',
},
google: {
strategy: :google_oauth2,
client_id: 'CLIENT_ID',
client_secret: 'CLIENT_SECRET',
icon: 'icons/google.svg',
},
orcid: {
client_id: 'CLIENT_SECRET',
client_secret: 'CLIENT_SECRET',
icon: 'icons/orcid.svg'
},
keycloak: {
strategy: :keycloak_openid,
client_id: 'YOUR_KEYCLOAK_CLIENT_ID',
client_secret: 'YOUR_KEYCLOAK_CLIENT_SECRET',
client_options: { site: 'KEYCLOAK_SITE', realm: 'KEYCLOAK_REALM' },
name: 'keycloak',
icon: 'icons/keycloak.svg'
}
}.freeze

# Don't load and don't display recent mappings if false, in case of too many mappings (take longer to load homepage)
$DISPLAY_RECENT = false

Expand Down
5 changes: 5 additions & 0 deletions config/initializers/omniauth.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Rails.application.config.middleware.use OmniAuth::Builder do
$OMNIAUTH_PROVIDERS.each do |provider, config|
provider config[:strategy] || provider, config[:client_id], config[:client_secret], client_options: {}.merge(config[:client_options].to_h)
end
end
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

root to: 'home#index'

get 'auth/:provider/callback', to: 'login#create_omniauth'
get 'locale/:language', to: 'language#set_locale_language'

get '/notes/new_comment', to: 'notes#new_comment'
Expand Down