rack-cas-rails 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +181 -54
- data/lib/rack_cas_rails/application.rb +22 -0
- data/lib/{rack-cas-rails → rack_cas_rails}/controllers.rb +7 -2
- data/lib/{rack-cas-rails → rack_cas_rails}/version.rb +1 -1
- data/lib/rack_cas_rails.rb +3 -0
- metadata +47 -4
- data/lib/rack-cas-rails.rb +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b7d484d2b59603bbedf3a28c4917a463edf86c08
|
4
|
+
data.tar.gz: 7bbe3d6ae9fdbf53eef3fcb523c1d019d1afe1f1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 26517014d8fc90148db433d49e79084aa83fb2d7697174e1e9b201b5d98eae5d2e04ce784b659eb68a2d3fecf860241aa57e4aca33d2d1fd30c2d6d7f7c7ccbf
|
7
|
+
data.tar.gz: 2413da86e88601ae8995cb1813b4d429a8c3f1dfa0ae9b0f836d5e95240c9e34b1d48ee7a80d454cd2a1161be6586eb2971e8fce19da26e3847e6cd4dd1e2c24
|
data/README.md
CHANGED
@@ -1,104 +1,223 @@
|
|
1
1
|
# rack-cas-rails
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
[rbCAS/CASinoApp](https://github.com/rbcas/casinoapp) is a great single sign-on authentication server, and
|
4
|
+
[biola/rack-cas](https://github.com/biola/rack-cas) provides a simple means to integrate with it. However, these two things
|
5
|
+
coupled with your Rails application do not a **single sign-on enabled application** make. That is, there are still some bits
|
6
|
+
missing.
|
6
7
|
|
7
|
-
This gem aims to
|
8
|
+
This gem aims to provide some of the bits to close the gap.
|
8
9
|
|
9
10
|
## Installation
|
10
11
|
|
11
|
-
Add the following
|
12
|
+
Add the following to your Rails application's Gemfile:
|
12
13
|
|
13
14
|
```ruby
|
14
15
|
gem "rack-cas-rails"
|
15
16
|
```
|
16
17
|
|
17
|
-
Then
|
18
|
+
Then run
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
bundle install
|
22
|
+
```
|
18
23
|
|
19
24
|
## Requirements
|
20
25
|
|
21
26
|
The rack-cas-rails gem relies on the following:
|
22
27
|
|
23
|
-
* A
|
28
|
+
* A working installation of [CASinoApp](http://rbcas.com), although theoretically it should work with any CAS-compliant server
|
24
29
|
* [rack-cas](https://github.com/biola/rack-cas)
|
25
30
|
* [rails](http://rubyonrails.org/)
|
26
31
|
|
32
|
+
Having access to a working CAS-compliant server is a pre-requisite. [CASinoApp](http://rbcas.com) is a simple one to set up and
|
33
|
+
use, especially if you go with the ***directly on your server*** option. Whiichever CAS server you go with, you'll need to
|
34
|
+
know the password of at least one login for testing purposes.
|
35
|
+
|
36
|
+
### Disclaimer
|
37
|
+
|
38
|
+
I don't have access to any other CAS servers except an instance of CASinoApp I have installed and configured. So I have
|
39
|
+
only ever developed and tested against it. If you are able to try it against others, please let me know how well it works.
|
40
|
+
|
27
41
|
## Basic Usage
|
28
42
|
|
29
|
-
|
30
|
-
server you are integrating with by pointing out its base URL,
|
43
|
+
Now that you have access to a functioning CAS-compliant server, the next thing you need to do is to make your ```Rails::Application```
|
44
|
+
subclass aware of the server you are integrating with by pointing out its base URL, as shown here.
|
45
|
+
|
46
|
+
Note that setting the ```@cas_server_url``` variable is important as the ```login_url``` helper will make use of it.
|
31
47
|
|
32
48
|
```ruby
|
49
|
+
# config/application.rb
|
50
|
+
|
51
|
+
require "rack-cas"
|
33
52
|
module MyGreatApplication
|
34
53
|
class Application < Rails::Application
|
35
54
|
# ...
|
36
|
-
# URL of CAS server
|
37
|
-
|
55
|
+
# Root URL of the CAS server
|
56
|
+
@cas_server_url = "https://sso.example.org/"
|
57
|
+
config.rack_cas.server_url = @cas_server_url
|
38
58
|
end
|
39
59
|
end
|
40
60
|
```
|
41
61
|
|
42
|
-
In the simplest
|
43
|
-
he can do nothing. To do so, add the following ```before_action``` callback to your ApplicationController
|
44
|
-
(file ```app/controllers/application_ronctoller.rb```):
|
62
|
+
In the simplest case, you'll want your entire application protected by authentication. That is, unless a user has authenticated,
|
63
|
+
he can do nothing. To do so, add the following ```before_action``` callback to your ```ApplicationController```:
|
45
64
|
|
46
65
|
```ruby
|
66
|
+
# app/controllers/application_ronctoller.rb
|
67
|
+
|
68
|
+
require "rack_cas_rails"
|
47
69
|
class ApplicationController < ActionController::Base
|
48
|
-
#
|
70
|
+
# Prevent CSRF attacks by raising an exception.
|
71
|
+
# For APIs, you may want to use :null_session instead.
|
72
|
+
protect_from_forgery with: :exception
|
49
73
|
before_action :authenticate!
|
50
|
-
# ...
|
51
74
|
end
|
52
75
|
```
|
53
76
|
|
54
|
-
The ```authenticate!```
|
55
|
-
Otherwise, it will render the ```public/401.html``` file as well as return a HTTP status of 401.
|
77
|
+
The ```authenticate!``` helper will check to see if a browser session is authenticated. If it is, controller execution will continue.
|
78
|
+
Otherwise, it will render the ```public/401.html``` file if one exists, as well as return a HTTP status of 401.
|
56
79
|
|
57
|
-
|
58
|
-
|
80
|
+
At this point, if you fire up your application and browse to access any view of any controller subclassed from
|
81
|
+
```ApplicationController```, the browser will get re-directed to the CAS server's log-in page.
|
59
82
|
|
60
83
|
## Helper Methods
|
61
84
|
|
62
|
-
The rack-cas-rails gem also
|
85
|
+
The rack-cas-rails gem also adds some helper methods:
|
86
|
+
|
87
|
+
* authenticate!
|
88
|
+
* authenticated?
|
89
|
+
* login_url
|
90
|
+
* logout_url
|
91
|
+
|
92
|
+
You have already seen ```authenticate!``` at work. The ```authenticated?``` helper allows your application to determine whether
|
93
|
+
a browser is authenticated or not and take appropriate action. When invoked, the latter two helpers will return the
|
94
|
+
CAS-integrated login and log out URLs, respectively. They, in turn, enable you to implement *partial authentication*.
|
95
|
+
|
96
|
+
## Partial Authentication
|
63
97
|
|
64
|
-
|
65
|
-
|
98
|
+
In this case, only certain portions of your application requires authentication. For example, perhaps actions that are
|
99
|
+
*read-only* need not be protected by authentication. To do this, change your ```ApplicationController``` as follows:
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
# app/controllers/application_ronctoller.rb
|
103
|
+
|
104
|
+
require "rack_cas_rails"
|
105
|
+
class ApplicationController < ActionController::Base
|
106
|
+
# Prevent CSRF attacks by raising an exception.
|
107
|
+
# For APIs, you may want to use :null_session instead.
|
108
|
+
protect_from_forgery with: :exception
|
109
|
+
before_action :authenticate!, except: [:index, :show]
|
110
|
+
end
|
111
|
+
```
|
112
|
+
|
113
|
+
Restart your application and browse to a *read-only* endpoint like ```/index``` or ```/show```, and you will not be re-directed
|
114
|
+
to the CAS log-in page. But if you browse to other endpoints like ```/new```, you will be re-directed and prompted to
|
115
|
+
authenticate.
|
116
|
+
|
117
|
+
Go back and look at the read-only endpoint. It would be nice to have some indication telling a user whether he's logged in or not.
|
118
|
+
So, open up your application layout and add a ```<div>``` container that will behave differently bepending on the authentication
|
119
|
+
status of a browser session.
|
120
|
+
|
121
|
+
```erb
|
122
|
+
<!-- views/layouts/application.html.erb -->
|
123
|
+
|
124
|
+
<!DOCTYPE html>
|
125
|
+
<html>
|
126
|
+
<head>
|
127
|
+
<title>MyGreatApplication</title>
|
128
|
+
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
|
129
|
+
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
|
130
|
+
<%= csrf_meta_tags %>
|
131
|
+
</head>
|
132
|
+
<body>
|
133
|
+
<div id="header">
|
134
|
+
<% if authenticated? %>
|
135
|
+
<span>You are logged in.</span>
|
136
|
+
<span style="float:right"><%= link_to "Logout", logout_url %></span>
|
137
|
+
<% else %>
|
138
|
+
<span>You are not logged in.</span>
|
139
|
+
<span style="float:right"><%= link_to "Login", login_url %></span>
|
140
|
+
<% end %>
|
141
|
+
</div>
|
142
|
+
<hr />
|
143
|
+
<div>
|
144
|
+
<%= yield %>
|
145
|
+
</div>
|
146
|
+
</body>
|
147
|
+
</html>
|
148
|
+
```
|
66
149
|
|
67
|
-
|
150
|
+
Refresh your browser. This time you'll see that you're not logged in, but you are also given a login URL. Click on it, and you'll
|
151
|
+
be prompted to log-in once again.
|
68
152
|
|
69
153
|
## What Is Still Missing
|
70
154
|
|
71
|
-
|
72
|
-
|
155
|
+
However, the basic authentication scheme we have cooked up is still incomplete. Namely:
|
156
|
+
|
157
|
+
* What credentails should a user use to login, and how does your application verify it?
|
158
|
+
* Once a user has authenticated, how does your application know about that user?
|
159
|
+
|
160
|
+
The first point is that your application doesn't have to worry about it, since that is the whole point of CAS (and single sign-on).
|
161
|
+
Once your CAS server is set up, any application you write and integrate with it won't have to worry about it. Your CAS
|
162
|
+
server will take care of it for you.
|
163
|
+
|
164
|
+
The second point, however,requires some explanation and experimentation...
|
73
165
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
166
|
+
Once a user has authenticated, the [rack-cas](https://github.com/biola/rack-cas) gem will insert some information about
|
167
|
+
that user into your application's session for it to retrieve. Your application should then take this information, usually
|
168
|
+
in the form of a username, and look up information about that user. Based on the information available, your application can
|
169
|
+
then implement additional features such as authorziation (not covered here).
|
78
170
|
|
79
|
-
|
80
|
-
|
81
|
-
|
171
|
+
Ideally, your application should use the same data repository as your CAS server to look up user information. That repository can
|
172
|
+
be a SQL database table, some LDAP server, or any number of things. But for now, we can fake it.
|
173
|
+
|
174
|
+
Go ahead and create a scaffold around a Person model (or any other name you'd like to use), like so:
|
175
|
+
|
176
|
+
```
|
177
|
+
$ rails generate scaffold person name:string age:integer
|
178
|
+
$ rake db:migrate
|
179
|
+
```
|
180
|
+
|
181
|
+
Populate the ```people``` table with at least one row where the ```name``` column has the same value as one of the users your CAS
|
182
|
+
server knows about and you know the password of. For example, let's use "jsmith":
|
183
|
+
|
184
|
+
```
|
185
|
+
$ rails console
|
186
|
+
Loading development environment (Rails 4.2.0)
|
187
|
+
2.2.0 :001 > person = Person.new(name: "jsmith", age: 123)
|
188
|
+
=> #<Person id: nil, name: "jsmith", age: 123, created_at: nil, updated_at: nil>
|
189
|
+
2.2.0 :002 > person.save!
|
190
|
+
(0.2ms) begin transaction
|
191
|
+
SQL (33.5ms) INSERT INTO "people" ("name", "age", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "jsmith"],
|
192
|
+
["age", 123], ["created_at", "2015-02-16 02:27:18.121111"], ["updated_at", "2015-02-16 02:27:18.121111"]]
|
193
|
+
(1.5ms) commit transaction
|
194
|
+
=> true
|
195
|
+
2.2.0 :003 > quit
|
196
|
+
```
|
197
|
+
|
198
|
+
Now, let's add a helper named ```current_user``` (or any other name you like) to your application:
|
82
199
|
|
83
200
|
```ruby
|
84
|
-
|
201
|
+
# app/controllers/application_ronctoller.rb
|
85
202
|
|
86
|
-
|
87
|
-
|
203
|
+
require "rack_cas_rails"
|
204
|
+
class ApplicationController < ActionController::Base
|
205
|
+
# Prevent CSRF attacks by raising an exception.
|
206
|
+
# For APIs, you may want to use :null_session instead.
|
207
|
+
protect_from_forgery with: :exception
|
208
|
+
before_action :authenticate!, except: [:index, :show]
|
88
209
|
def current_user
|
89
|
-
|
210
|
+
authenticated? ? Person.find_by_name(request.session["cas"]["user"]) : nil
|
90
211
|
end
|
91
|
-
|
92
212
|
helper_method :current_user
|
93
|
-
|
94
213
|
end
|
95
214
|
```
|
96
215
|
|
97
|
-
|
98
|
-
|
99
|
-
Lastly, change your ```views/layouts/application.html.erb``` to be as follows:
|
216
|
+
Next, change your layout to be as follows:
|
100
217
|
|
101
218
|
```erb
|
219
|
+
<!-- views/layouts/application.html.erb -->
|
220
|
+
|
102
221
|
<!DOCTYPE html>
|
103
222
|
<html>
|
104
223
|
<head>
|
@@ -108,12 +227,13 @@ Lastly, change your ```views/layouts/application.html.erb``` to be as follows:
|
|
108
227
|
<%= csrf_meta_tags %>
|
109
228
|
</head>
|
110
229
|
<body>
|
111
|
-
<
|
230
|
+
<div id="header">
|
112
231
|
<% if authenticated? %>
|
113
|
-
<span>
|
232
|
+
<span>You are logged in as <%= current_user.name %>.</span>
|
114
233
|
<span style="float:right"><%= link_to "Logout", logout_url %></span>
|
115
234
|
<% else %>
|
116
|
-
<span
|
235
|
+
<span>You are not logged in.</span>
|
236
|
+
<span style="float:right"><%= link_to "Login", login_url %></span>
|
117
237
|
<% end %>
|
118
238
|
</div>
|
119
239
|
<hr />
|
@@ -124,20 +244,27 @@ Lastly, change your ```views/layouts/application.html.erb``` to be as follows:
|
|
124
244
|
</html>
|
125
245
|
```
|
126
246
|
|
247
|
+
Restart your application again, and visit an ```/index``` endpoint. Click the __Login__ link, and authenticate using "jsmith"
|
248
|
+
(or whichever user you chose) and the correct password. Once authenticated, you'll be re-directed back to the original page.
|
249
|
+
This time, you are shown whom you are logged in as. Now visit a ```/new``` endpoint, and you won't be prompted to authenticate
|
250
|
+
again, until you click the __Logout__ link or restart your browser.
|
251
|
+
|
127
252
|
## Summary
|
128
253
|
|
129
|
-
|
254
|
+
With rack-cas-rails, you can integrate your Rails application with CASinoApp or another CAS-compliant server for
|
255
|
+
authentication by making these changes in it:
|
130
256
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
257
|
+
1. Your Rails::Application subclass (in config/application.rb)
|
258
|
+
2. Your ApplicationController class (in app/controllers/application_controller.rb)
|
259
|
+
3. Your layout template (in app/views/layouts/application.html.erb)
|
260
|
+
4. Add a model (or some other means) by which you can retrieve information about the currently logged in user
|
135
261
|
|
136
|
-
|
262
|
+
With these changes in place, you can expect your application to exhibit the following behavior:
|
137
263
|
|
138
|
-
|
139
|
-
|
140
|
-
|
264
|
+
* When you browse to any protected endpoint within your application using a fresh session, you'll be re-directed to the sign-in page
|
265
|
+
* After you authenticate, you'll be re-directed back to the page you browsed to, after which you'll have access to all endpoints
|
266
|
+
* When you click the __Logout__ link or restart your browser, your session will end; and should you now attempt to access
|
267
|
+
a protected enpoint, you'll be prompted to log in once again
|
141
268
|
|
142
269
|
## Credits
|
143
270
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+
##
|
2
|
+
# Augments the Rails application class.
|
3
|
+
|
4
|
+
class Rails::Application < Rails::Engine
|
5
|
+
|
6
|
+
##
|
7
|
+
# Gives the Rails::Application class a read-only class attribute to point to the CAS server URL. The URL in turn is then
|
8
|
+
# settable using @cas_server_url at the class level.
|
9
|
+
|
10
|
+
class << self
|
11
|
+
attr_reader :cas_server_url
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# Gets the CAS server root URL. Provides a convenience method at the instance level to fetch it.
|
16
|
+
# @return [String] Cas server's root URL.
|
17
|
+
|
18
|
+
def cas_server_url
|
19
|
+
self.class.cas_server_url
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -10,7 +10,12 @@ class ApplicationController < ActionController::Base
|
|
10
10
|
# When invoked, will force authenticate. Most likely to be invoked as a before_action.
|
11
11
|
|
12
12
|
def authenticate!
|
13
|
-
authenticated?
|
13
|
+
return if authenticated?
|
14
|
+
if File.exists?("public/401.html")
|
15
|
+
render(:file => "public/401.html", :status => :unauthorized)
|
16
|
+
else
|
17
|
+
render(:plain => "Unauthorized!", :status => :unauthorized)
|
18
|
+
end
|
14
19
|
end
|
15
20
|
|
16
21
|
##
|
@@ -27,7 +32,7 @@ class ApplicationController < ActionController::Base
|
|
27
32
|
# @return [String] The CAS login URL.
|
28
33
|
|
29
34
|
def login_url(service_url=request.url)
|
30
|
-
url = URI(Rails.application.
|
35
|
+
url = URI(Rails.application.cas_server_url)
|
31
36
|
url.path = "/login"
|
32
37
|
url.query = "service=#{service_url || request.url}"
|
33
38
|
url.to_s
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-cas-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Brazil
|
@@ -44,6 +44,48 @@ dependencies:
|
|
44
44
|
- - ">="
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: 4.2.0
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: byebug
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: sqlite3
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: yard
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
47
89
|
description: Provides the integration glue between a Rails application and biola/rack-cas
|
48
90
|
so that a CAS-compliant server (only tested with CASinoApp) can be used for authentication
|
49
91
|
by the application.
|
@@ -54,9 +96,10 @@ extra_rdoc_files: []
|
|
54
96
|
files:
|
55
97
|
- LICENSE
|
56
98
|
- README.md
|
57
|
-
- lib/
|
58
|
-
- lib/
|
59
|
-
- lib/
|
99
|
+
- lib/rack_cas_rails.rb
|
100
|
+
- lib/rack_cas_rails/application.rb
|
101
|
+
- lib/rack_cas_rails/controllers.rb
|
102
|
+
- lib/rack_cas_rails/version.rb
|
60
103
|
homepage: https://github.com/bitaxis/rack-cas-rails.git
|
61
104
|
licenses:
|
62
105
|
- MIT
|
data/lib/rack-cas-rails.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require "rack-cas-rails/controllers"
|