els_token 1.0.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/README.rdoc +12 -2
  2. data/lib/els_token.rb +209 -113
  3. data/lib/els_token/{els_user.rb → els_identity.rb} +15 -6
  4. data/lib/els_token/version.rb +1 -1
  5. data/test/dummy/Gemfile +9 -0
  6. data/test/dummy/Gemfile.lock +17 -1
  7. data/test/dummy/app/assets/javascripts/application.js +1 -2
  8. data/test/dummy/app/assets/javascripts/els_session.js.coffee +7 -0
  9. data/test/dummy/app/controllers/application_controller.rb +45 -6
  10. data/test/dummy/app/controllers/els_session_controller.rb +91 -0
  11. data/test/dummy/app/models/els_faker.rb +8 -0
  12. data/test/dummy/app/views/els_session/new.html.erb +41 -0
  13. data/test/dummy/app/views/els_session/show.html.erb +4 -0
  14. data/test/dummy/app/views/layouts/application.html.erb +6 -1
  15. data/test/dummy/config/application.rb +3 -39
  16. data/test/dummy/config/els_token.yml +21 -0
  17. data/test/dummy/config/environments/development.rb +1 -1
  18. data/test/dummy/config/environments/uat.rb +67 -0
  19. data/test/dummy/config/initializers/els_token.rb +1 -1
  20. data/test/dummy/config/routes.rb +9 -55
  21. data/test/dummy/log/development.log +2170 -4
  22. data/test/dummy/tmp/cache/assets/C65/500/sprockets%2F53516304d6d54f9499b5a7788631e5c5 +0 -0
  23. data/test/dummy/tmp/cache/assets/CA6/630/sprockets%2F8af9c2296e34c4f01a58747a12c07130 +0 -0
  24. data/test/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
  25. data/test/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
  26. data/test/dummy/tmp/cache/assets/D49/140/sprockets%2Fd128539bcb29d65cf7e28a43f8563a2f +0 -0
  27. data/test/dummy/tmp/cache/assets/D4E/1B0/sprockets%2Ff7cbd26ba1d28d48de824f0e94586655 +0 -0
  28. data/test/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
  29. data/test/dummy/tmp/cache/assets/D9C/D00/sprockets%2F66ef3d03a58dfcc273e3453b04fdf81b +0 -0
  30. data/test/dummy/tmp/cache/assets/D9F/AA0/sprockets%2Fab395cb72ff1e290f0de1f739a87bd50 +0 -0
  31. data/test/dummy/tmp/cache/assets/DDC/400/sprockets%2Fcffd775d018f68ce5dba1ee0d951a994 +0 -0
  32. data/test/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
  33. metadata +41 -54
  34. data/test/dummy/app/assets/javascripts/hello.js +0 -2
  35. data/test/dummy/app/assets/stylesheets/hello.css +0 -4
  36. data/test/dummy/app/controllers/hello_controller.rb +0 -4
  37. data/test/dummy/app/views/hello/index.html.erb +0 -1
  38. data/test/dummy/config/els.yml +0 -12
  39. data/test/els_token_test.rb.old +0 -7
  40. data/test/hello_controller_test.rb +0 -32
@@ -11,5 +11,4 @@
11
11
  // GO AFTER THE REQUIRES BELOW.
12
12
  //
13
13
  //= require jquery
14
- //= require jquery_ujs
15
- //= require_tree .
14
+ //= require els_session
@@ -0,0 +1,7 @@
1
+ $ ->
2
+
3
+ $('.els_session input#override').on "click", ->
4
+ if $(this).is(':checked')
5
+ $('.els_session input#password').parent().fadeOut()
6
+ else
7
+ $('.els_session input#password').parent().fadeIn()
@@ -2,16 +2,55 @@ class ApplicationController < ActionController::Base
2
2
  protect_from_forgery
3
3
 
4
4
  include ElsToken
5
- #els_options ELS_CONFIG
5
+ els_config ELS_CONFIG
6
6
 
7
- before_filter :authenticate
7
+ helper_method :remote_user, :rpa_username, :els_identity
8
8
 
9
9
  private
10
10
 
