has_global_session 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,104 +5,121 @@ session state in a cryptographically secure way, facilitating single sign-on
5
5
  and enabling easier development of large-scale distributed applications that
6
6
  make use of architectural strategies such as sharding or separation of concerns.
7
7
 
8
- This plugin does not provide a complete solution for authentication. In
9
- particular, it does *not* provide any of the following:
8
+ In other words: it lets semi-related Web apps share selected bits of session
9
+ state.
10
+
11
+ This plugin does not provide a complete solution for identity management. In
12
+ particular, it does not provide any of the following:
10
13
 
11
14
  * <b>federation</b> -- aka cross-domain single sign-on -- use OpenID for that.
12
15
 
13
- * <b>authentication</b> -- the application's controllers must authenticate the user.
16
+ * <b>authentication</b> -- the application must authenticate the user.
17
+
18
+ * <b>authorization</b> -- the application is responsible for using the contents
19
+ of the global session to make authorization decisions.
14
20
 
15
21
  * <b>secrecy</b> -- global session attributes can be signed but never encrypted;
16
- protect against third-party snooping using SSL, and if you don't want your
17
- users to see their session state, put it in a database.
22
+ protect against third-party snooping using SSL. Group secrecy is expensive;
23
+ if you don't want your users to see their session state, put it in a database,
24
+ or in an encrypted local session cookie.
18
25
 
19
26
  * <b>replication</b> -- the authentication authorities must have some way to
20
- share information about the database of users, their passwords, etc.
27
+ share information about the database of users in order to authenticate
28
+ them and place identifying information into the global session.
21
29
 
22
30
  * <b>single sign-out</b> -- the authorities must have some way to broadcast a
23
31
  notification when sessions are invalidated; they can override the default
24
32
  Directory implementation to do realtime revocation checking.
25
33
 
26
- == Global Session Contents
34
+ = Example
35
+
36
+ 1) Create a basic config file and edit it to suit your needs:
37
+ $ script/generate global_session_config mycoolapp.com
38
+
39
+ 2) Create an authentication authority:
40
+ $ script/generate global_session_authority mycoolapp
41
+
42
+ 3) Declare that some or all of your controllers will use the global session:
43
+ class ApplicationController < ActionController::Base
44
+ has_global_session
45
+ end
46
+
47
+ 4) Make use of the global session hash in your controllers:
48
+ global_session['user'] = @user.id
49
+ ...
50
+ @current_user = User.find(global_session['user'])
51
+
52
+ 5) For easier programming, enable seamless integration with the local session:
53
+ (in global_session.yml)
54
+ common:
55
+ integrated: true
56
+
57
+ (in your controllers)
58
+ session['user'] = @user.id #goes to the global session
59
+ session['local_thingie'] = @thingie.id #goes to the local session
60
+
61
+ = Global Session Contents
27
62
 
28
63
  Global session state is stored as a cookie in the user's browser. The cookie
29
64
  is a Zlib-compressed JSON dictionary containing the following stuff:
30
- * session metadata (UUID, created-at, expires-at, certifying-authority)
65
+ * session metadata (UUID, created-at, expires-at, signing-authority)
31
66
  * signed session attributes (e.g. the authenticated user ID)
32
67
  * insecure session attributes (e.g. the last-visited URL)
33
68
  * a cryptographic signature of the metadata and signed attributes
34
69
 
35
70
  The global session is unserialized and its signature is verified whenever
36
- a controller asks for the global session. The cookie's value is updated
37
- whenever its attributes change. As an optimization, the signature is only
71
+ a controller asks for one of its attributes. The cookie's value is updated
72
+ whenever attributes change. As an optimization, the signature is only
38
73
  recomputed when the metadata or signed attributes have changed; insecure
39
74
  attributes can change "for free."
40
75
 
41
76
  Because the security properties of attributes can vary, HasGlobalSession
42
77
  requires all _possible_ attributes to be declared up-front in the config
43
78
  file. The 'attributes' section of the config file defines the _schema_
