omniauth-cul 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +13 -0
- data/LICENSE.txt +21 -0
- data/README.md +114 -0
- data/Rakefile +12 -0
- data/lib/omniauth/cul/cas_3.rb +52 -0
- data/lib/omniauth/cul/permission_file_validator.rb +40 -0
- data/lib/omniauth/cul/strategies/cas_3_strategy.rb +9 -0
- data/lib/omniauth/cul/version.rb +7 -0
- data/lib/omniauth/cul.rb +13 -0
- data/sig/omniauth/cul.rbs +6 -0
- metadata +84 -0
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
data/.rubocop.yml
ADDED
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,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
|
data/lib/omniauth/cul.rb
ADDED
@@ -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
|
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: []
|