11
- def authenticate
12
- session[:user] ||= get_identity
13
- unless session[:user]
14
- render :nothing => true, :status => :unauthorized
11
+ # will set a @cdid instance variable
12
+ # determined by the REMOTE_USER or RPA_USERNAME headers.
13
+ # cdid doesn't change often so it's gets stashed in the session
14
+ #
15
+ def cdid
16
+ @cdid ||=
17
+ session[:cdid] ||=
18
+ request.headers["REMOTE_USER"] ||=
19
+ request.headers["RPA_USERNAME"]
20
+ end
21
+
22
+ # the els_identity is backed by the ELS SSO system.
23
+ # It will try to get a full identity object and then store
24
+ # that in a memcache as raw retrieval currently hits performance.
25
+ # Whilst SSO is brilliant, it can be a bit of a drag working around
26
+ # it during development.
27
+ #
28
+ # This method will allow an end user to circumvent
29
+ # the domain specific ELS login by authenticating directly with the ELS
30
+ # system or, if a cookie is already resent, use that to retrieve an identity.
31
+ # As an additional development bonus, it's possible to fake the identity -
32
+ # setting it to whatever username is desired.
33
+ #
34
+ # It's up to the implementer to test the validity of that username in
35
+ # their own application.
36
+ # Likewise once you have an ElsIdentity object you may want to call your own
37
+ # usermodel based on some value. 'cdid' and 'employee_number'
38
+ # are common ones.
39
+ #
40
+ # One of the best things about the ElsIdentity is that it contains Group
41
+ # information :) So, rather than implementing yet-another-role system in
42
+ # your app, let the identity be managed centrally. Once you have the
43
+ # ElsIdentity you can ask it whether it belongs to some role:
44
+ #
45
+ # @els_identity.has_role? "some group"
46
+ #
47
+ def els_identity
48
+ @els_identity = Rails.cache.fetch(session[:els_token], :namespace => "els_identity")
49
+ unless @els_identity
50
+ Rails.logger.debug("no identity in cache. Redirecting")
51
+ session[:redirect_to] = request.env["PATH_INFO"]
52
+ logger.debug("user will be returned to #{session[:redirect_to]}")
53
+ redirect_to els_session_new_path
15
54
  end
16
55
  end
17
56
 
