devise_ticketable 0.0.1
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.
- data/.gitignore +12 -0
- data/LICENSE +20 -0
- data/README.md +73 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/devise_ticketable.gemspec +55 -0
- data/lib/devise_ticketable.rb +22 -0
- data/lib/devise_ticketable/hooks/ticketable.rb +30 -0
- data/lib/devise_ticketable/model.rb +101 -0
- data/test/helper.rb +10 -0
- data/test/test_devise_ticketable.rb +7 -0
- metadata +92 -0
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Morton Jonuschat
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# devise_ticketable
|
2
|
+
|
3
|
+
Adds support to [devise](http://github.com/plataformatec/devise) for acting as a single sign on server
|
4
|
+
using [mod\_auth\_tkt](http://www.openfusion.com.au/labs/mod_auth_tkt/) for the [Apache HTTP Server](http://httpd.apache.org/)
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Rails 2.3 - add the following to your list of gems
|
9
|
+
|
10
|
+
config.gem 'devise_ticketable'
|
11
|
+
|
12
|
+
Rails 3 - add the following to your Gemfile
|
13
|
+
|
14
|
+
gem 'devise_ticketable'
|
15
|
+
|
16
|
+
## Configuration
|
17
|
+
|
18
|
+
devise_ticketable add a few configuration options to devise.
|
19
|
+
|
20
|
+
1. The secret used to generate cookies. Set to empty string by default. Should be set to some long and random
|
21
|
+
string comparable to the Rails cookie secret. This value needs to mach your webserver configuration!
|
22
|
+
|
23
|
+
config.auth\_tkt\_domain = secret
|
24
|
+
|
25
|
+
|
26
|
+
1. The domain for which the cookie is valid. Not set by default. Setting this to something like '.example.com'
|
27
|
+
allows single sign on across multiple subdomains
|
28
|
+
|
29
|
+
config.auth\_tkt\_domain = ''
|
30
|
+
|
31
|
+
1. Optionally do a Base64 encode of the cookie data. Not enabled by default.
|
32
|
+
|
33
|
+
config.auth\_tkt\_encode = false
|
34
|
+
|
35
|
+
1. Ignore the remote ip address when generating or validating the ticket. Not enabled by default.
|
36
|
+
|
37
|
+
config.auth\_tkt\_ignore\_ip = false
|
38
|
+
|
39
|
+
## Accessors / Model attributes
|
40
|
+
|
41
|
+
devise_ticketable makes use of a few optional but recommended accessors on your user model.
|
42
|
+
|
43
|
+
1. :auth\_tkt\_user
|
44
|
+
|
45
|
+
Define this so that it returns the username you might later use to grant access
|
46
|
+
|
47
|
+
1. :auth\_tkt\_user\_data
|
48
|
+
|
49
|
+
Can be used to return payload data that mod\_auth\_tkt may use
|
50
|
+
|
51
|
+
1. :auth\_tkt\_token\_list
|
52
|
+
|
53
|
+
Should return a list of comma separated tokens can be used for authentication purposes by mod\_auth\_tkt.
|
54
|
+
Possible uses include returning group memberships or roles.
|
55
|
+
|
56
|
+
## Limitations
|
57
|
+
|
58
|
+
Currently the cookie name is hardcoded to *auth_tkt*. As there is no documentation available for mod\_auth\_tkt that suggests
|
59
|
+
that the cookie name is configurable this doesn't pose any serious problems.
|
60
|
+
|
61
|
+
## Note on Patches/Pull Requests
|
62
|
+
|
63
|
+
* Fork the project.
|
64
|
+
* Make your feature addition or bug fix.
|
65
|
+
* Add tests for it. This is important so I don't break it in a
|
66
|
+
future version unintentionally.
|
67
|
+
* Commit, do not mess with rakefile, version, or history.
|
68
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
69
|
+
* Send me a pull request. Bonus points for topic branches.
|
70
|
+
|
71
|
+
## Copyright
|
72
|
+
|
73
|
+
Copyright (c) 2010 Morton Jonuschat. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "devise_ticketable"
|
8
|
+
gem.summary = %Q{Add support to devise for acting as a SSO server using mod_auth_tkt for apache }
|
9
|
+
gem.description = %Q{Adding device_ticketable to your devise implementaton will integrate it with mod_auth_tkt for the Apache HTTP server by setting/destroying the necessary auth_tkt cookie}
|
10
|
+
gem.email = "yabawock@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/yabawock/devise_ticketable"
|
12
|
+
gem.authors = ["Morton Jonuschat"]
|
13
|
+
gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
+
end
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'rake/testtask'
|
22
|
+
Rake::TestTask.new(:test) do |test|
|
23
|
+
test.libs << 'lib' << 'test'
|
24
|
+
test.pattern = 'test/**/test_*.rb'
|
25
|
+
test.verbose = true
|
26
|
+
end
|
27
|
+
|
28
|
+
begin
|
29
|
+
require 'rcov/rcovtask'
|
30
|
+
Rcov::RcovTask.new do |test|
|
31
|
+
test.libs << 'test'
|
32
|
+
test.pattern = 'test/**/test_*.rb'
|
33
|
+
test.verbose = true
|
34
|
+
end
|
35
|
+
rescue LoadError
|
36
|
+
task :rcov do
|
37
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
task :test => :check_dependencies
|
42
|
+
|
43
|
+
task :default => :test
|
44
|
+
|
45
|
+
require 'rake/rdoctask'
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
47
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
48
|
+
|
49
|
+
rdoc.rdoc_dir = 'rdoc'
|
50
|
+
rdoc.title = "devise_ticketable #{version}"
|
51
|
+
rdoc.rdoc_files.include('README*')
|
52
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
53
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{devise_ticketable}
|
8
|
+
s.version = "0.0.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Morton Jonuschat"]
|
12
|
+
s.date = %q{2010-07-30}
|
13
|
+
s.description = %q{Adding device_ticketable to your devise implementaton will integrate it with mod_auth_tkt for the Apache HTTP server by setting/destroying the necessary auth_tkt cookie}
|
14
|
+
s.email = %q{yabawock@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.md"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".gitignore",
|
21
|
+
"LICENSE",
|
22
|
+
"README.md",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"devise_ticketable.gemspec",
|
26
|
+
"lib/devise_ticketable.rb",
|
27
|
+
"lib/devise_ticketable/hooks/ticketable.rb",
|
28
|
+
"lib/devise_ticketable/model.rb",
|
29
|
+
"test/helper.rb",
|
30
|
+
"test/test_devise_ticketable.rb"
|
31
|
+
]
|
32
|
+
s.homepage = %q{http://github.com/yabawock/devise_ticketable}
|
33
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
34
|
+
s.require_paths = ["lib"]
|
35
|
+
s.rubygems_version = %q{1.3.7}
|
36
|
+
s.summary = %q{Add support to devise for acting as a SSO server using mod_auth_tkt for apache}
|
37
|
+
s.test_files = [
|
38
|
+
"test/helper.rb",
|
39
|
+
"test/test_devise_ticketable.rb"
|
40
|
+
]
|
41
|
+
|
42
|
+
if s.respond_to? :specification_version then
|
43
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
44
|
+
s.specification_version = 3
|
45
|
+
|
46
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
47
|
+
s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
48
|
+
else
|
49
|
+
s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
50
|
+
end
|
51
|
+
else
|
52
|
+
s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Devise.add_module :ticketable, :model => 'devise_ticketable/model'
|
2
|
+
|
3
|
+
module Devise
|
4
|
+
# Custom domain for auth_tkt_cookies. Not set by default
|
5
|
+
mattr_accessor :auth_tkt_domain
|
6
|
+
@@auth_tkt_domain = false
|
7
|
+
|
8
|
+
# Base64 encode the cookie data. Not set by default
|
9
|
+
mattr_accessor :auth_tkt_encode
|
10
|
+
@@auth_tkt_encode = false
|
11
|
+
|
12
|
+
# Do not check the remote ip address. Not set by default
|
13
|
+
mattr_accessor :auth_tkt_ignore_ip
|
14
|
+
@@auth_tkt_ignore_ip = false
|
15
|
+
|
16
|
+
# Define the secret used to generate cookies. Not set by default
|
17
|
+
mattr_accessor :auth_tkt_secret
|
18
|
+
@@auth_tkt_secret = ''
|
19
|
+
end
|
20
|
+
|
21
|
+
#module DeviseTicketable
|
22
|
+
#end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Before the user gets logged out we destroy the mod_auth_tkt cookie
|
2
|
+
#
|
3
|
+
# This is only triggered when the user is explicitly set (with set_user)
|
4
|
+
# and on authentication. Retrieving the user from session (:fetch) does
|
5
|
+
# not trigger it.
|
6
|
+
|
7
|
+
Warden::Manager.before_logout do |record, warden, opts|
|
8
|
+
if record.respond_to?(:destroy_auth_tkt_cookie!)
|
9
|
+
cookie_data = record.destroy_auth_tkt_cookie!
|
10
|
+
warden.cookies[:auth_tkt] = cookie_data
|
11
|
+
warden.cookies.delete(:auth_tkt)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# After the user gets logged in we set the mod_auth_tkt cookie
|
16
|
+
#
|
17
|
+
# This callback is triggered the first time one of those three
|
18
|
+
# events happens during a request: :authentication, :fetch
|
19
|
+
# (from session) and :set_user (when manually set)
|
20
|
+
|
21
|
+
Warden::Manager.after_authentication do |record, warden, opts|
|
22
|
+
if record.respond_to?(:get_auth_tkt_cookie!)
|
23
|
+
options = {}
|
24
|
+
options[:user] = record.auth_tkt_user if record.respond_to?(:auth_tkt_user)
|
25
|
+
options[:user_data] = record.auth_tkt_user_data if record.respond_to?(:auth_tkt_user_data)
|
26
|
+
options[:token_list] = record.auth_tkt_token_list if record.respond_to?(:auth_tkt_token_list)
|
27
|
+
|
28
|
+
warden.cookies[:auth_tkt] = record.get_auth_tkt_cookie!(options, warden.request)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'devise_ticketable/hooks/ticketable'
|
2
|
+
|
3
|
+
module Devise
|
4
|
+
module Models
|
5
|
+
# This module generates cookie tickets compatible
|
6
|
+
# with the "mod_auth_tkt" apache module.
|
7
|
+
#
|
8
|
+
# Based on work by: MESO Web Scapes, Sascha Hanssen
|
9
|
+
# www.meso.net/auth_tkt_rails | hanssen@meso.net
|
10
|
+
|
11
|
+
module Ticketable
|
12
|
+
extend ActiveSupport::Concern
|
13
|
+
|
14
|
+
# destroys the auth_tkt cookie to sign out the current user
|
15
|
+
def destroy_auth_tkt_cookie!
|
16
|
+
# reset ticket value of cookie, safeguard if deleting the cookie fails
|
17
|
+
{:value => '', :expire => Time.at(0), :domain => self.class.auth_tkt_domain}
|
18
|
+
end
|
19
|
+
|
20
|
+
# sets the auth_tkt cookie, returns the signed cookie string
|
21
|
+
def get_auth_tkt_cookie!(options, request)
|
22
|
+
# get signed cookie string
|
23
|
+
tkt_hash = get_tkt_hash(options, request)
|
24
|
+
|
25
|
+
cookie_data = {:value => tkt_hash}
|
26
|
+
|
27
|
+
# set domain for cookie, if wanted
|
28
|
+
cookie_data[:domain] = self.class.auth_tkt_domain if self.class.auth_tkt_domain
|
29
|
+
|
30
|
+
# return signed cookie
|
31
|
+
cookie_data
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
# returns a string that contains the signed cookie content
|
37
|
+
def get_tkt_hash(user_options, request)
|
38
|
+
options = {
|
39
|
+
:user => '',
|
40
|
+
:token_list => '',
|
41
|
+
:user_data => '',
|
42
|
+
:encode => self.class.auth_tkt_encode,
|
43
|
+
:ignore_ip => self.class.auth_tkt_ignore_ip
|
44
|
+
}.merge(user_options)
|
45
|
+
|
46
|
+
# set timestamp and binary string for timestamp and ip packed together
|
47
|
+
timestamp = Time.now.to_i
|
48
|
+
ip_address = options[:ignore_ip] ? '0.0.0.0' : request.remote_ip
|
49
|
+
ip_timestamp = [ip2long(ip_address), timestamp].pack("NN")
|
50
|
+
|
51
|
+
# creating the cookie signature
|
52
|
+
digest0 = Digest::MD5.hexdigest(ip_timestamp + get_secret_key + options[:user] + "\0" + options[:token_list] + "\0" + options[:user_data])
|
53
|
+
digest = Digest::MD5.hexdigest(digest0 + get_secret_key)
|
54
|
+
|
55
|
+
# concatenating signature, timestamp and payload
|
56
|
+
cookie = digest + timestamp.to_s(16) + options[:user] + '!' +
|
57
|
+
options[:token_list] + '!' + options[:user_data]
|
58
|
+
|
59
|
+
# base64 encode cookie, if needed
|
60
|
+
if options[:encode]
|
61
|
+
require 'base64'
|
62
|
+
cookie = Base64.encode64(cookie).gsub("\n", '').strip
|
63
|
+
end
|
64
|
+
|
65
|
+
return cookie
|
66
|
+
end
|
67
|
+
|
68
|
+
# returns token list previously saved in auth_tkt cookie
|
69
|
+
def get_auth_tkt_token_list
|
70
|
+
cookie_decoded = Base64.decode64(cookies[:auth_tkt])
|
71
|
+
return cookie_decoded.split('!')[1]
|
72
|
+
end
|
73
|
+
|
74
|
+
# returns user data previously saved in auth_tkt cookie
|
75
|
+
def get_auth_tkt_user_data
|
76
|
+
cookie_decoded = Base64.decode64(cookies[:auth_tkt])
|
77
|
+
return cookie_decoded.split('!')[2]
|
78
|
+
end
|
79
|
+
|
80
|
+
# returns the shared secret string used to sign the cookie
|
81
|
+
def get_secret_key
|
82
|
+
self.class.auth_tkt_secret
|
83
|
+
end
|
84
|
+
|
85
|
+
# function adapted according to php: generates an IPv4 Internet network address
|
86
|
+
# from its Internet standard format (dotted string) representation.
|
87
|
+
def ip2long(ip)
|
88
|
+
long = 0
|
89
|
+
ip.split(/\./).reverse.each_with_index do |x, i|
|
90
|
+
long += x.to_i << (i * 8)
|
91
|
+
end
|
92
|
+
long
|
93
|
+
end
|
94
|
+
|
95
|
+
# Digests the password using the configured encryptor.
|
96
|
+
module ClassMethods
|
97
|
+
Devise::Models.config(self, :auth_tkt_domain, :auth_tkt_encode, :auth_tkt_ignore_ip, :auth_tkt_secret)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/test/helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: devise_ticketable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Morton Jonuschat
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-07-30 00:00:00 +02:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: thoughtbot-shoulda
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
description: Adding device_ticketable to your devise implementaton will integrate it with mod_auth_tkt for the Apache HTTP server by setting/destroying the necessary auth_tkt cookie
|
36
|
+
email: yabawock@gmail.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- LICENSE
|
43
|
+
- README.md
|
44
|
+
files:
|
45
|
+
- .gitignore
|
46
|
+
- LICENSE
|
47
|
+
- README.md
|
48
|
+
- Rakefile
|
49
|
+
- VERSION
|
50
|
+
- devise_ticketable.gemspec
|
51
|
+
- lib/devise_ticketable.rb
|
52
|
+
- lib/devise_ticketable/hooks/ticketable.rb
|
53
|
+
- lib/devise_ticketable/model.rb
|
54
|
+
- test/helper.rb
|
55
|
+
- test/test_devise_ticketable.rb
|
56
|
+
has_rdoc: true
|
57
|
+
homepage: http://github.com/yabawock/devise_ticketable
|
58
|
+
licenses: []
|
59
|
+
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options:
|
62
|
+
- --charset=UTF-8
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
hash: 3
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
hash: 3
|
80
|
+
segments:
|
81
|
+
- 0
|
82
|
+
version: "0"
|
83
|
+
requirements: []
|
84
|
+
|
85
|
+
rubyforge_project:
|
86
|
+
rubygems_version: 1.3.7
|
87
|
+
signing_key:
|
88
|
+
specification_version: 3
|
89
|
+
summary: Add support to devise for acting as a SSO server using mod_auth_tkt for apache
|
90
|
+
test_files:
|
91
|
+
- test/helper.rb
|
92
|
+
- test/test_devise_ticketable.rb
|