trivial_sso 4.0.0.3

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
+ SHA1:
3
+ metadata.gz: 757d1e6efcab4ef502c3b7081079211f9b59efb2
4
+ data.tar.gz: 132360a31cfd6b5c8e5859c50acb907f433b30a4
5
+ SHA512:
6
+ metadata.gz: 513db9226ecb8da76264c56cc7c202355aff18553627c2f3b8c47d30758e0839d4509ba4553ec32953f14189a3b871f7329a13cd57552e7c8f36c9e0bd80f30e
7
+ data.tar.gz: 0e1edc9ec2f99d0cd34424292107a32eaf54374c26060e7bab067bbf699b97c4a6adbbfc8ca25894556cd4dbb8d25d424ca534487f15877ebd29c72aee275834
data/CHANGELOG.md ADDED
@@ -0,0 +1,15 @@
1
+ ## TrivialSso Change Log ##
2
+ ### Changelog ###
3
+
4
+ ### 4.0.0.3
5
+ - ease the required ruby back to 1.9.3
6
+
7
+ #### 4.0.0
8
+ - change version high number number to follow supported Rails version
9
+
10
+ #### 0.1.3 ####
11
+
12
+ - Refactor the main code for slimness
13
+ - Add Guard with Test Unit and Bundler support
14
+ - Refactor Tests
15
+ - added .rvmrc
data/MIT-LICENSE ADDED
@@ -0,0 +1,8 @@
1
+ Copyright (c) 2012 David J. Lee., David Southard
2
+ http://lee.dj/ http://github.com/nacengineer
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5
+
6
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7
+
8
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,109 @@
1
+ ## TrivialSso
2
+
3
+ A very simple gem to help with creating and reading cookies across multiple sites in a Ruby on Rails application.
4
+
5
+ This allows for a simple single sign on solution among sites within the same domain.
6
+
7
+ This does *not* work across domains.
8
+
9
+ ## Requirements
10
+
11
+ - ruby 1.9
12
+
13
+ ## Getting Started
14
+
15
+ Add the gem to your Gemfile
16
+
17
+ gem 'trivial_sso'
18
+
19
+ Install the gem
20
+
21
+ bundle install
22
+
23
+ After you've installed the gem, you need to generate a configuration file.
24
+
25
+ rails g trivial_sso:install
26
+
27
+ This will create an initializer file with a shared secret. You need to modify this to a big long string of characters. Keep this safe from others as they could forge cookies for your sites if they get ahold of this string. All sites that use the single sign on must have this same shared secret for the cookies to properly interoperate.
28
+
29
+ ## Creating a cookie
30
+
31
+ A cookie is created using a hash of data supplied to it. This must contain a **username** key.
32
+
33
+ When you create the cookie data an expire time is built into the payload. Setting the **:expires** on the cookie is just a convenience to make sure it gets cleared by the browser. The actual expiration date that matters is what is encoded in the cookie.
34
+
35
+ ```ruby
36
+ # Create a hash of data we want to store in the cookie.
37
+ userdata = {
38
+ "username" => current_user.login,
39
+ "display" => current_user.display_name,
40
+ "groups" => current_user.memberof
41
+ }
42
+
43
+ #Generate the cookie data
44
+ cookie = TrivialSso::Login.cookie(userdata)
45
+
46
+ # Set the cookie
47
+ cookies[:sso_login] = {
48
+ :value => cookie,
49
+ :expires => TrivialSso::Login.expire_date,
50
+ :domain => 'mydomain.com',
51
+ :httponly => true,
52
+ }
53
+ ```
54
+
55
+ The above code creates a hash of data we will be putting in the cookie, generates the cookie, and then sets the cookie in the browser.
56
+
57
+ ## Decoding a cookie
58
+
59
+ Retrieve the contents of the cookie by calling decode_cookie
60
+
61
+ @userdata = TrivialSso::Login.decode_cookie(cookies[:sso_login])
62
+
63
+ This will throw an exception if the cookie has been tampered with, or if the expiration date has passed.
64
+
65
+ ## Sample code for application_controller
66
+
67
+ Here are some methods you can add into your application controller to authenticate against the cookie.
68
+
69
+ ```ruby
70
+ # If there is a problem with the cookie, redirect back to our central login server.
71
+ rescue_from TrivialSso::CookieError do |exception|
72
+ redirect_to 'https://login.mydomain.com/'
73
+ end
74
+
75
+ # authorize our users based on the cookie.
76
+ before_filter :auth_user!
77
+
78
+ # authenticate a user and set @current_user
79
+ def auth_user!
80
+ cu = current_user
81
+
82
+ # Check for authorization based on "groups" data that was put in the cookie
83
+ # by the central login application.
84
+ # you could also skip this check and just return true if the cookie is valid.
85
+ if cu['groups'].include? "ALLOWED_GROUP" #all lower case
86
+ @current_user = cu
87
+ true
88
+ else
89
+ render :file => "#{Rails.root}/public/403", :formats => [:html], :status => 403, :layout => false
90
+ end
91
+
92
+ false
93
+ end
94
+
95
+ # our current_user decodes the cookie.
96
+ def current_user
97
+ TrivialSso::Login.decode_cookie(cookies[:sso_login])
98
+ end
99
+
100
+ # Define the name we want to record in paper_trail (if using)
101
+ def user_for_paper_trail
102
+ if @current_user.blank?
103
+ "anonymous"
104
+ else
105
+ @current_user['username']
106
+ end
107
+ end
108
+ ```
109
+
@@ -0,0 +1,9 @@
1
+ =======================================================================
2
+
3
+ What you need to do next:
4
+
5
+ Edit config/initalizers/sso_secret.rb to include a secret that will
6
+ be shared between all of the sites. This secret must match for each
7
+ site using the cookies.
8
+
9
+ =======================================================================
@@ -0,0 +1,5 @@
1
+ # This file is required to define the shared secret used for generating and decoding
2
+ # SSO cookies. This secret *must* be the same across all of your applications.
3
+ require 'securerandom'
4
+
5
+ <%= Rails.application.class.parent_name %>::Application.config.sso_secret = SecureRandom.hex(64)
@@ -0,0 +1,18 @@
1
+ module TrivialSso
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../../templates",__FILE__)
5
+
6
+ desc "Creates a sso_secret initalizer"
7
+
8
+ def copy_initializer
9
+ template "sso_secret.rb", "config/initializers/sso_secret.rb"
10
+ end
11
+
12
+ def show_readme
13
+ readme "README"
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ require "trivial_sso/version"
2
+ require 'trivial_sso/error'
3
+ require 'trivial_sso/login'
@@ -0,0 +1,54 @@
1
+ module TrivialSso
2
+ module Error
3
+
4
+ # General Cookie Error
5
+ class CookieError < RuntimeError
6
+ def to_s
7
+ "There was an error processing the Ophth Cookie"
8
+ end
9
+ end
10
+
11
+ # Cookie can not be verified, data has been altered
12
+ class BadCookie < CookieError
13
+ def to_s
14
+ "Login cookie can not be verified!"
15
+ end
16
+ end
17
+
18
+ # cookie is no longer valid
19
+ class LoginExpired < CookieError
20
+ def to_s
21
+ "Login cookie has expired!"
22
+ end
23
+ end
24
+
25
+ # Cookie is missing
26
+ class MissingCookie < CookieError
27
+ def to_s
28
+ "Login cookie is missing!"
29
+ end
30
+ end
31
+
32
+ # Cookie is lacking a username.
33
+ class NoUsernameCookie < CookieError
34
+ def to_s
35
+ "Need username to create cookie"
36
+ end
37
+ end
38
+
39
+ # Missing configuration value.
40
+ class MissingConfig < CookieError
41
+ def to_s
42
+ "Missing secret configuration for cookie, need to define config.sso_secret"
43
+ end
44
+ end
45
+
46
+ # Missing Rails configuration value.
47
+ class MissingRails < CookieError
48
+ def to_s
49
+ "Rails isn't loaded, you need Rails to use trivial_sso"
50
+ end
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,77 @@
1
+ module TrivialSso
2
+ class Login
3
+
4
+ # signing and un-signing may have to be refactored to use OpenSSL:HMAC...
5
+ # as this will not work well across platforms. (ideally this should work for PHP as well)
6
+
7
+ # Decodes and verifies an encrypted cookie
8
+ # throw a proper exception if a bad or invalid cookie.
9
+ # otherwise, return the username and userdata stored in the cookie
10
+ def self.decode_cookie(cookie = nil)
11
+ begin
12
+ raise TrivialSso::Error::MissingCookie if cookie.nil? || cookie.empty?
13
+ userdata, timestamp = encrypted_message.decrypt_and_verify(cookie)
14
+ raise TrivialSso::Error::LoginExpired if check_timestamp(timestamp)
15
+ userdata
16
+ rescue NoMethodError
17
+ raise TrivialSso::Error::MissingConfig
18
+ rescue ActiveSupport::MessageVerifier::InvalidSignature ||
19
+ ActiveSupport::MessageEncryptor::InvalidMessage
20
+ raise TrivialSso::Error::BadCookie
21
+ end
22
+ end
23
+
24
+ # create an encrypted and signed cookie containing userdata and an expiry date.
25
+ # userdata should be an array, and at minimum include a 'username' key.
26
+ # using json serializer to hopefully allow future cross version compatibliity
27
+ # (Marshall, the default serializer, is not compatble between versions)
28
+ def self.cookie(userdata, expire_date = default_expire_date)
29
+ begin
30
+ raise TrivialSso::Error::MissingConfig if sso_secret
31
+ raise TrivialSso::Error::NoUsernameCookie if check_username(userdata)
32
+ enc.encrypt_and_sign([userdata, expire_date])
33
+ rescue NoMethodError
34
+ raise TrivialSso::Error::MissingConfig
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def self.check_username(userdata)
41
+ userdata.nil? ||
42
+ userdata.empty? ||
43
+ ! userdata.has_key?('username') ||
44
+ userdata['username'].empty?
45
+ end
46
+
47
+ def self.enc
48
+ ActiveSupport::MessageEncryptor.new(sso_secret , serializer: JSON)
49
+ end
50
+
51
+ def self.default_expire_date
52
+ (9.hours.from_now).to_i
53
+ end
54
+
55
+ def self.check_timestamp(timestamp)
56
+ (timestamp - DateTime.now.to_i) <= 0
57
+ end
58
+
59
+ def self.encrypted_message
60
+ raise TrivialSso::Error::MissingRails unless defined? Rails
61
+ ActiveSupport::MessageEncryptor.new(sso_secret, serializer: JSON)
62
+ end
63
+
64
+ def self.sso_secret
65
+ check_for_rails
66
+ if Rails.configuration.sso_secret.nil? || Rails.configuration.sso_secret.empty?
67
+ raise TrivialSso::Error::MissingConfig
68
+ end
69
+ Rails.configuration.sso_secret
70
+ end
71
+
72
+ def self.check_for_rails
73
+ raise TrivialSso::Error::MissingRails unless defined?(Rails)
74
+ end
75
+
76
+ end
77
+ end
@@ -0,0 +1,3 @@
1
+ module TrivialSso
2
+ VERSION = "4.0.0.3"
3
+ end
@@ -0,0 +1,66 @@
1
+ require 'active_support/core_ext'
2
+
3
+ require 'trivial_sso'
4
+ require 'forgery'
5
+ require 'securerandom'
6
+
7
+ describe TrivialSso do
8
+
9
+ def before
10
+ # Stub out our Rails config so we can test things properly.
11
+ Rails.stubs(:configuration).returns(Rails::Application::Configuration.allocate)
12
+ Rails.configuration.sso_secret = SecureRandom.hex(64)
13
+ @user_name = Forgery::Internet.user_name
14
+ @data = Forgery::LoremIpsum.words(20)
15
+ @userdata = {'username' => @user_name, 'data' => @data}
16
+ @expired_cookie = TrivialSso::Login.cookie(
17
+ {'username' => 'testor'}, 2.seconds.ago
18
+ )
19
+ end
20
+
21
+ it "does create cookie with userdata" do
22
+ TrivialSso::Login.cookie(@userdata).should_not be_nil
23
+ end
24
+
25
+ # def test_create_cookie_and_decode_it
26
+ # mycookie = TrivialSso::Login.cookie(@userdata)
27
+ # data = TrivialSso::Login.decode_cookie(mycookie)
28
+ # assert_equal data['data'], @data
29
+ # end
30
+
31
+ # def test_throw_exception_on_missing_username
32
+ # assert_raise TrivialSso::Error::NoUsernameCookie do
33
+ # mycookie = TrivialSso::Login.cookie("")
34
+ # end
35
+ # end
36
+
37
+ # def test_expire_date_exists
38
+ # # in a full rails environment, this will return an ActiveSupport::TimeWithZone
39
+ # assert TrivialSso::Login.expire_date.is_a?(Time),
40
+ # "proper Time object not returned"
41
+ # end
42
+
43
+ # def test_expire_date_is_in_future
44
+ # assert (DateTime.now < TrivialSso::Login.expire_date),
45
+ # "Expire date is in the past - cookie will expire immediatly."
46
+ # end
47
+
48
+ # def test_raise_exception_on_blank_cookie
49
+ # assert_raise TrivialSso::Error::MissingCookie do
50
+ # TrivialSso::Login.decode_cookie("")
51
+ # end
52
+ # end
53
+
54
+ # def test_raise_exception_on_bad_cookie
55
+ # assert_raise TrivialSso::Error::BadCookie do
56
+ # TrivialSso::Login.decode_cookie("BAhbB0kiC2RqbGVlMgY6BkVUbCsHo17iTg")
57
+ # end
58
+ # end
59
+
60
+ # def test_raise_exception_on_expired_cookie
61
+ # assert_raise TrivialSso::Error::LoginExpired do
62
+ # TrivialSso::Login.decode_cookie(@expired_cookie)
63
+ # end
64
+ # end
65
+
66
+ end
@@ -0,0 +1,62 @@
1
+ require 'rubygems'
2
+ require 'spork'
3
+ # uncomment the following line to use spork with the debugger
4
+ # require 'spork/ext/ruby-debug'
5
+
6
+ Spork.prefork do
7
+ # Loading more in this block will cause your tests to run faster. However,
8
+ # if you change any configuration or code from libraries loaded here, you'll
9
+ # need to restart spork for it take effect.
10
+ ENV["RAILS_ENV"] ||= 'test'
11
+
12
+ unless ENV['DRB']
13
+ require 'simplecov'
14
+ SimpleCov.start
15
+ end
16
+
17
+ require 'rails'
18
+ require 'rspec/autorun'
19
+ require 'rspec/mocks'
20
+ require 'factory_girl'
21
+ require 'perftools'
22
+
23
+ # Requires supporting ruby files with custom matchers and macros, etc,
24
+ # in spec/support/ and its subdirectories.
25
+ # Dir[File.join("spec/support/**/*.rb")].each {|f| require f}
26
+
27
+ RSpec.configure do |config|
28
+ config.include FactoryGirl::Syntax::Methods
29
+
30
+ config.mock_with :rspec
31
+
32
+ config.order = "random"
33
+
34
+ config.before :suite do
35
+ PerfTools::CpuProfiler.start("#{profile_directory}/rspec_profile")
36
+ end
37
+
38
+ config.after :suite do
39
+ PerfTools::CpuProfiler.stop
40
+ end
41
+
42
+ def profile_directory
43
+ directory = "/tmp/trivial_sso"
44
+ system("mkdir #{directory}") unless Dir.exist? directory
45
+ directory
46
+ end
47
+
48
+ end
49
+ end
50
+
51
+ Spork.each_run do
52
+ if ENV['DRB']
53
+ require 'simplecov'
54
+ SimpleCov.start
55
+ end
56
+ FactoryGirl.reload
57
+ RSpec.configure do |config|
58
+ def svg_filename
59
+ "/tmp/trivial_sso/profile-#{Time.now.localtime.strftime("%H%M%S")}.svg"
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,19 @@
1
+ class DeferredGarbageCollection
2
+
3
+ DEFERRED_GC_THRESHOLD = (ENV['DEFER_GC'] || 15.0).to_f
4
+
5
+ @@last_gc_run = Time.now
6
+
7
+ def self.start
8
+ GC.disable if DEFERRED_GC_THRESHOLD > 0
9
+ end
10
+
11
+ def self.reconsider
12
+ if DEFERRED_GC_THRESHOLD > 0 && Time.now - @@last_gc_run >= DEFERRED_GC_THRESHOLD
13
+ GC.enable
14
+ GC.start
15
+ GC.disable
16
+ @@last_gc_run = Time.now
17
+ end
18
+ end
19
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: trivial_sso
3
+ version: !ruby/object:Gem::Version
4
+ version: 4.0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - David J. Lee
8
+ - David Southard
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-07-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - '>='
19
+ - !ruby/object:Gem::Version
20
+ version: 4.0.0
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - '>='
26
+ - !ruby/object:Gem::Version
27
+ version: 4.0.0
28
+ - !ruby/object:Gem::Dependency
29
+ name: activesupport
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '>='
33
+ - !ruby/object:Gem::Version
34
+ version: 4.0.0
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: 4.0.0
42
+ description: |-
43
+ Used to encode and decode cookies used in a single
44
+ sign on implementation within the same domain
45
+ email:
46
+ - david@lee.dj
47
+ - nacengineer@gmail.com
48
+ executables: []
49
+ extensions: []
50
+ extra_rdoc_files: []
51
+ files:
52
+ - lib/generators/templates/README
53
+ - lib/generators/templates/sso_secret.rb
54
+ - lib/generators/trivial_sso/install_generator.rb
55
+ - lib/trivial_sso/error.rb
56
+ - lib/trivial_sso/login.rb
57
+ - lib/trivial_sso/version.rb
58
+ - lib/trivial_sso.rb
59
+ - MIT-LICENSE
60
+ - README.md
61
+ - CHANGELOG.md
62
+ - spec/models/trivial_sso_spec.rb
63
+ - spec/spec_helper.rb
64
+ - spec/support/deferred_garbage_collection.rb
65
+ homepage: https://github.com/nacengineer/trivial_sso
66
+ licenses:
67
+ - MIT
68
+ metadata: {}
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - '>='
76
+ - !ruby/object:Gem::Version
77
+ version: 1.9.3
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 2.0.3
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: A simple library to help with Single Sign On cookies
89
+ test_files:
90
+ - spec/models/trivial_sso_spec.rb
91
+ - spec/spec_helper.rb
92
+ - spec/support/deferred_garbage_collection.rb