ls-omniauth 3.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +99 -0
  4. data/Rakefile +22 -0
  5. data/app/controllers/ls_omniauth/omniauth_controller.rb +60 -0
  6. data/app/helpers/ls_omniauth/omniauth_helper.rb +72 -0
  7. data/app/models/ls_omniauth/abstract_session.rb +17 -0
  8. data/app/models/ls_omniauth/auth_sessions.rb +10 -0
  9. data/app/models/ls_omniauth/config.rb +10 -0
  10. data/config/initializers/load_lsomniauth_config.rb +6 -0
  11. data/config/initializers/ls-omniauth.rb +11 -0
  12. data/config/routes.rb +6 -0
  13. data/lib/ls-omniauth.rb +4 -0
  14. data/lib/ls-omniauth/engine.rb +7 -0
  15. data/lib/ls-omniauth/version.rb +3 -0
  16. data/spec/controllers/ls_omniauth/omniauth_controller_spec.rb +56 -0
  17. data/spec/dummy/README.rdoc +5 -0
  18. data/spec/dummy/Rakefile +7 -0
  19. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  20. data/spec/dummy/app/controllers/private_controller.rb +5 -0
  21. data/spec/dummy/app/controllers/public_controller.rb +5 -0
  22. data/spec/dummy/app/controllers/secure_application_controller.rb +9 -0
  23. data/spec/dummy/app/views/layouts/application.html.erb +22 -0
  24. data/spec/dummy/config.ru +4 -0
  25. data/spec/dummy/config/application.rb +63 -0
  26. data/spec/dummy/config/boot.rb +10 -0
  27. data/spec/dummy/config/environment.rb +5 -0
  28. data/spec/dummy/config/environments/development.rb +37 -0
  29. data/spec/dummy/config/environments/production.rb +67 -0
  30. data/spec/dummy/config/environments/test.rb +37 -0
  31. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  32. data/spec/dummy/config/initializers/inflections.rb +15 -0
  33. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  34. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  35. data/spec/dummy/config/initializers/session_store.rb +8 -0
  36. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  37. data/spec/dummy/config/locales/en.yml +5 -0
  38. data/spec/dummy/config/ls-omniauth.yml +9 -0
  39. data/spec/dummy/config/routes.rb +7 -0
  40. data/spec/dummy/log/development.log +7 -0
  41. data/spec/dummy/public/404.html +26 -0
  42. data/spec/dummy/public/422.html +26 -0
  43. data/spec/dummy/public/500.html +25 -0
  44. data/spec/dummy/public/favicon.ico +0 -0
  45. data/spec/dummy/script/rails +6 -0
  46. data/spec/dummy/spec/controllers/private_controller_spec.rb +39 -0
  47. data/spec/dummy/spec/controllers/public_controller_spec.rb +10 -0
  48. data/spec/dummy/spec/spec_helper.rb +27 -0
  49. data/spec/helpers/omniauth_helper_spec.rb +12 -0
  50. data/spec/ls_omniauth_spec.rb +6 -0
  51. data/spec/models/ls_omniauth/config_spec.rb +69 -0
  52. data/spec/spec_helper.rb +16 -0
  53. metadata +229 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a7db0c922e3ee7c046ebe1777f687954bd54fdba
