omniauth-cul 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5da31c2f79868b1ffaa0b942b3c8c26bfed1911777d53c153ed4ecf2bcd2f289
4
+ data.tar.gz: 39590d04655b7260e5ff0423bb826abbf9500e7cd47617bbb679b8c23fa92fdd
5
+ SHA512:
6
+ metadata.gz: 85874e250cc849120dfa5869a8e78516bfc2269d0275b0e549cf755e4838a1e1be1197df01b8cb1cbbe79d9273904bf0254da6e5708a114577e2e055a7ec720c
7
+ data.tar.gz: 0b861025b96752b267ab4eaf78dad76aa6933c7341be2427884cdf62b82a04696be0956e90cc449ef2cc526335e2fbc80430223467cbf54cda9ce8fb01e9a388
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,13 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.6
3
+
4
+ Style/StringLiterals:
5
+ Enabled: true
6
+ EnforcedStyle: double_quotes
7
+
8
+ Style/StringLiteralsInInterpolation:
9
+ Enabled: true
10
+ EnforcedStyle: double_quotes
11
+
12
+ Layout/LineLength:
13
+ Max: 120
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Eric O
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,114 @@
1
+ # Cul::Omniauth
2
+
3
+ Cul::Omniauth is a gem that facilitates using Rails, [Devise](https://github.com/plataformatec/devise "Devise") and Omniauth with the [CAS offering from Columbia University IT](https://cuit.columbia.edu/cas-authentication "CUIT CAS Documentation").
4
+
5
+ At this time, this gem only supports Columbia University's CAS3 authentication endpoint (which provides user affiliation information), but support for additional auth mechanisms may be added later if needed.
6
+
7
+ ## Installation and setup
8
+
9
+ The instructions below assume that your Rails application's user model will be called "User".
10
+
11
+ 1. Add gem `devise` (>= 4.9) to your Gemfile.
12
+ 2. Follow the standard Devise setup instructions (https://github.com/heartcombo/devise). Recap:
13
+ 1. `rails generate devise:install`
14
+ 2. `rails generate devise User`
15
+ 3. `rails db:migrate`
16
+ 3. Add gem `omniauth` (>= 2.1) to your Gemfile.
17
+ 4. Add this gem, 'omniauth-cul', to your Gemfile.
18
+ 5. Run `bundle install`.
19
+ 6. In `/config/initializers/devise.rb`, add this:
20
+ ```
21
+ config.omniauth :cas, strategy_class: Omniauth::Cul::Strategies::Cas3Strategy
22
+ ```
23
+ (There may already be a config.omniauth section, and if so you can append this to the existing lines in that section.)
24
+ 7. Add a :uid column to the User model by running: `rails generate migration AddUidToUsers uid:string:uniq:index`
25
+ 8. In `/app/models/user.rb`, find the line where the `devise` method is called (usually with arguments like `:database_authenticatable`, `:registerable`, etc.).
26
+ - Minimally, you need to add these additional arguments to the end of the method call: `:omniauthable, omniauth_providers: [:cas]`
27
+ - In most cases though, you'll probably want to disable most of the modules and have only this:
28
+ ```
29
+ devise :database_authenticatable, :validatable, :omniauthable, omniauth_providers: [:cas]
30
+ ```
31
+ 9. In `/config/routes.rb`, find this line:
32
+ ```
33
+ devise_for :users
34
+ ```
35
+ And replace it with these lines:
36
+ ```
37
+ devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
38
+ ```
39
+ 10. Create a new file at `app/controllers/users/omniauth_callbacks_controller.rb` with the following content:
40
+ ```
41
+ require 'omniauth/cul'
42
+
43
+ class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
44
+ # Adding the line below so that if the auth endpoint POSTs to our cas endpoint, it won't
45
+ # be rejected by authenticity token verification.
46
+ # See https://github.com/omniauth/omniauth/wiki/FAQ#rails-session-is-clobbered-after-callback-on-developer-strategy
47
+ skip_before_action :verify_authenticity_token, only: :cas
48
+
49
+ def app_cas_callback_endpoint
50
+ "#{request.base_url}/users/auth/cas/callback"
51
+ end
52
+
53
+ # GET /users/auth/cas (go here to be redirected to the CAS login form)
54
+ def passthru
55
+ redirect_to Omniauth::Cul::Cas3.passthru_redirect_url(app_cas_callback_endpoint), allow_other_host: true
56
+ end
57
+
58
+ # GET /users/auth/cas/callback
59
+ def cas
60
+ user_id, affils = Omniauth::Cul::Cas3.validation_callback(request.params['ticket'], app_cas_callback_endpoint)
61
+
62
+ # Custom auth logic for your app goes here.
63
+ # The code below is provided as an example. If you want to use Omniauth::Cul::PermissionFileValidator,
64
+ # to validate see the later "Omniauth::Cul::PermissionFileValidator" section of this README.
65
+ #
66
+ # if Omniauth::Cul::PermissionFileValidator.permitted?(user_id, affils)
67
+ # user = User.find_by(uid: user_id) || User.create!(
68
+ # uid: user_id,
69
+ # email: "#{user_id}@columbia.edu"
70
+ # )
71
+ # sign_in_and_redirect user, event: :authentication # this will throw if @user is not activated
72
+ # else
73
+ # flash[:error] = 'Login attempt failed'
74
+ # redirect_to root_path
75
+ # end
76
+ end
77
+ end
78
+ ```
79
+
80
+ ## Omniauth::Cul::PermissionFileValidator - Permission validation with a user id list or affiliation list
81
+
82
+ One of the modules in this gem is `Omniauth::Cul::PermissionFileValidator`, which can be used like this:
83
+
84
+ ```
85
+ user_id = 'abc123'
86
+ affils = ['affil1']
87
+ if Omniauth::Cul::PermissionFileValidator.permitted?(user_id, affils)
88
+ # This block will run if your Rails app has a file at /config/permissions.yml that
89
+ # permits access for user 'abc123' OR any user with affiliation 'affil1'.
90
+ end
91
+ ```
92
+
93
+ In your Rails app, your permission.yml file should be located at /config/permissions.yml. For each environment, you may define allowed_user_ids and/or allowed_user_affils.
94
+
95
+ ```
96
+ # Permissions
97
+
98
+ all: &all
99
+ allowed_user_ids:
100
+ - abc123
101
+ - def123
102
+ - ghi123
103
+ allowed_user_affils:
104
+ - CUL_dpts-ldpd
105
+
106
+ development: *all
107
+ test: *all
108
+ ```
109
+
110
+ ## Development
111
+
112
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
113
+
114
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omniauth
4
+ module Cul
5
+ module Cas3
6
+ # For Columbia CAS 3 endpoint info, see: https://www.cuit.columbia.edu/cas-authentication
7
+
8
+ def self.passthru_redirect_url(app_cas_callback_endpoint)
9
+ 'https://cas.columbia.edu/cas/login?'\
10
+ "service=#{Rack::Utils.escape(app_cas_callback_endpoint)}"
11
+ end
12
+
13
+ def self.validation_callback(ticket, app_cas_callback_endpoint)
14
+ cas_ticket = ticket
15
+ validation_url = cas_validation_url(app_cas_callback_endpoint, cas_ticket)
16
+ validation_response = validate_ticket(validation_url, cas_ticket)
17
+
18
+ # We are always expecting an XML response
19
+ response_xml = Nokogiri::XML(validation_response)
20
+
21
+ user_id = user_id_from_response_xml(response_xml)
22
+ affils = affils_from_response_xml(response_xml)
23
+
24
+ [user_id, affils]
25
+ end
26
+
27
+ def self.cas_validation_url(app_cas_callback_endpoint, cas_ticket)
28
+ 'https://cas.columbia.edu/cas/p3/serviceValidate?'\
29
+ "service=#{Rack::Utils.escape(app_cas_callback_endpoint)}&"\
30
+ "ticket=#{cas_ticket}"
31
+ end
32
+
33
+ def self.validate_ticket(validation_url, cas_ticket)
34
+ uri = URI.parse(validation_url)
35
+ http = Net::HTTP.new(uri.host, uri.port)
36
+ http.use_ssl = true
37
+ # http.verify_mode = OpenSSL::SSL::VERIFY_NONE
38
+ validation_request = Net::HTTP::Get.new(uri.request_uri)
39
+ response = http.request(validation_request)
40
+ response.body
41
+ end
42
+
43
+ def self.user_id_from_response_xml(response_xml)
44
+ response_xml.xpath('/cas:serviceResponse/cas:authenticationSuccess/cas:user', 'cas' => 'http://www.yale.edu/tp/cas')&.first&.text
45
+ end
46
+
47
+ def self.affils_from_response_xml(response_xml)
48
+ response_xml.xpath('/cas:serviceResponse/cas:authenticationSuccess/cas:attributes/cas:affiliation', 'cas' => 'http://www.yale.edu/tp/cas')&.map(&:text)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omniauth
4
+ module Cul
5
+ module PermissionFileValidator
6
+ # For Columbia CAS 3 endpoint info, see: https://www.cuit.columbia.edu/cas-authentication
7
+
8
+ def self.permission_file_data
9
+ return @permission_file_data if @permission_file_data
10
+ @permission_file_data = {}
11
+ if defined?(Rails)
12
+ permission_file_path = Rails.root.join('config/permissions.yml')
13
+ # We'll use YAML loading logic similar to Rails 7, for older and newer psych gem compatibility
14
+ # https://github.com/rails/rails/blob/7-1-stable/activesupport/lib/active_support/encrypted_configuration.rb#L99
15
+ conf = YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load_file(permission_file_path) : YAML.load_file(permission_file_path)
16
+ @permission_file_data = conf[Rails.env] || {}
17
+ end
18
+
19
+ @permission_file_data
20
+ end
21
+
22
+ def self.allowed_user_ids
23
+ permission_file_data.fetch('allowed_user_ids', [])
24
+ end
25
+
26
+ def self.allowed_user_affils
27
+ permission_file_data.fetch('allowed_user_affils', [])
28
+ end
29
+
30
+ # Returns true if the given user_id OR affils match at least one of the rules defined in the
31
+ # permissions.yml config file. This method will always return false if user_id is nil.
32
+ def self.permitted?(user_id, affils)
33
+ return false if user_id.nil?
34
+ return true if allowed_user_ids.include?(user_id)
35
+ return true if affils.respond_to?(:include?) && allowed_user_affils.include?(affils)
36
+ return false
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,9 @@
1
+ module Omniauth
2
+ module Cul
3
+ module Strategies
4
+ class Cas3Strategy
5
+ include OmniAuth::Strategy
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omniauth
4
+ module Cul
5
+ VERSION = "0.2.0"
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'cul/version'
4
+ require_relative 'cul/cas_3'
5
+ require_relative 'cul/permission_file_validator'
6
+ require_relative 'cul/strategies/cas_3_strategy'
7
+
8
+ module Omniauth
9
+ module Cul
10
+ class Error < StandardError; end
11
+ # Your code goes here...
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ module Omniauth
2
+ module Cul
3
+ VERSION: String
4
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
5
+ end
6
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: omniauth-cul
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Eric O
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-01-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: devise
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.9'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '4.9'
27
+ - !ruby/object:Gem::Dependency
28
+ name: omniauth
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ description:
42
+ email:
43
+ - elo2112@columbia.edu
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".rspec"
49
+ - ".rubocop.yml"
50
+ - LICENSE.txt
51
+ - README.md
52
+ - Rakefile
53
+ - lib/omniauth/cul.rb
54
+ - lib/omniauth/cul/cas_3.rb
55
+ - lib/omniauth/cul/permission_file_validator.rb
56
+ - lib/omniauth/cul/strategies/cas_3_strategy.rb
57
+ - lib/omniauth/cul/version.rb
58
+ - sig/omniauth/cul.rbs
59
+ homepage: https://github.com/cul/omniauth-cul
60
+ licenses:
61
+ - MIT
62
+ metadata:
63
+ homepage_uri: https://github.com/cul/omniauth-cul
64
+ source_code_uri: https://github.com/cul/omniauth-cul
65
+ post_install_message:
66
+ rdoc_options: []
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: 2.7.5
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ requirements: []
80
+ rubygems_version: 3.4.10
81
+ signing_key:
82
+ specification_version: 4
83
+ summary: A devise omniauth adapter for Rails apps, using Columbia University authentication.
84
+ test_files: []