concerto_saml_auth 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b6ebfa7bb437454efca0513642b2bfbf5464e5f2
4
+ data.tar.gz: 59ac1d64b4f418bc48019657687edc7bb94ddc98
5
+ SHA512:
6
+ metadata.gz: 2e16f9fa978ded9c51250f5a3e2b2aee663db06cceabd22a2ae1c5068b9c2e1e667d91e1acc5879d3f8c1d319e39a1408dfbcbb2199270ef3969a827f0c73ede
7
+ data.tar.gz: 6d466a2c368cd922ec36fb2d7cc6d0d8249ba5dfef681d03f211905fd1f2e387239febe9bef305e756db91e1a25a57e25255f9baaefd4bcba9c03cbf05b94cb8
data/LICENSE ADDED
@@ -0,0 +1,14 @@
1
+ Copyright 2014 Concerto Authors
2
+ Copyright 2017 Thorben Dahl
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,64 @@
1
+ Concerto SAML Auth
2
+ =====================
3
+
4
+ Authenticate Concerto users through your own [SAML](https://en.wikipedia.org/wiki/Security_Assertion_Markup_Language) deployment.
5
+
6
+ Please note that this project is not affiliated with or endorsed by the Concerto Digital Signage project.
7
+
8
+ The aim of this project is to customize the Concerto CAS Auth plugin so it works with `omniauth-saml` instead of `omniauth-cas`.
9
+
10
+ Installing the plugin
11
+ ----------------------
12
+
13
+ 1. Log in using a system admin account in your Concerto deployment. You should have set up your Concerto installation already.
14
+ 2. Click on the "plugins" button on the top navigation bar under the admin section.
15
+ 3. On the right side of the page, click on the "new plugin" button.
16
+ 4. With Git Repository selected as the source, write `concerto_saml_auth` as the Gem Name, and this repository's clone URL as the Source URL.
17
+ 5. Click save, you will now stop your Concerto web server, run the ```bundle``` command (while in the Concerto directory), and start your web server again.
18
+ 6. Since the SAML plugin is not configured yet, you can log back into your Concerto accounts by visiting the ```your.concerto.url/users/sign_in``` route, using
19
+ any user that was not created using through SAML login.
20
+ 7. If the plugin was installed successfully, you will see a new "SAML User Authentication" settings tab under the "settings" page. This page can be found by clicking the "settings" button on the top navigation bar under the admin section.
21
+ 8. Configure the plugin and restart the web server, as explained below.
22
+ 9. Add your Service Provider's metadata to the Identity Provider. You can find your metadata at `your.concerto.url/auth/saml/metadata`.
23
+
24
+ Configuring the plugin
25
+ ----------------------
26
+
27
+ **The details of how to configure this plugin are not finalized.**
28
+
29
+ 1. Log in using a system admin account in your Concerto deployment
30
+ 2. Click on the "settings" button on the top navigation bar under the admin section.
31
+ 3. Click on the "SAML User Authentication" tab.
32
+ 4. Configure the different values (see explanation below).
33
+ 7. After saving these settings, you will need to restart your Concerto web server.
34
+ 8. Your log in links at the top of the page should now point to your CAS authentication.
35
+
36
+ Explanation of the configuration parameters:
37
+
38
+ **Saml Idp Metadata**: URL to the Identity Provider's metadata. For a simpleSAML installation, this could be `https://idp.example.com/simplesaml/saml2/idp/metadata.php`. All information about the Identity Provider is gathered through this.
39
+
40
+ **Saml Issuer**: Unique identification of this application, used by the Identity Provider to separate different Service Provider. It is normal to use an URL you control, so there is no chance of collision. Example: `https://concerto.example.com/saml2`.
41
+
42
+ The rest of the configuration items maps information received from the Identity Provider to fields in Concerto.
43
+
44
+ **Saml Uid Key**: Name of field containing user ID, used to map between users logging in and the local Concerto user they should log in as.
45
+
46
+ **Saml Email Key**: Name of field containing the user's email address.
47
+
48
+ **Saml First Name Key**: Name of field containing the user's first name.
49
+
50
+ **Saml Last Name Key**: Name of field containing the user's last name.
51
+
52
+ **Saml Member Of Key**: Name of fields containing the groups the user is a member of, as expressed by LDAP's memberOf field. You can leave this out to not synchronize groups.
53
+
54
+ **Saml Member Of Filter**: Comma-separated list of case-insensitive assertions. A group must match at least one of those assertions in order to be included in Concerto. You can use the common name to whitelist groups, like `CN=Administrators, CN=Graphics`.
55
+
56
+ **Saml Admin Groups**: Comma-separated case-insensitive list of groups whose members should be made admin when they log in through SAML.
57
+
58
+ note: This plugin is essentially a wrapper around [omniauth-saml](https://github.com/omniauth/omniauth-saml) with added logic for creating Concerto user accounts with the returned SAML information and synchronize privileges. Feel free to follow the omniauth-saml link and see a more detailed description of the configuration items.
59
+
60
+ Known Issues
61
+ ------------
62
+
63
+ * Localization is not a thing with this plugin. All error messages and changes made to interface are in English only.
64
+ * Somewhat specific: This plugin was made to fit the needs of Studentmediene i Trondheim AS. Some details of its operation may not be suitable for others.
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'ConcertoSamlAuth'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+
34
+ task default: :test
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any styles
10
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11
+ * file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,190 @@
1
+ module ConcertoSamlAuth
2
+ class ApplicationController < ::ApplicationController
3
+
4
+ # Used to map a user id with a corresponding authentication provider in the
5
+ # database (in this case it's SAML)
6
+ require 'concerto_identity'
7
+
8
+ # Find or create a new user based on values returned by the SAML callback
9
+ def find_from_omniauth(saml_hash)
10
+ # Get configuration options for customized SAML return value identifiers
11
+ omniauth_config = ConcertoSamlAuth::Engine.config.omniauth_config
12
+ uid = saml_hash[:uid]
13
+ uid = uid.downcase
14
+
15
+ # Check if an identity records exists for the user attempting to sign in
16
+ if identity = ConcertoIdentity::Identity.find_by_external_id(uid)
17
+ # Return the matching user record
18
+ user_existed = true
19
+ user = identity.user
20
+ else
21
+ # Add a new user via omniauth SAML details
22
+ user_existed = false
23
+ user = User.new
24
+ end
25
+
26
+ # Set user attributes
27
+
28
+ # First name is required for user validation
29
+ if !saml_hash[:info][:first_name].nil?
30
+ user.first_name = saml_hash[:info][:first_name]
31
+ else
32
+ user.first_name = uid
33
+ end
34
+
35
+ if !saml_hash[:info][:last_name].nil?
36
+ user.last_name = saml_hash[:info][:last_name]
37
+ end
38
+
39
+ # Email is required for user validation
40
+ if saml_hash[:info][:email].nil?
41
+ flash.notice = "No email was provided by the identity provider"
42
+ return nil
43
+ else
44
+ user.email = saml_hash[:info][:email]
45
+ end
46
+
47
+
48
+ # Set user password and confirmation to random tokens
49
+ user.password,user.password_confirmation=Devise.friendly_token
50
+
51
+ # Attempt to save our new user
52
+ if user.save
53
+ # Saved
54
+
55
+ if omniauth_config[:member_of_key].present?
56
+ synchronize_group_membership(user, saml_hash, omniauth_config)
57
+ end
58
+
59
+ if omniauth_config[:admin_groups].present?
60
+ synchronize_is_admin(user, omniauth_config)
61
+ end
62
+
63
+ user.save!
64
+
65
+ if !user_existed
66
+ # Create a matching identity to track our new user for future
67
+ # sessions and return our new user record
68
+ ConcertoIdentity::Identity.create(provider: "saml",
69
+ external_id: uid,
70
+ user_id: user.id)
71
+ end
72
+
73
+ return {user: user, existed: user_existed}
74
+ else
75
+ # User save failed, an error occurred
76
+ flash.notice = "Failed to sign in with SAML.
77
+ #{user.errors.full_messages.to_sentence}."
78
+ return nil
79
+ end
80
+ end
81
+
82
+ def synchronize_group_membership(user, saml_hash, omniauth_config)
83
+ desired_group_names = find_user_groups(saml_hash, omniauth_config)
84
+ existing_group_memberships = Membership.where(user: user)
85
+ existing_group_names = existing_group_memberships.map do |membership|
86
+ membership.group.name
87
+ end
88
+ groups_to_add = desired_group_names - existing_group_names
89
+ groups_to_remove = existing_group_names - desired_group_names
90
+ add_user_to(groups_to_add, user)
91
+ remove_user_from(groups_to_remove, user)
92
+ end
93
+
94
+ def find_user_groups(saml_hash, omniauth_config)
95
+ member_of_key = omniauth_config[:member_of_key]
96
+ member_of_lines = saml_hash[:extra][:response_object].attributes.multi(member_of_key)
97
+ if member_of_lines.nil?
98
+ Rails.logger.debug "No user groups found"
99
+ return nil
100
+ end
101
+ # Go from array of "CN=Broadcast Engineer,OU=Commission,OU=Groups,DC=example,DC=com"
102
+ # to array of ["CN=Broadcast Engineer", "OU=Commission", "OU=Groups", "DC=example", "DC=com"]
103
+ groups_splitted = member_of_lines.map do |single_member_of_line|
104
+ single_member_of_line.split(",")
105
+ end
106
+ # Downcase every string
107
+ groups_splitted.map! do |single_splitted_group|
108
+ single_splitted_group.map do |group_part|
109
+ group_part.downcase
110
+ end
111
+ end
112
+ Rails.logger.debug "Interpreting the memberOf field:"
113
+ Rails.logger.debug groups_splitted
114
+ # Remove elements which are not matched by the filter
115
+ if !omniauth_config[:member_of_filter].blank?
116
+ filter = omniauth_config[:member_of_filter]
117
+ filter = (filter.strip).downcase
118
+ filter_list = filter.split(",")
119
+ Rails.logger.debug filter_list
120
+ matching_groups = groups_splitted.select do |single_splitted_group|
121
+ # Check if the intersection of single_splitted_group and filter_list has elements
122
+ # (meaning that at least one element in single_splitted_group matches one element
123
+ # in filter_list)
124
+ !(single_splitted_group & filter_list).empty?
125
+ end
126
+ else
127
+ matching_groups = groups_splitted
128
+ end
129
+ Rails.logger.debug matching_groups
130
+ # Go to array of {:cn => ["broadcast engineer"], :ou => ["commission", "groups"], :dc => ["example", "com"]}
131
+ group_hashes = matching_groups.map do |single_splitted_group|
132
+ # Create a hash which returns new Arrays for missing entries
133
+ resulting_group_hash = Hash.new{|h,k| h[k] = []}
134
+ single_splitted_group.each do |single_group_attribute|
135
+ key_and_value = single_group_attribute.split("=")
136
+ key = key_and_value.first
137
+ value = key_and_value.second
138
+ resulting_group_hash[key].push(value)
139
+ end
140
+ resulting_group_hash
141
+ end
142
+ Rails.logger.debug group_hashes
143
+ # Go to array of "broadcast engineer", but ensure all CNs are included
144
+ common_names = []
145
+ group_hashes.each do |single_group_hash|
146
+ single_group_hash["cn"].each do |group_name|
147
+ common_names.push(group_name)
148
+ end
149
+ end
150
+ Rails.logger.debug common_names
151
+ # Go to array of "Broadcast engineer" (normalizing names)
152
+ common_names.map do |single_common_name|
153
+ single_common_name.capitalize
154
+ end
155
+ end
156
+
157
+ def add_user_to(all_groups, user)
158
+ all_groups.each do |group_name|
159
+ group = Group.where(:name => group_name).first_or_create!
160
+ membership = Membership.create!(:user_id => user.id, :group_id => group.id, :level => Membership::LEVELS[:regular])
161
+ membership.perms[:screen] = :all
162
+ membership.perms[:feed] = :all
163
+ membership.save!
164
+ end
165
+ end
166
+
167
+ def remove_user_from(all_groups, user)
168
+ all_groups.each do |group_name|
169
+ group = Group.where(:name => group_name).first!
170
+ Membership.where(:user_id => user.id, :group_id => group.id).destroy
171
+ end
172
+ end
173
+
174
+ def synchronize_is_admin(user, omniauth_config)
175
+ admin_group_string = omniauth_config[:admin_groups]
176
+ admin_group_names = admin_group_string.split(",")
177
+ admin_group_names.map! do |group|
178
+ (group.strip).capitalize
179
+ end
180
+
181
+ user_groups = Membership.where(:user_id => user.id)
182
+ user_group_names = user_groups.map do |membership|
183
+ membership.group.name
184
+ end
185
+ should_be_admin = admin_group_names & user_group_names
186
+ user.is_admin = !should_be_admin.empty?
187
+ end
188
+
189
+ end
190
+ end
@@ -0,0 +1,35 @@
1
+ require_dependency "concerto_saml_auth/application_controller"
2
+
3
+ module ConcertoSamlAuth
4
+ class OmniauthCallbackController < ApplicationController
5
+
6
+ # We will be receiving a POST request initiated by the identity provider.
7
+ # To check its authenticity, OneLogin SAML will check its signature.
8
+ # Therefore, we must skip the CSRF protection, since it interferes with
9
+ # normal operation (it disconnects us from the session, basically).
10
+ skip_before_action :verify_authenticity_token
11
+
12
+ def saml_auth
13
+ saml_hash = request.env["omniauth.auth"]
14
+ result = find_from_omniauth(saml_hash)
15
+
16
+ if !result
17
+ # Redirect showing flash notice with errors
18
+ redirect_to "/"
19
+ else
20
+ user = result[:user]
21
+ user_existed = result[:existed]
22
+ session["devise.user_attributes"] = user.attributes
23
+ sign_in user
24
+ if user_existed
25
+ flash[:notice] = "Signed in as #{user.first_name} #{user.last_name}"
26
+ redirect_to "/"
27
+ else
28
+ flash[:notice] = "Welcome to Concerto, #{user.first_name} #{user.last_name}! Have a look at the options"
29
+ redirect_to "/manage/users/#{user.id}/edit"
30
+ end
31
+ end
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,4 @@
1
+ module ConcertoSamlAuth
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1 @@
1
+ <%= link_to t('.sign_in'), root_url + 'auth/saml/' %>
@@ -0,0 +1,123 @@
1
+ require 'omniauth'
2
+ if ActiveRecord::Base.connection.table_exists? 'concerto_configs'
3
+ # Concerto Configs are created if they don't exist already
4
+ # these are used to initialize and configure omniauth-cas
5
+ # TODO: Finalize which settings are available
6
+ default_saml_idp_metadata = "https://example.com/auth/saml2/idp/metadata"
7
+ ConcertoConfig.make_concerto_config("saml_idp_metadata", default_saml_idp_metadata,
8
+ :value_type => "string",
9
+ :category => "SAML User Authentication",
10
+ :seq_no => 1,
11
+ :description =>"URL at which the Identity Provider's metadata can be found.")
12
+
13
+ ConcertoConfig.make_concerto_config("saml_issuer", "https://concerto.example.com/SAML2",
14
+ :value_type => "string",
15
+ :category => "SAML User Authentication",
16
+ :seq_no => 2,
17
+ :description => "A unique identifier used by this application to identify itself to the identity provider.")
18
+
19
+ ConcertoConfig.make_concerto_config("saml_uid_key", "uid",
20
+ :value_type => "string",
21
+ :category => "SAML User Authentication",
22
+ :seq_no => 3,
23
+ :description => "SAML field name containing user login names")
24
+
25
+ ConcertoConfig.make_concerto_config("saml_email_key", "email",
26
+ :value_type => "string",
27
+ :category => "SAML User Authentication",
28
+ :seq_no => 4,
29
+ :description => "SAML field name containing user email addresses. Leave blank if using email_suffix below")
30
+
31
+ ConcertoConfig.make_concerto_config("saml_first_name_key", "first_name",
32
+ :value_type => "string",
33
+ :category => "SAML User Authentication",
34
+ :seq_no => 6,
35
+ :description => "SAML field name containing first name")
36
+
37
+ ConcertoConfig.make_concerto_config("saml_last_name_key", "last_name",
38
+ :value_type => "string",
39
+ :category => "SAML User Authentication",
40
+ :seq_no => 7,
41
+ :description => "SAML field name containing last name")
42
+
43
+ ConcertoConfig.make_concerto_config("saml_member_of_key", "memberOf",
44
+ :value_type => "string",
45
+ :category => "SAML User Authentication",
46
+ :seq_no => 8,
47
+ :description => "SAML field name containing the memberOf attribute, as retrieved from LDAP")
48
+
49
+ ConcertoConfig.make_concerto_config("saml_member_of_filter", "OU=Access control",
50
+ :value_type => "string",
51
+ :category => "SAML User Authentication",
52
+ :seq_no => 9,
53
+ :description => "Filter determining which groups are made in Concerto. At least one of the assertions provided here, separated by comma, must match a memberOf field for it to be included.")
54
+
55
+ ConcertoConfig.make_concerto_config("saml_admin_groups", "administrator group",
56
+ :value_type => "string",
57
+ :category => "SAML User Authentication",
58
+ :seq_no => 10,
59
+ :description => "Common name of groups, separated by comma, whose members should be granted administrator permission in Concerto")
60
+
61
+ # Store omniauth config values from main application's ConcertoConfig
62
+ saml_idp_metadata = ConcertoConfig[:saml_idp_metadata]
63
+ if saml_idp_metadata.present? && saml_idp_metadata != default_saml_idp_metadata
64
+
65
+ idp_metadata_parser = OneLogin::RubySaml::IdpMetadataParser.new
66
+ begin
67
+ omniauth_config = idp_metadata_parser.parse_remote_to_hash(saml_idp_metadata)
68
+ rescue
69
+ Rails.logger.error "Failed to fetch or parse IDP metadata. Error message: #{$!}"
70
+ omniauth_config = {}
71
+ end
72
+ else
73
+ omniauth_config = {}
74
+ Rails.logger.warn "No URL (or default URL) defined for IDP metadata, SAML authentication will not be working."
75
+ end
76
+
77
+ request_attributes = []
78
+ if ConcertoConfig[:saml_email_key].present?
79
+ request_attributes.push({:name => ConcertoConfig[:saml_email_key], :friendly_name => "Email", :is_required => true})
80
+ end
81
+ if ConcertoConfig[:saml_first_name_key].present?
82
+ request_attributes.push({:name => ConcertoConfig[:saml_first_name_key], :friendly_name => "First Name", :is_required => true})
83
+ end
84
+ if ConcertoConfig[:saml_last_name_key].present?
85
+ request_attributes.push({:name => ConcertoConfig[:saml_last_name_key], :friendly_name => "Last Name", :is_required => true})
86
+ end
87
+ if ConcertoConfig[:saml_member_of_key].present?
88
+ request_attributes.push({:name => ConcertoConfig[:saml_member_of_key], :friendly_name => "Member Of", :is_required => true})
89
+ end
90
+
91
+ request_attributes.map! do |attr|
92
+ attr[:name_format] = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic"
93
+ attr
94
+ end
95
+
96
+ omniauth_config.merge!(
97
+ :issuer => ConcertoConfig[:saml_issuer],
98
+ :uid_attribute => ConcertoConfig[:saml_uid_key],
99
+ :attribute_statements => {
100
+ :email => [ConcertoConfig[:saml_email_key]],
101
+ :first_name => [ConcertoConfig[:saml_first_name_key]],
102
+ :last_name => [ConcertoConfig[:saml_last_name_key]],
103
+ },
104
+ :request_attributes => request_attributes,
105
+ :member_of_key => ConcertoConfig[:saml_member_of_key],
106
+ :member_of_filter => ConcertoConfig[:saml_member_of_filter],
107
+ :admin_groups => ConcertoConfig[:saml_admin_groups],
108
+ # :callback_url => "/auth/saml/callback"
109
+ )
110
+
111
+ Rails.logger.debug omniauth_config
112
+
113
+ # configure omniauth-cas gem based on specified yml configs
114
+ Rails.application.config.middleware.use OmniAuth::Builder do
115
+ provider :saml, omniauth_config
116
+ end
117
+
118
+ # save omniauth configuration for later use in application
119
+ # to reference any unique identifiers for extra CAS options
120
+ ConcertoSamlAuth::Engine.configure do
121
+ config.omniauth_config = omniauth_config
122
+ end
123
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ Concerto::Application.routes.draw do
2
+ post "/auth/saml/callback", :to => "concerto_saml_auth/omniauth_callback#saml_auth"
3
+ end
@@ -0,0 +1,31 @@
1
+ module ConcertoSamlAuth
2
+
3
+ require 'omniauth'
4
+ require 'omniauth-saml'
5
+ require 'concerto_identity'
6
+
7
+ class Engine < ::Rails::Engine
8
+ isolate_namespace ConcertoSamlAuth
9
+ engine_name 'concerto_saml_auth'
10
+
11
+ # Define plugin information for the Concerto application to read.
12
+ # Do not modify @plugin_info outside of this static configuration block.
13
+ def plugin_info(plugin_info_class)
14
+ @plugin_info ||= plugin_info_class.new do
15
+
16
+ # Add our concerto_saml_auth route to the main application
17
+ add_route("concerto_saml_auth", ConcertoSamlAuth::Engine)
18
+
19
+ # View hook to override Devise sign in links in the main application
20
+ add_view_hook "ApplicationController", :signin_hook,
21
+ :partial => "concerto_saml_auth/omniauth_saml/signin"
22
+
23
+ # Controller hook to supply a redirect route (example: non public Concerto instances)
24
+ add_controller_hook "ApplicationController", :auth_plugin, :before do
25
+ @auth_url = "/auth/saml"
26
+ end
27
+ end
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module ConcertoSamlAuth
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,4 @@
1
+ require "concerto_saml_auth/engine"
2
+
3
+ module ConcertoSamlAuth
4
+ end
@@ -0,0 +1,18 @@
1
+ namespace :concerto_saml_auth do
2
+ desc "Creates identities from existing user emails"
3
+ task :identity_from_email => :environment do
4
+ User.all.each do |u|
5
+ identity = ConcertoIdentity::Identity.new(
6
+ user_id: u.id,
7
+ external_id: u.email[/[^@]+/],
8
+ provider: "saml"
9
+ )
10
+
11
+ if identity.save
12
+ puts "Created Identity: #{identity.external_id} -> #{identity.user_id}"
13
+ else
14
+ puts "Error creating Identity for User #{identity.user_id}"
15
+ end
16
+ end
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: concerto_saml_auth
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Gabe Perez
8
+ - Thorben Dahl
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2017-07-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: omniauth-saml
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: concerto_identity
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ description: Authorize Concerto users with SAML
57
+ email:
58
+ - perez283@gmail.com
59
+ - thorben@thorbendahl.com
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - LICENSE
65
+ - README.md
66
+ - Rakefile
67
+ - app/assets/javascripts/concerto_saml_auth/application.js
68
+ - app/assets/stylesheets/concerto_saml_auth/application.css
69
+ - app/controllers/concerto_saml_auth/application_controller.rb
70
+ - app/controllers/concerto_saml_auth/omniauth_callback_controller.rb
71
+ - app/helpers/concerto_saml_auth/application_helper.rb
72
+ - app/views/concerto_saml_auth/omniauth_saml/_signin.html.erb
73
+ - config/initializers/omniauth.rb
74
+ - config/routes.rb
75
+ - lib/concerto_saml_auth.rb
76
+ - lib/concerto_saml_auth/engine.rb
77
+ - lib/concerto_saml_auth/version.rb
78
+ - lib/tasks/concerto_saml_auth_tasks.rake
79
+ homepage: http://www.concerto-signage.org
80
+ licenses:
81
+ - Apache-2.0
82
+ metadata: {}
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ requirements: []
98
+ rubyforge_project:
99
+ rubygems_version: 2.5.2
100
+ signing_key:
101
+ specification_version: 4
102
+ summary: Provides user authentication using SAML
103
+ test_files: []