4
+ data.tar.gz: 6aca405d80f430cf2f18283d6ffb2b2a7b558b99
5
+ SHA512:
6
+ metadata.gz: 52a91fac3c78a0a09f84d125ba54934205f26cee85d8f766a8afa90e1d83572dffcba23c3f38814d937455acb2f72ac7bad3ab9d984bd1a7a7ea81ded6ae4720
7
+ data.tar.gz: 03840409523bac80984361385259b7022808166d646c0facb2b1429ec63aa16f9d29a9e70ff9be55fa70c0e0d4a9f0789e57f6d413841d93d503f12256bbf6ac
@@ -0,0 +1,20 @@
1
+ Copyright 2013 YOURNAME
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.
@@ -0,0 +1,99 @@
1
+ # LsOmniauth
2
+ LsOmniauth is a Rails Engine that provides authentication via Google OAuth.
3
+
4
+ You can allow all users with a livingsocial.com or hungrymachine.com email
5
+ address to access protected parts of your app.
6
+
7
+ You can also whitelist the email addresses that are authorized to access
8
+ protected resources.
9
+
10
+ ## Getting Started
11
+ _Note: There is a dummy application in `spec/dummy` where this setup is used._
12
+
13
+ #### Mount the engine
14
+ First off, we'll need to mount the engine in your `config/routes.rb`:
15
+ ```ruby
16
+ Dummy::Application.routes.draw do
17
+ get 'public' => 'public#index', as: :public_page
18
+ get 'private' => 'private#index', as: :private_page
19
+
20
+ mount LsOmniauth::Engine, at: "/auth", as: 'ls_omniauth' # <------ The engine will provide its functionality at /auth in your app
21
+ root to: 'public#index'
22
+ end
23
+ ```
24
+
25
+ #### Protect controllers
26
+ Adding the following lines to a controller will deny access to anyone who does not
27
+ authenticate with a LivingSocial.com or HungryMachine.com address.
28
+ ```ruby
29
+ class SecureApplicationController < ApplicationController
30
+ include LsOmniauth::OmniauthHelper
31
+ before_filter { |c| c.require_authorization domains: ["livingsocial.com","hungrymachine.com"] }
32
+ end
33
+ ```
34
+
35
+ #### Restrict access to only specific users
36
+ Add a `config/ls-omniauth.yml` file in your app using a format like this to define a `general_access` group.
37
+ You can have several groups under `authorized_users`.
38
+ Also note that the client id and secret configurations are a requirement as of version 2.0.0
39
+
40
+ ```yaml
41
+ client: &client
42
+ client_id: 12345.apps.googleusercontent.com
43
+ client_secret: 12345
44
+ development:
45
+ <<: *client
46
+ dev_mode: true
47
+ production:
48
+ <<: *client
49
+ authorized_users:
50
+ general_access:
51
+ - dan.rabinowitz@hungrymachine.com
52
+ - tyler.montgomery@hungrymachine.com
53
+ super_secret_access:
54
+ - the.nsa@hungrymachine.com
55
+ ```
56
+
57
+ Then, add the following lines to a controller:
58
+ ```ruby
59
+ class SecureApplicationController < ApplicationController
60
+ include LsOmniauth::OmniauthHelper
61
+ before_filter { |c| c.require_authorization group: "general_access" }
62
+ end
63
+ ```
64
+
65
+ ## Dev Mode
66
+
67
+ It's recommended that for test and dev environments, you enable dev mode by setting the dev_mode key to true in ls-omniauth.yml
68
+
69
+ ```
70
+ dev_mode: true
71
+ ```
72
+
73
+ This will no-op the require_authorization method to prevent any live requests from being made while you're developing or testing.
74
+
75
+ ## Routes
76
+
77
+ LsOmniauth adds a `sign_in` and `sign_out` route for you. They will work at `/auth/sign_in` and `/auth/sign_out` (if you mount your
78
+ app at in your routes at `/auth`).
79
+
80
+ These routes won't pollute your app's routes. You can access them in views or controllers almost like normal:
81
+ ```ruby
82
+ redirect_to ls_omniauth.sign_out_url # <---- notice the ls_omniauth prepended to the url helper
83
+ ```
84
+
85
+ ## Redirect URL authorization
86
+
87
+ In order to use this gem, you'll need an active Google Oauth client id and client secret. Additionally, you'll need to add your application's redirect url to the list of OAuth authorized routes for that Oauth api client. You can find and edit those lists here:
88
+
89
+ * [Digital Marketing] (https://console.developers.google.com/apis/credentials/oauthclient/1041688722300.apps.googleusercontent.com?project=hungrymachine.com:arctic-app-831)
90
+
91
+
92
+ ## TODO:
93
+ Are we recreating the wheel here? Can this all be done with already-existing gems? Devise?
94
+
95
+ Is the return_uri code working? If not, can it be made to work?
96
+
97
+ ##License
98
+ This project rocks and uses MIT-LICENSE.
99
+
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+
8
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
9
+ load 'rails/tasks/engine.rake'
10
+
11
+ Bundler::GemHelper.install_tasks
12
+
13
+ Dir[File.join(File.dirname(__FILE__), 'tasks/**/*.rake')].each {|f| load f }
14
+
15
+ require 'rspec/core'
16
+ require 'rspec/core/rake_task'
17
+
18
+ desc "Run all specs in spec directory (excluding plugin specs)"
19
+
20
+ RSpec::Core::RakeTask.new(:spec)
21
+
22
+ task :default => :spec
@@ -0,0 +1,60 @@
1
+ module LsOmniauth
2
+ class OmniauthController < ActionController::Base
3
+ include Rails.application.routes.url_helpers
4
+
5
+ before_filter :set_return_uri
6
+
7
+ def authenticate
8
+ auth_response = request.env['omniauth.auth']
9
+ email = auth_response.info.email
10
+
11
+ LsOmniauth::AuthSessions.new(session).tap {|session|
12
+ session.auth.set(email)
13
+ origin = session.origin.getOrElse("/")
14
+ Rails.logger.warn "origin = #{origin}"
15
+ session.origin.clear
16
+ redirect_to origin
17
+ }
18
+ end
19
+
20
+ def new_authentication
21
+ LsOmniauth::AuthSessions.new(session).origin.set(params[:return_uri]) if params[:return_uri]
22
+ LsOmniauth::AuthSessions.new(session).auth.clear
23
+ url = oauth_url(params)
24
+ redirect_to url
25
+ end
26
+
27
+ def revoke_authentication
28
+ return_uri = return_uri(session)
29
+ clear_authentication_sessions(session)
30
+ render :text => "<div class='notification'>your have been logged out click <a href='#{ls_omniauth.sign_in_url}?return_uri=#{return_uri}' target='_self'>here</a> to log back in</div>"
31
+ end
32
+
33
+ private
34
+ def set_return_uri
35
+ session[:return_uri] = request.referrer if (request.referrer !~ /sign_out/)
36
+ end
37
+
38
+ def return_uri(session)
39
+ session.delete(:return_uri) || (defined?(root_url) && root_url) || '/'
40
+ end
41
+
42
+ def clear_authentication_sessions(session)
43
+ LsOmniauth::AuthSessions.new(session).tap {|s|
44
+ s.auth.clear
45
+ s.origin.clear
46
+ }
47
+ end
48
+
49
+ def oauth_url(params)
50
+ params = params.dup
51
+ provider = params.delete(:provider) || 'google_oauth2'
52
+ url = route_for_provider(provider)
53
+ params.empty? ? url : "#{url}?#{params.to_query}"
54
+ end
55
+
56
+ def route_for_provider(provider)
57
+ "/auth/#{provider}"
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,72 @@
1
+ module LsOmniauth::OmniauthHelper
2
+ def require_authentication
3
+ when_not_in_dev_mode {
4
+ sessions = LsOmniauth::AuthSessions.new(session)
5
+ if sessions.auth.get.blank?
6
+ sessions.origin.set("#{request.protocol}#{request.host_with_port}#{request.fullpath}")
7
+ redirect_to ls_omniauth.sign_in_url and return false
8
+ end
9
+ true
10
+ }
11
+ end
12
+
13
+ def require_authorization(options = {})
14
+ when_not_in_dev_mode {
15
+ return unless require_authentication
16
+
17
+ sessions = LsOmniauth::AuthSessions.new(session)
18
+ email = sessions.auth.get
19
+
20
+
21
+ options.symbolize_keys!
22
+ if options[:domains].respond_to? :include?
23
+ email_domain = email.match(/[\w]+\.com/)[0]
24
+ unless options[:domains].map(&:upcase).include? email_domain.upcase
25
+ render_access_denied and return
26
+ end
27
+ end
28
+
29
+ if options.has_key? :group
30
+ if !email_in_group(email, options[:group])
31
+ render_access_denied and return
32
+ end
33
+ end
34
+ }
35
+ end
36
+
37
+ def current_user_in_group(group)
38
+ email_in_group(email_for_current_user, group)
39
+ end
40
+
41
+ def when_not_in_dev_mode(&block)
42
+ if !running_in_dev_mode?
43
+ yield
44
+ end
45
+ end
46
+
47
+ module_function
48
+
49
+ def running_in_dev_mode?
50
+ LS_OMNIAUTH.config.running_in_dev_mode?
51
+ end
52
+
53
+ def authorized_users
54
+ @authorized_users ||= (LS_OMNIAUTH.config[:authorized_users] || {})
55
+ end
56
+
57
+ def authorized_group_users(group)
58
+ authorized_users[group] || []
59
+ end
60
+
61
+ def email_for_current_user
62
+ LsOmniauth::AuthSessions.new(session).auth.get
63
+ end
64
+
65
+ def email_in_group(email, group)
66
+ authorized_group_users(group).map(&:upcase).include?(email.to_s.upcase)
67
+ end
68
+
69
+ def render_access_denied
70
+ render :text => "<div class='notification error'>You are not authorized to view this resource. Sorry!</div>", :status => 401
71
+ end
72
+ end
@@ -0,0 +1,17 @@
1
+ class LsOmniauth::AbstractSession
2
+ attr_reader :session, :key, :value
3
+
4
+ def initialize(session, key);
5
+ @session = session
6
+ @key = key
7
+ @value = session[key]
8
+ end
9
+
10
+ def set(value); @session[@key] = value end
11
+ def get; @session[@key] end
12
+ def getOrElse(v2)
13
+ v = get
14
+ v.blank? ? v2 : v
15
+ end
16
+ def clear; @session[@key] = nil end
17
+ end
@@ -0,0 +1,10 @@
1
+ class LsOmniauth::AuthSessions
2
+ AUTH_SESSION_KEY = "ls_auth_user"
3
+ AUTH_REQUEST_ORIGIN = "ls_auth_request_origin"
4
+
5
+ attr_reader :auth, :origin
6
+ def initialize(session)
7
+ @auth = LsOmniauth::AbstractSession.new(session, AUTH_SESSION_KEY)
8
+ @origin = LsOmniauth::AbstractSession.new(session, AUTH_REQUEST_ORIGIN)
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ class LsOmniauth::Config < HashWithIndifferentAccess
2
+
3
+ def running_in_dev_mode?
4
+ self[:dev_mode].to_s == true.to_s && !LS_OMNIAUTH.environment.production?
5
+ end
6
+
7
+ def valid?
8
+ self.slice(*[:client_id, :client_secret]).values.compact.length == 2
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ config_file = Rails.root.join("config/ls-omniauth.yml")
2
+
3
+ LS_OMNIAUTH = OpenStruct.new(
4
+ config: LsOmniauth::Config.new(File.exists?(config_file) ? YAML.load_file(config_file)[Rails.env] : {}),
5
+ environment: Rails.env
6
+ )
@@ -0,0 +1,11 @@
1
+ # -*- encoding : utf-8 -*-
2
+ Rails.application.config.middleware.use OmniAuth::Builder do
3
+ config = LS_OMNIAUTH.config
4
+
5
+ if config.valid?
6
+ provider :google_oauth2, config[:client_id], config[:client_secret], {:access_type => 'online', :approval_prompt => 'auto'}
7
+ else
8
+ Rails.logger.error("ERROR: ls-omniauth.yml is missing or not properly configured. Please ensure that both a client id and client secret have been set.")
9
+ end
10
+ end
11
+
@@ -0,0 +1,6 @@
1
+ # Rails.application.routes.draw do
2
+ ::LsOmniauth::Engine.routes.draw do
3
+ get '/:provider/callback', :to => 'omniauth#authenticate'
4
+ get '/sign_in', :to => 'omniauth#new_authentication', as: :sign_in
5
+ get '/sign_out', :to => 'omniauth#revoke_authentication', as: :sign_out
6
+ end
@@ -0,0 +1,4 @@
1
+ require "ls-omniauth/engine"
2
+
3
+ module LsOmniauth
4
+ end
@@ -0,0 +1,7 @@
1
+ module LsOmniauth
2
+ class Engine < ::Rails::Engine
3
+ require 'omniauth'
4
+ require 'omniauth-google-oauth2'
5
+ isolate_namespace LsOmniauth
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module LsOmniauth
2
+ VERSION = "3.0.3"
3
+ end
@@ -0,0 +1,56 @@
1
+ require "spec_helper"
2
+
3
+ describe LsOmniauth::OmniauthController, :type => :controller do
4
+ routes { LsOmniauth::Engine.routes }
5
+
6
+ describe "GET authenticate" do
7
+ before :each do
8
+ info = double
9
+ expect(info).to receive(:email).and_return('user@domain.com')
10
+
11
+ auth_response = double(:info => info)
12
+
13
+ controller.request.env['omniauth.auth'] = auth_response
14
+
15
+ LsOmniauth::AuthSessions.new(session).origin.set('/blah')
16
+ end
17
+
18
+ it "should set the email key of the session" do
19
+ get :authenticate, provider: :google_oauth2
20
+ expect(session['ls_auth_user']).to eq 'user@domain.com'
21
+ end
22
+
23
+ it "should redirect" do
24
+ get :authenticate, provider: :google_oauth2
25
+ expect(response).to redirect_to("/blah")
26
+ end
27
+ end
28
+
29
+ describe "GET new_authentication" do
30
+ before :each do
31
+ LsOmniauth::AuthSessions.new(session).auth.set('user@domain.com')
32
+ end
33
+
34
+ it "should redirect" do
35
+ get :new_authentication
36
+ expect(response).to redirect_to("/auth/google_oauth2?action=new_authentication&controller=ls_omniauth%2Fomniauth")
37
+ end
38
+
39
+ it "should clear the user" do
40
+ get :new_authentication
41
+ expect(session['ls_auth_user']).to eq nil
42
+ end
43
+ end
44
+
45
+ describe "GET revoke_authentication" do
46
+ before :each do
47
+ LsOmniauth::AuthSessions.new(session).auth.set('user@domain.com')
48
+ end
49
+
50
+ it "should clear the user" do
51
+ get :revoke_authentication
52
+ expect(session['ls_auth_user']).to eq nil
53
+ end
54
+ end
55
+
56
+ end
@@ -0,0 +1,5 @@
1
+ This is the dummy app used for testing ls-omniauth
2
+
3
+ These are the two pages to test:
4
+ * http://localhost:3004/public
5
+ * http://localhost:3004/private
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
3
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4
+
5
+ require File.expand_path('../config/application', __FILE__)
6
+
7
+ Dummy::Application.load_tasks