44
- for the global session: which attributes can be used, and which must be
45
- cryptographically signed in order to be used.
79
+ for the global session: which attributes can be used, which can be trusted
80
+ to make authorization decisions (because they are signed), and are insecure
81
+ and therefore act only as "hints" about the session.
46
82
 
47
83
  Since the session is serialized as JSON, only a limited range of object
48
84
  types can be stored in it: strings, numbers, lists, hashes and other Ruby
49
85
  primitives. Ruby booleans (true/false) do not translate well into JSON
50
86
  and should be avoided.
51
87
 
52
- = Example
53
-
54
- 1) Create a basic config file and edit it to suit your needs:
55
- $ script/generate global_session_config mycoolapp.com
56
-
57
- 2) Create an authentication authority:
58
- $ script/generate global_session_authority mycoolapp
59
-
60
- 3) Declare that some or all of your application's controllers will have access
61
- to the global session:
62
- class ApplicationController < ActionController::Base
63
- has_global_session
64
- end
65
-
66
- 4) Make use of the global session hash in your controllers:
67
- global_session['user'] = @user.id
68
- ...
69
- @current_user = User.find(global_session['user'])
70
-
71
88
  = Detailed Information
72
89
 
73
90
  == Global Session Domain
74
91
 
75
92
  We refer to collection of _all_ Web application instances capable of using the
76
93
  global session as the "domain." The global session domain may consist of any
77
- number of distinct servers, possibly hidden behind load balancers or proxies.
78
- The servers within the domain may all be running the same Rails application,
94
+ number of distinct nodes, possibly hidden behind load balancers or proxies.
95
+ The nodes within the domain may all be running the same Rails application,
79
96
  or they may be running different codebases that represent different parts of
80
97
  a distributed application. (They may also be using app frameworks other than
81
98
  Rails.)
82
99
 
83
- The only constraint imposed by HasGlobalSession is that all servers within the
100
+ The only constraint imposed by HasGlobalSession is that all nodes within the
84
101
  domain must have end-user-facing URLs within the same second-level DNS domain.
85
102
  This is due to limitations imposed by the HTTP cookie mechanism: for privacy
86
- reasons, cookies will only be sent to servers within the same domain as the
87
- server that first created them.
103
+ reasons, cookies will only be sent to nodes within the same domain as the
104
+ node that first created them.
88
105
 
89
106
  For example, in my HasGlobalSession configuration file I might specify that my
90
- cookie's domain is "example.com". My app servers at app1.example.com and
107
+ cookie's domain is "example.com". My app nodes at app1.example.com and
91
108
  app2.example.com would be part of the global session domain, but my business
92
- partner's application at www.partner.com could not participate.
109
+ partner's application at app3.partner.com could not participate.
93
110
 
94
111
  == Authorities and Relying Parties
95
112
 
96
- A Web application that can create or update the global session is said to
97
- be an "authority" (because it's trusted by other parties to make assertions
98
- about global session state). An application that can read the global session
99
- is said to be a "relying party." In practice, every application is a relying
100
- party but not all of them need to be authorities.
113
+ A node that can create or update the global session is said to be an "authority"
114
+ (because it's trusted by other parties to make assertions about global session
115
+ state). An application that can read the global session is said to be a "relying
116
+ party." In practice, every application is a relying party, but not all of them
117
+ need to be authorities.
101
118
 
102
119
  There is an RSA key pair associated with each authority. The authority's
103
120
  public key is distribued to all relying parties, but the private key must
104
121
  remain a secret to that authority (which may consist of many individual
105
- servers).
122
+ nodes).
106
123
 
107
124
  This system allows for significant flexibility when configuring a distributed
108
125
  app's global session. There must be at least one authority, but for many apps
@@ -117,7 +134,7 @@ Here are some reasons you might consider dividing your systems into different
117
134
  authorities:
118
135
  * beta/staging system vs. production system
119
136
  * system hosted by a third party vs. system hosted internally