@@ -0,0 +1,91 @@
1
+ class ElsSessionController < ApplicationController
2
+
3
+ before_filter :els_identity, :only => [:show]
4
+
5
+ def show
6
+ end
7
+
8
+ # When in dev/qa we may need to provide credentials
9
+ # if ELS has not been setup
10
+ # this will be valid if a known cookie exists
11
+ def new
12
+ @els_identity = get_identity rescue nil
13
+ if @els_identity
14
+ session[:els_token] = @els_identity.token_id
15
+ Rails.cache.write(session[:els_token], @els_identity,
16
+ :namespace => "els_identity",
17
+ :expires_in => 1200)
18
+ go_back
19
+ end
20
+ # or get some login details
21
+ end
22
+
23
+ # Should not get here during production
24
+ def create
25
+ begin
26
+ if params["override"]
27
+ # just fake the session
28
+ logger.debug("faking session with id #{params["username"]}")
29
+ @els_identity = ElsFaker.new(params["username"])
30
+ else
31
+ logger.debug("attempting to authenticate #{params["username"]}")
32
+ token = authenticate(params["username"],params["password"])
33
+ logger.debug("got token #{token}")
34
+ if token
35
+ @els_identity = get_token_identity(token)
36
+ flash[:notice] = "cannot retrieve identity" unless @els_identity
37
+ else
38
+ flash[:error] = "unable to authenticate"
39
+ end
40
+ end
41
+ rescue Exception => e
42
+ flash[:error] = "Something went wrong #{e.message}"
43
+ end
44
+ if @els_identity
45
+ update_and_return
46
+ else
47
+ render :new
48
+ end
49
+ end
50
+
51
+ def destroy
52
+ Rails.cache.delete(session[:els_token])
53
+ session[:els_token] = nil
54
+ cookies.delete(ELS_CONFIG['cookie'], :domain => request.env["SERVER_NAME"])
55
+ redirect_to els_session_new_path
56
+ end
57
+
58
+ private
59
+
60
+ # This app should really be running behind an els processor
61
+ # stashing the els token against the current host should allow
62
+ # for a better dev/qa experience without affecting production
63
+ def stash_cookie
64
+ cookies[ELS_CONFIG['cookie']] = {
65
+ :value => @els_identity.token_id,
66
+ :domain => request.env["SERVER_NAME"],
67
+ :path => '/',
68
+ :expires => Time.now + 24.hours
69
+ }
70
+ end
71
+
72
+ def update_and_return
73
+ stash_cookie
74
+ session[:els_token] = @els_identity.token_id
75
+ logger.debug("got token id #{session[:els_token]}")
76
+ Rails.cache.write(session[:els_token], @els_identity,
77
+ :namespace => "els_identity",
78
+ :expires_in => 1200)
79
+ go_back
80
+ end
81
+
82
+ def go_back
83
+ if session[:redirect_to] =~ /els_session\//
84
+ # Do not redirect back to a session action
85
+ redirect_to root_path
86
+ else
87
+ redirect_to session[:redirect_to]
88
+ end
89
+ end
90
+
91
+ end
@@ -0,0 +1,8 @@
1
+ # Simple class Used for development only
2
+ class ElsFaker < ElsToken::ElsIdentity
3
+ def initialize(cdid)
4
+ super
5
+ @name = cdid
6
+ @token_id = Random.rand
7
+ end
8
+ end
@@ -0,0 +1,41 @@
1
+ <h1>Oops! Authentication Required</h1>
2
+ <p>We are currently running with a <span class="env"><%= Rails.env %></span> configuration</p>
3
+
4
+ <div class='flash'>
5
+ <% if flash[:notice] %>
6
+ <p class="notice"><%= flash[:notice] %></p>
7
+ <% end %>
8
+
9
+ <% if flash[:error] %>
10
+ <p class="error"><%= flash[:error] %></p>
11
+ <% end %>
12
+ </div>
13
+
14
+ <% if Rails.env.eql? "development" %>
15
+ <p>As a convenience, anyone can login as anyone when in dev mode - just enter a valid cdid and go</p>
16
+ <p>If you need to test real authentication, uncheck the override box and enter a UAT password.<br>
17
+ If you don't know what your UAT cdid password is then speak to someone in EIO@teamaol.com</p>
18
+ <% else %>
19
+ <p>This login screen should only appear when in development mode so something has gone wrong.<br>
20
+ However, you can still use the system if you enter valid cdid credentials.<br>
21
+ Someone has been notified of the situation so don't worry :)
22
+ </p>
23
+ <% end %>
24
+
25
+ <%= form_tag els_session_create_path, :class => "els_session" do %>
26
+ <div class="field">
27
+ <%= label_tag :username %>
28
+ <%= text_field_tag :username, params[:username] %>
29
+ </div>
30
+ <div class="field<%= Rails.env.eql?("development") ? ' default_hidden' : '' %>">
31
+ <%= label_tag :password %>
32
+ <%= password_field_tag :password, params[:password] %>
33
+ </div>
34
+ <% if Rails.env.eql? "development" %>
35
+ <div class="field">
36
+ <%= label_tag "Override: Just log me in and forget the password. I know what I'm doing, honest :)" %>
37
+ <%= check_box_tag :override, params[:override] %>
38
+ </div>
39
+ <% end %>
40
+ <div class="actions"><%= submit_tag "Log in" %></div>
41
+ <% end %>
@@ -0,0 +1,4 @@
1
+ <h1>Session Info<h1>
2
+ <div class='field'>
3
+ <p>Identity: <%= @els_identity.inspect %></p>
4
+ </div>
@@ -1,12 +1,17 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
- <title>Dummy</title>
4
+ <title>ElsSession</title>
5
5
  <%= stylesheet_link_tag "application", :media => "all" %>
6
6
  <%= javascript_include_tag "application" %>
7
7
  <%= csrf_meta_tags %>
8
8
  </head>
9
9
  <body>
10
+ <% if @els_identity %>
11
+ <div class='els_logout'>
12
+ <%= button_to "logout", els_session_destroy_path, :method => :delete %>
13
+ </div>
14
+ <% end %>
10
15
 