120
- * e-commerce server vs. storefront server
137
+ * e-commerce node vs. storefront node
121
138
 
122
139
  == The Directory
123
140
 
@@ -131,21 +148,41 @@ signing session attributes.
131
148
 
132
149
  The Directory implementation included with HasGlobalSession uses the filesystem
133
150
  as the backing store for its key pairs. Its #initialize method accepts a
134
- filesystem path that will be searched for *.pub and *.key files containing PEM-
135
- encoded public and private keys (the same format used by OpenSSH).
151
+ filesystem path that will be searched for files containing PEM-encoded public
152
+ and private keys (the same format used by OpenSSH). This simple Directory
153
+ implementation relies on the following conventions:
154
+ * Public keys have a *.pub extension.
155
+ * Private keys have a *.key extension.
156
+ * If a node is an authority, then one (and *only* one) *.key file should exist.
157
+ * The local node's authority name is inferred from the name of the private key
158
+ file.
136
159
 
137
160
  When used with a Rails app, HasGlobalSession expects to find its keystore in
138
161
  config/authorities. You can use the global_session generator to create new key
139
- pairs. Remember never to check a *.key file into a public repository!! (In
140
- contrast, *.pub files can be distributed freely.)
162
+ pairs. Remember never to check a *.key file into a public repository!! (*.pub
163
+ files can be checked into source control and distributed freely.)
141
164
 
142
165
  If you wish all of the systems to stop trusting an authority, simply delete
143
- its public key from config/authorities.
166
+ its public key from config/authorities and re-deploy your app.
167
+
168
+ === Implementing Your Own Directory Provider
169
+
170
+ To replace or enhance the built-in Directory, simply create a new class that
171
+ extends Directory and put the class somewhere in your app (the lib directory
172
+ is a good choice). In the HasGlobalSession configuration file, specify the
173
+ class name of the directory under the 'common' section, like so:
174
+ common:
175
+ integrated: true
176
+ directory: MyCoolDirectory
144
177
 
145
178
  = To-Do
146
179
 
147
180
  * Configurable session expiry
181
+
148
182
  * Option to auto-renew session
149
- * Option for non-sticky global session (cookie expires at close of browser session, not at global session expiration!)
183
+
184
+ * Option for non-sticky global session
185
+ (e.g. cookie expires at close of browser session, not at global session
186
+ expiration!)
150
187
 
151
188
  Copyright (c) 2010 Tony Spataro <code@tracker.xeger.net>, released under the MIT license
@@ -7,7 +7,7 @@ spec = Gem::Specification.new do |s|
7
7
  s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
8
8
 
9
9
  s.name = 'has_global_session'
10
- s.version = '0.8.0'
10
+ s.version = '0.8.1'
11
11
  s.date = '2010-06-01'
12
12
 
13
13
  s.authors = ['Tony Spataro']
@@ -17,10 +17,10 @@ spec = Gem::Specification.new do |s|
17
17
  s.summary = %q{Secure single-domain session sharing plugin for Rails.}
18
18
  s.description = %q{This Rails plugin allows several Rails web apps that share the same back-end user database to share session state in a cryptographically secure way, facilitating single sign-on in a distributed web app. It only provides session sharing and does not concern itself with authentication or replication of the user database.}
19
19
 
20
- s.add_runtime_dependency('uuidtools', [">= 2.1.1"])
20
+ s.add_runtime_dependency('uuidtools', [">= 1.0.7"])
21
21
 
22
22
  basedir = File.dirname(__FILE__)
23
- candidates = ['has_global_session.gemspec', 'init.rb', 'MIT-LICENSE', 'README'] +
23
+ candidates = ['has_global_session.gemspec', 'init.rb', 'MIT-LICENSE', 'README.rdoc'] +
24
24
  Dir['lib/**/*'] +
25
25
  Dir['rails/**/*']
26
26
  s.files = candidates.sort
@@ -0,0 +1,32 @@
1
+ class GlobalSessionAuthorityGenerator < Rails::Generator::Base
2
+ def initialize(runtime_args, runtime_options = {})
3
+ super
4
+
5
+ @app_name = File.basename(RAILS_ROOT)
6
+ @auth_name = args.shift
7
+ raise ArgumentError, "Must specify name for global session authority, e.g. 'mycoolapp'" unless @auth_name
8
+ end
9
+
10
+ def manifest
11
+ record do |m|
12
+ new_key = OpenSSL::PKey::RSA.generate( 1024 )
13
+ new_public = new_key.public_key.to_pem
14
+ new_private = new_key.to_pem
15
+
16
+ dest_dir = File.join(RAILS_ROOT, 'config', 'authorities')
17
+ FileUtils.mkdir_p(dest_dir)
18
+
19
+ File.open(File.join(dest_dir, @auth_name + ".pub"), 'w') do |f|
20
+ f.puts new_public
21
+ end
22
+
23
+ File.open(File.join(dest_dir, @auth_name + ".key"), 'w') do |f|
24
+ f.puts new_private
25
+ end
26
+
27
+ puts "***"
28
+ puts "*** Don't forget to delete config/authorities/#{@auth_name}.key"
29
+ puts "***"
30
+ end
31
+ end
32
+ end
@@ -10,7 +10,7 @@ class GlobalSessionConfigGenerator < Rails::Generator::Base
10
10
  def manifest
11
11
  record do |m|
12
12
 
13
- m.template 'templates/global_session.yml.erb',
13
+ m.template 'global_session.yml.erb',
14
14
  'config/global_session.yml',
15
15
  :assigns=>{:app_name=>@app_name,
16
16
  :app_domain=>@app_domain}
@@ -1,6 +1,5 @@
1
1
  # Common settings of the global session (that apply to all Rails environments)
2
- # are listed here. These may be overidden in the environment-specific section,
3
- # but it seldom makes sense to do so.
2
+ # are listed here. These may be overidden in the environment-specific section.
4
3
  common:
5
4
  attributes:
6
5
  # Signed attributes of the global session
@@ -14,17 +13,30 @@ common:
14
13
  # global attributes always taking precedence over local attributes.
15
14
  integrated: true
16
15
 
17
- development:
16
+ # Test/spec runs
17
+ test:
18
+ timeout: 900
18
19
  cookie:
19
- name: __<%= app_name %>_development
20
+ name: __<%= app_name %>_test
20
21
  domain: localhost
22
+ trust:
23
+ - test
21
24
 
22
- test:
25
+ # Development mode
26
+ development:
27
+ timeout: 3600
23
28
  cookie:
24
- name: __<%= app_name %>_test
29
+ name: __<%= app_name %>_development
25
30
  domain: localhost
31
+ trust:
32
+ - development
33
+ - production
26
34
 
35
+ # Production mode
27
36
  production:
37
+ timeout: 3600
28
38
  cookie:
29
39
  name: __<%= app_name %>_global
30
40
  domain: <%= app_domain %>
41
+ trust:
42
+ - production
@@ -4,23 +4,13 @@ module HasGlobalSession
4
4
  mattr_accessor :environment
5
5
 
6
6
  def self.[](key)
7
- unless @config
8
- raise MissingConfiguration, "config_file is nil; cannot read configuration" unless config_file
9
- raise MissingConfiguration, "environment is nil; must be specified" unless environment
10
- @config = YAML.load(File.read(config_file))
11
- validate
12
- end
13
- if @config.has_key?(environment) && @config[environment].has_key?(key)
14
- return @config[environment][key]
15
- else
16
- @config['common'][key]
17
- end
7
+ get(key, true)
18
8
  end
19
9
 
20
10
  def self.validate
21
11
  ['attributes/signed', 'integrated', 'cookie/name', 'cookie/domain'].each do |path|
22
12
  elements = path.split '/'
23
- object = self[elements.shift]
13
+ object = get(elements.shift, false)
24
14
  elements.each do |element|