11
16
  <%= yield %>
12
17
 
@@ -7,50 +7,14 @@ require "els_token"
7
7
 
8
8
  module Dummy
9
9
  class Application < Rails::Application
10
- # Settings in config/environments/* take precedence over those specified here.
11
- # Application configuration should go into files in config/initializers
12
- # -- all .rb files in that directory are automatically loaded.
13
10
 
14
- # Custom directories with classes and modules you want to be autoloadable.
15
- # config.autoload_paths += %W(#{config.root}/extras)
16
-
17
- # Only load the plugins named here, in the order given (default is alphabetical).
18
- # :all can be used as a placeholder for all plugins not explicitly named.
19
- # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
20
-
21
- # Activate observers that should always be running.
22
- # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
23
-
24
- # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
25
- # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
26
- # config.time_zone = 'Central Time (US & Canada)'
27
-
28
- # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
29
- # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
30
- # config.i18n.default_locale = :de
31
-
32
- # Configure the default encoding used in templates for Ruby 1.9.
33
11
  config.encoding = "utf-8"
34
-
35
- # Configure sensitive parameters which will be filtered from the log file.
36
12
  config.filter_parameters += [:password]
37
-
38
- # Use SQL instead of Active Record's schema dumper when creating the database.
39
- # This is necessary if your schema can't be completely dumped by the schema dumper,
40
- # like if you have constraints or database-specific column types
41
- # config.active_record.schema_format = :sql
42
-
43
- # Enforce whitelist mode for mass assignment.
44
- # This will create an empty whitelist of attributes available for mass-assignment for all models
45
- # in your app. As such, your models will need to explicitly whitelist or blacklist accessible
46
- # parameters by using an attr_accessible or attr_protected declaration.
47
- # config.active_record.whitelist_attributes = true
48
-
49
- # Enable the asset pipeline
50
13
  config.assets.enabled = true
51
-
52
- # Version of your assets, change this if you want to expire all your assets
53
14
  config.assets.version = '1.0'
15
+ config.cache_store = :memory_store
16
+ #, :size => 100.megabytes
17
+ #, :namespace => "els_identity", :expires_in => 1200
54
18
  end
55
19
  end
56
20
 
@@ -0,0 +1,21 @@
1
+ development:
2
+ uri: https://elsuat-sso.corp.aol.com/opensso/identity
3
+ cookie: iPlanetDirectoryProuat
4
+
5
+ test:
6
+ faker:
7
+ name: neilcuk
8
+ employee_number: 09095
9
+ roles:
10
+ - Passport Admins
11
+ - Domain Users
12
+ uri: https://els-sso.corp.aol.com/opensso/identity
13
+ cookie: iPlanetDirectoryPro
14
+
15
+ uat:
16
+ uri: https://els-sso.corp.aol.com/opensso/identity
17
+ cookie: iPlanetDirectoryPro
18
+
19
+ production:
20
+ uri: https://els-sso.corp.aol.com/opensso/identity
21
+ cookie: iPlanetDirectoryPro
@@ -11,7 +11,7 @@ Dummy::Application.configure do
11
11
 
12
12
  # Show full error reports and disable caching
13
13
  config.consider_all_requests_local = true
14
- config.action_controller.perform_caching = false
14
+ config.action_controller.perform_caching = true
15
15
 
16
16
  # Don't care if the mailer can't send
17
17
  config.action_mailer.raise_delivery_errors = false