25
15
  object = object[element]
26
16
  if object.nil?
@@ -30,5 +20,23 @@ module HasGlobalSession
30
20
  end
31
21
  end
32
22
  end
23
+
24
+ private
25
+ def self.get(key, validated)
26
+ unless @config
27
+ raise MissingConfiguration, "config_file is nil; cannot read configuration" unless config_file
28
+ raise MissingConfiguration, "environment is nil; must be specified" unless environment
29
+ @config = YAML.load(File.read(config_file))
30
+ raise TypeError, "#{config_file} must contain a Hash!" unless Hash === @config
31
+ validate if validated
32
+ end
33
+ if @config.has_key?(environment) &&
34
+ @config[environment].respond_to?(:has_key?) &&
35
+ @config[environment].has_key?(key)
36
+ return @config[environment][key]
37
+ else
38
+ @config['common'][key]
39
+ end
40
+ end
33
41
  end
34
42
  end
@@ -36,6 +36,12 @@ module HasGlobalSession
36
36
  raise SecurityError, "Signature mismatch on global session cookie; tampering suspected"
37
37
  end
38
38
 
39
+ unless Configuration['trust'].blank? ||
40
+ @authority = @directory.my_authority_name ||
41
+ Configuration['trust'].include?(@authority)
42
+ raise SecurityError, "Global sessions created by #{@authority} are not trusted"
43
+ end
44
+
39
45
  if expired? || @directory.invalidated_session?(@id)
40
46
  raise ExpiredSession, "Global session cookie has expired"
41
47
  end
@@ -43,25 +49,25 @@ module HasGlobalSession
43
49
  else
44
50
  @signed = {}
45
51
  @insecure = {}
46
- @id = UUIDTools::UUID.timestamp_create.to_s
52
+ @id = UUID.timestamp_create.to_s
47
53
  @created_at = Time.now.utc
48
- @expires_at = 2.hours.from_now.utc #TODO configurable
49
54
  @authority = @directory.my_authority_name
50
- @dirty_secure = true
55
+ renew!
51
56
  end
52
57
  end
53
58
 
54
- def supports_key?(key)
55
- @schema_signed.include?(key) || @schema_insecure.include?(key)
56
- end
57
-
58
59
  def expired?
59
60
  (@expires_at <= Time.now)
60
61
  end
61
62
 
62
63
  def expire!
63
64
  @expires_at = Time.at(0)
64
- @dirty_secure = true
65
+ @dirty = true
66
+ end
67
+
68
+ def renew!
69
+ @expires_at = Configuration['timeout'].to_i.minutes.from_now.utc || 1.hours.from_now.utc
70
+ @dirty = true
65
71
  end
66
72
 
67
73
  def to_s
@@ -69,7 +75,7 @@ module HasGlobalSession
69
75
  'tc'=>@created_at.to_i, 'te'=>@expires_at.to_i,
70
76
  'ds'=>@signed, 'dx'=>@insecure}
71
77
 
72
- if @signature && !@dirty_secure
78
+ if @signature && !@dirty
73
79
  #use cached signature unless we've changed secure state
74
80
  authority = @authority
75
81
  signature = @signature
@@ -82,23 +88,34 @@ module HasGlobalSession
82
88
 
83
89
  hash['s'] = signature
84
90
  hash['a'] = authority
85
- json = ActiveSupport::JSON.encode(hash)
91
+ json = hash.to_json #ActiveSupport::JSON.encode(hash) -- why does this expect Data sometimes?!
86
92
  zbin = Zlib::Deflate.deflate(json, Zlib::BEST_COMPRESSION)
87
93
  return Base64.encode64(zbin)
88
94
  end
89
95
 
96
+ def supports_key?(key)
97
+ @schema_signed.include?(key) || @schema_insecure.include?(key)
98
+ end
99
+
90
100
  def [](key)
91
101
  @signed[key] || @insecure[key]
92
102
  end
93
103
 
94
104
  def []=(key, value)
105
+ case value
106
+ when String, Numeric, Array
107
+ #no-op
108
+ else
109
+ raise TypeError, "Cannot store values of type #{value.class.name} reliably"
110
+ end
111
+
95
112
  if @schema_signed.include?(key)
96
113
  unless @directory.my_private_key && @directory.my_authority_name
97
114
  raise StandardError, 'Cannot change secure session attributes; we are not an authority'
98
115
  end
99
116
 
100
117
  @signed[key] = value
101
- @dirty_secure = true
118
+ @dirty = true
102
119
  elsif @schema_insecure.include?(key)
103
120
  @insecure[key] = value
104
121
  else
@@ -109,7 +126,7 @@ module HasGlobalSession
109
126
  def has_key?(key)
110
127
  @signed.has_key(key) || @insecure.has_key?(key)
111
128
  end
112
-
129
+
113
130
  def keys
114
131
  @signed.keys + @insecure.keys
115
132
  end
@@ -6,6 +6,7 @@ module HasGlobalSession
6
6
  end
7
7
 
8
8
  def [](key)
9
+ key = key.to_s
9
10
  if @global_session.supports_key?(key)
10
11
  @global_session[key]
11
12
  else
@@ -14,6 +15,7 @@ module HasGlobalSession
14
15
  end
15
16
 
16
17
  def []=(key, value)
18
+ key = key.to_s
17
19
  if @global_session.supports_key?(key)
18
20
  @global_session[key] = value
19
21
  else
@@ -22,6 +24,7 @@ module HasGlobalSession
22
24
  end
23
25
 
24
26
  def has_key?(key)
27
+ key = key.to_s
25
28
  @global_session.has_key(key) || @local_session.has_key?(key)
26
29
  end
27
30
 
@@ -4,8 +4,14 @@ module HasGlobalSession
4
4
  return @global_session if @global_session
5
5
 
6
6
  begin
7
+ if (klass = Configuration['directory'])
8
+ klass = klass.constantize
9
+ else
10
+ klass = Directory
11
+ end
12
+
13
+ directory = klass.new(File.join(RAILS_ROOT, 'config', 'authorities'))
7
14
  cookie = cookies[Configuration['cookie']['name']]
8
- directory = Directory.new(File.join(RAILS_ROOT, 'config', 'authorities'))
9
15
 
10
16
  begin
11
17
  #unserialize the global session from the cookie, or
@@ -44,5 +50,36 @@ module HasGlobalSession
44
50
  cookies[Configuration['cookie']['name']] = options
45
51
  end
46
52
  end
53
+
54
+ def log_processing
55
+ if logger && logger.info?
56
+ log_processing_for_request_id
57
+ log_processing_for_parameters
58
+ end
59
+ end
60
+
61
+ def log_processing_for_request_id()
62
+ if global_session && global_session.id
63
+ session_id = global_session.id + " (#{session[:session_id]})"
64
+ elsif session[:session_id]
65
+ session_id = session[:session_id]
66
+ elsif request.session_options[:id]
67
+ session_id = request.session_options[:id]
68
+ end
69
+
70
+ request_id = "\n\nProcessing #{self.class.name}\##{action_name} "
71
+ request_id << "to #{params[:format]} " if params[:format]
72
+ request_id << "(for #{request_origin.split[0]}) [#{request.method.to_s.upcase}]"
73
+ request_id << "\n Session ID: #{session_id}" if session_id
74
+
75
+ logger.info(request_id)
76
+ end
77
+
78
+ def log_processing_for_parameters
79
+ parameters = respond_to?(:filter_parameters) ? filter_parameters(params) : params.dup
80
+ parameters = parameters.except!(:controller, :action, :format, :_method)
81
+
82
+ logger.info " Parameters: #{parameters.inspect}" unless parameters.empty?
83
+ end
47
84
  end
48
85
  end
data/rails/init.rb CHANGED
@@ -1,18 +1,21 @@
1
1
  basedir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