@@ -0,0 +1,67 @@
1
+ Dummy::Application.configure do
2
+ # Settings specified here will take precedence over those in config/application.rb
3
+
4
+ # Code is not reloaded between requests
5
+ config.cache_classes = true
6
+
7
+ # Full error reports are disabled and caching is turned on
8
+ config.consider_all_requests_local = false
9
+ config.action_controller.perform_caching = true
10
+
11
+ # Disable Rails's static asset server (Apache or nginx will already do this)
12
+ config.serve_static_assets = false
13
+
14
+ # Compress JavaScripts and CSS
15
+ config.assets.compress = true
16
+
17
+ # Don't fallback to assets pipeline if a precompiled asset is missed
18
+ config.assets.compile = false
19
+
20
+ # Generate digests for assets URLs
21
+ config.assets.digest = true
22
+
23
+ # Defaults to Rails.root.join("public/assets")
24
+ # config.assets.manifest = YOUR_PATH
25
+
26
+ # Specifies the header that your server uses for sending files
27
+ # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
28
+ # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
29
+
30
+ # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
31
+ # config.force_ssl = true
32
+
33
+ # See everything in the log (default is :info)
34
+ # config.log_level = :debug
35
+
36
+ # Prepend all log lines with the following tags
37
+ # config.log_tags = [ :subdomain, :uuid ]
38
+
39
+ # Use a different logger for distributed setups
40
+ # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
41
+
42
+ # Use a different cache store in production
43
+ # config.cache_store = :mem_cache_store
44
+
45
+ # Enable serving of images, stylesheets, and JavaScripts from an asset server
46
+ # config.action_controller.asset_host = "http://assets.example.com"
47
+
48
+ # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
49
+ # config.assets.precompile += %w( search.js )
50
+
51
+ # Disable delivery errors, bad email addresses will be ignored
52
+ # config.action_mailer.raise_delivery_errors = false
53
+
54
+ # Enable threaded mode
55
+ # config.threadsafe!
56
+
57
+ # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
58
+ # the I18n.default_locale when a translation can not be found)
59
+ config.i18n.fallbacks = true
60
+
61
+ # Send deprecation notices to registered listeners
62
+ config.active_support.deprecation = :notify
63
+
64
+ # Log the query plan for queries taking more than this (works
65
+ # with SQLite, MySQL, and PostgreSQL)
66
+ # config.active_record.auto_explain_threshold_in_seconds = 0.5
67
+ end
@@ -1,4 +1,4 @@
1
- ELS_CONFIG = YAML.load_file("#{Rails.root}/config/els.yml")["test"]
1
+ ELS_CONFIG = YAML.load_file("#{Rails.root}/config/els_token.yml")[Rails.env]
2
2
 
3
3
  class ElsTester < ActionController::Base
4
4
  include ElsToken
@@ -1,60 +1,14 @@
1
1
  Dummy::Application.routes.draw do
2
- get "hello/index"
3
-
4
- # The priority is based upon order of creation:
5
- # first created -> highest priority.
6
-
7
- # Sample of regular route:
8
- # match 'products/:id' => 'catalog#view'
9
- # Keep in mind you can assign values other than :controller and :action
10
-
11
- # Sample of named route:
12
- # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
13
- # This route can be invoked with purchase_url(:id => product.id)
14
-
15
- # Sample resource route (maps HTTP verbs to controller actions automatically):
16
- # resources :products
17
-
18
- # Sample resource route with options:
19
- # resources :products do
20
- # member do
21
- # get 'short'
22
- # post 'toggle'
23
- # end
24
2
  #
25
- # collection do
26
- # get 'sold'
27
- # end
28
- # end
29
-
30
- # Sample resource route with sub-resources:
31
- # resources :products do
32
- # resources :comments, :sales
33
- # resource :seller
34
- # end
35
-
36
- # Sample resource route with more complex sub-resources
37
- # resources :products do
38
- # resources :comments
39
- # resources :sales do
40
- # get 'recent', :on => :collection
41
- # end
42
- # end
43
-
44
- # Sample resource route within a namespace:
45
- # namespace :admin do
46
- # # Directs /admin/products/* to Admin::ProductsController
47
- # # (app/controllers/admin/products_controller.rb)
48
- # resources :products
49
- # end
50
-
51
- # You can have the root of your site routed with "root"
52
- # just remember to delete public/index.html.
53
- # root :to => 'welcome#index'
3
+ # session handlers
4
+ #
5
+ get "els_session/new"
54
6
 
55
- # See how all your routes lay out with "rake routes"
7
+ get "els_session/show"
8
+
9
+ post "els_session/create"
56
10
 
57
- # This is a legacy wild controller route that's not recommended for RESTful applications.
58
- # Note: This route will make all actions in every controller accessible via GET requests.
59
- # match ':controller(/:action(/:id))(.:format)'
11
+ delete "els_session/destroy"
12
+
13
+ root :to => 'els_session#show'
60
14
  end