2
2
  require File.join(basedir, 'lib', 'has_global_session')
3
3
 
4
- # Tie the Configuration module to Rails' filesystem structure
5
- # and operating environment.
6
- HasGlobalSession::Configuration.config_file =
7
- File.join(RAILS_ROOT, 'config', 'global_session.yml')
8
- HasGlobalSession::Configuration.environment = RAILS_ENV
4
+ config_file = File.join(RAILS_ROOT, 'config', 'global_session.yml')
9
5
 
10
- require File.join(basedir, 'rails', 'action_controller_instance_methods')
6
+ if File.exist?(config_file)
7
+ # Tie the Configuration module to Rails' filesystem structure
8
+ # and operating environment.
9
+ HasGlobalSession::Configuration.config_file = config_file
10
+ HasGlobalSession::Configuration.environment = RAILS_ENV
11
11
 
12
- # Enable ActionController integration.
13
- class ActionController::Base
14
- def self.has_global_session
15
- include HasGlobalSession::ActionControllerInstanceMethods
16
- after_filter :global_session_update_cookie
12
+ require File.join(basedir, 'rails', 'action_controller_instance_methods')
13
+
14
+ # Enable ActionController integration.
15
+ class ActionController::Base
16
+ def self.has_global_session
17
+ include HasGlobalSession::ActionControllerInstanceMethods
18
+ after_filter :global_session_update_cookie
19
+ end
17
20
  end
18
- end
21
+ end
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: has_global_session
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ hash: 61
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 8
9
+ - 1
10
+ version: 0.8.1
5
11
  platform: ruby
6
12
  authors:
7
13
  - Tony Spataro
@@ -14,14 +20,20 @@ default_executable:
14
20
  dependencies:
15
21
  - !ruby/object:Gem::Dependency
16
22
  name: uuidtools
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
20
26
  requirements:
21
27
  - - ">="
22
28
  - !ruby/object:Gem::Version
23
- version: 2.1.1
24
- version:
29
+ hash: 25
30
+ segments:
31
+ - 1
32
+ - 0
33
+ - 7
34
+ version: 1.0.7
35
+ type: :runtime
36
+ version_requirements: *id001
25
37
  description: This Rails plugin allows several Rails web apps that share the same back-end user database to share session state in a cryptographically secure way, facilitating single sign-on in a distributed web app. It only provides session sharing and does not concern itself with authentication or replication of the user database.
26
38
  email: code@tracker.xeger.net
27
39
  executables: []
@@ -32,9 +44,10 @@ extra_rdoc_files: []
32
44
 
33
45
  files:
34
46
  - MIT-LICENSE
35
- - README
47
+ - README.rdoc
36
48
  - has_global_session.gemspec
37
49
  - init.rb
50
+ - lib/generators/global_session_authority/global_session_authority_generator.rb
38
51
  - lib/generators/global_session_config/USAGE
39
52
  - lib/generators/global_session_config/global_session_config_generator.rb
40
53
  - lib/generators/global_session_config/templates/global_session.yml.erb
@@ -55,21 +68,29 @@ rdoc_options: []
55
68
  require_paths:
56
69
  - lib
57
70
  required_ruby_version: !ruby/object:Gem::Requirement
71
+ none: false
58
72
  requirements:
59
73
  - - ">="
60
74
  - !ruby/object:Gem::Version
75
+ hash: 57
76
+ segments:
77
+ - 1
78
+ - 8
79
+ - 7
61
80
  version: 1.8.7
62
- version:
63
81
  required_rubygems_version: !ruby/object:Gem::Requirement
82
+ none: false
64
83
  requirements:
65
84
  - - ">="
66
85
  - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
67
89
  version: "0"
68
- version:
69
90
  requirements: []
70
91
 
71
92
  rubyforge_project:
72
- rubygems_version: 1.3.5
93
+ rubygems_version: 1.3.7
73
94
  signing_key:
74
95
  specification_version: 3
75
96
  summary: Secure single-domain session sharing plugin for Rails.