omniauth-rails 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +47 -3
  3. data/Rakefile +1 -0
  4. data/app/assets/stylesheets/omniauth/rails/application.css +11 -12
  5. data/app/controllers/omniauth/rails/{require_authentication.rb → authentication_concern.rb} +13 -3
  6. data/app/controllers/omniauth/rails/{require_authorization.rb → authorization_concern.rb} +13 -4
  7. data/app/controllers/omniauth/rails/controllers_concern.rb +11 -0
  8. data/app/controllers/omniauth/rails/flash.rb +2 -21
  9. data/app/models/omniauth/rails/authentication_request.rb +5 -2
  10. data/app/views/omniauth/rails/forbidden.html +1 -0
  11. data/app/views/omniauth/rails/sessions/destroy.html.erb +3 -3
  12. data/config/initializers/omniauth_rails.rb +1 -34
  13. data/lib/omniauth/rails.rb +2 -0
  14. data/lib/omniauth/rails/configuration.rb +5 -1
  15. data/lib/omniauth/rails/configurator.rb +103 -0
  16. data/lib/omniauth/rails/engine.rb +13 -0
  17. data/lib/omniauth/rails/provider.rb +20 -0
  18. data/lib/omniauth/rails/provider/google_oauth2.rb +34 -0
  19. data/lib/omniauth/rails/version.rb +1 -1
  20. data/lib/tasks/mutant.rake +8 -0
  21. data/spec/controllers/application_controller_spec.rb +0 -1
  22. data/spec/controllers/authentication_concern_spec.rb +40 -0
  23. data/spec/examples.txt +20 -15
  24. data/spec/lib/omniauth/rails/configurator_spec.rb +45 -0
  25. data/spec/models/omniauth/rails/authorization_types/emails_spec.rb +0 -2
  26. data/spec/models/omniauth/rails/authorization_types/regex_spec.rb +0 -2
  27. data/spec/rails_helper_for_engine.rb +1 -1
  28. data/spec/spec_helper.rb +2 -0
  29. data/spec/test_app/app/controllers/private_controller.rb +0 -1
  30. data/spec/test_app/config/application.rb +1 -0
  31. data/spec/test_app/config/omniauth_rails.yml +6 -0
  32. data/spec/test_app/config/routes.rb +0 -3
  33. data/spec/test_app/log/development.log +2333 -0
  34. data/spec/test_app/log/test.log +50737 -0
  35. data/spec/test_app/spec/requests/private_controller_spec.rb +33 -6
  36. data/spec/test_app/spec/requests/sessions_controller_spec.rb +11 -9
  37. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/7w/7wvYXBtPYrpJ0AsySxiCGKfyqkX-mahHfSlLe8bkKLg.cache +1 -0
  38. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/Em/EmJbUP6PHR0uxNqWjp0TDKiG2j-89vsmX0dfwbmvzkc.cache +0 -0
  39. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/HS/HScCeVhpnmJmuQX7s7oOUbEmBL2KWC40o78iLC-3e3M.cache +1 -0
  40. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/O7/O7W_v6SN36f1tRfV6clZc10p24T7-Ihb3_totn6VrVA.cache +0 -0
  41. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/S-/S-cHz0vJ4VrdXCUiB5fP9TR5Viz885rz10Wgix-urAA.cache +0 -0
  42. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/WJ/WJhc1q0sGH7WcpvF09oA0iw4iAdiQkHerW6hdCHwxHo.cache +0 -0
  43. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/jK/jK2TgENQlNR4Qvt28Euq9dEK5k_UQuVSbofD4vWeTno.cache +0 -0
  44. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/n0/n0Kk2o2xNYUkuiXPYuld9V2t6GRLzY5YfDfnqdfKlRo.cache +1 -0
  45. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/nF/nFB84MNiFDrMN0WelMUdomScBrhYdJ4b8LPhXT3v8C4.cache +1 -0
  46. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/xW/xW2O0qRLEOz9w_8VDiVMAztr-N8UrUvx8v5EEV7mFBU.cache +0 -0
  47. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/yb/ybtAnaaqo1s0ZXeIKLc5sW1EovhL83HYrgFcKGHUa0Q.cache +1 -0
  48. data/spec/test_app/tmp/pids/server.pid +1 -1
  49. metadata +50 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d56083f2dbbbb8598f6740095b9df4dd967269be
4
- data.tar.gz: 905900d024010eee45dc8025a958e80a167ea269
3
+ metadata.gz: 059f75d1200dc3b91d801bd9123a59735abf41c7
4
+ data.tar.gz: fafa8b4b4d0a349c4af547544057b98e4653fa5b
5
5
  SHA512:
6
- metadata.gz: 418f5a1cafc19fd179bd4bb78b80ec45962c410a3f9aef1f41dc5eaa6aaaddf83b65cb13d0d51234d484d6a5535df8f0c5b6a2f7ae3594f654d6e57449414d29
7
- data.tar.gz: 69b3d71ee4887a09f8283c0304391901483b921384f9976805b80b10e109e6149364365cd189dce427cf5133a80a0cd529b873c8f8100ff29e437d4bfcbfc306
6
+ metadata.gz: 773c1f3d104401f4f59158cd9cc2d237368a3e94643e6e7bec0d56fc445e90b4bf9c619be862b758a5277e6a125c4e2ab011d2be765800fedf8a45f0fc5b72f4
7
+ data.tar.gz: 2ae36708dd6e522bdb7ebc20a30577bed4c53674d0fc10892ceeb78d4f66300f4fe50d1cc7a811ef5a772575d853ece0a69aba661d6712036b955c7b483ea59b
data/README.md CHANGED
@@ -1,6 +1,13 @@
1
1
  # Omniauth::Rails
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/omniauth-rails.svg)](https://badge.fury.io/rb/omniauth-rails)
4
+ [![Code Climate](https://codeclimate.com/github/danrabinowitz/omniauth-rails/badges/gpa.svg)](https://codeclimate.com/github/danrabinowitz/omniauth-rails)
5
+ [![Build Status](https://travis-ci.org/danrabinowitz/omniauth-rails.svg?branch=master)](https://travis-ci.org/danrabinowitz/omniauth-rails)
6
+ [![Test Coverage](https://codeclimate.com/github/danrabinowitz/omniauth-rails/badges/coverage.svg)](https://codeclimate.com/github/danrabinowitz/omniauth-rails/coverage)
7
+
2
8
  A Rails Engine to make it as easy as possible to add oauth authentication to a Rails app.
3
9
 
10
+
4
11
  The canonical use case is this:
5
12
  You build a simple Rails app for your company. It is for internal use only. Your company uses Google Apps for gmail.
6
13
 
@@ -14,9 +21,8 @@ Authorization is handled separately.
14
21
 
15
22
  ## TODO
16
23
 
17
- * Add a "dev mode" override which simply skips all authentication.
18
-
19
- * Search for "TODO" in the code.
24
+ * Add a new AuthorizationType for groups of email addresses
25
+ * Run ```rake mutant``` and add all the specs.
20
26
 
21
27
  ## Usage
22
28
 
@@ -56,6 +62,33 @@ production:
56
62
  include Omniauth::Rails::RequireAuthentication
57
63
  ```
58
64
 
65
+ ## Additional configuration
66
+
67
+ ### Automount
68
+ By default, Omniauth::Rails sets automount to true. You can override this in the omniauth_rails.yml configuration file.
69
+
70
+ When automount is true (the default), the engine's routes are mounted in the host application's routes.
71
+
72
+ When automount is false, you need to add this line to your routes.rb:
73
+ ```ruby
74
+ mount Omniauth::Rails::Engine => OmniAuth.config.path_prefix
75
+ ```
76
+
77
+ ### path_prefix
78
+ The default path_prefix for Omniauth is "/auth". In the unlikely event that this
79
+ causes a conflict, it can be changed with the path_prefix configuration parameter.
80
+
81
+ ### autoload_in_application_controller
82
+ The default value of autoload_in_application_controller is true.
83
+
84
+ When it is true, the controller concerns are automatically included in ActionController::Base.
85
+
86
+ If there is a conflict in having those methods in all controllers, set autoload_in_application_controller to
87
+ false and manually add this line to any controllers which require authentication or authorization:
88
+ ```ruby
89
+ include Omniauth::Rails::ControllersConcern
90
+ ```
91
+
59
92
  ## Logging out
60
93
 
61
94
  In general, there's not much point in "logging out". It wipes the Omniauth::Rails session,
@@ -64,8 +97,19 @@ but the browser is still logged in to the provider, which has granted access to
64
97
 
65
98
  Bottom line: There's usually no reason to have a logout button when using Omniauth::Rails
66
99
 
100
+ ## Mutation Testing
101
+
102
+ Run ```rake mutant```
103
+ The output will appear on STDOUT and also in coverage/mutant.out
104
+
105
+ More info on reading the reports is here: https://github.com/mbj/mutant#reading-reports
106
+
67
107
  ## Contributing
68
108
  PRs are welcome!
69
109
 
110
+ ## Credit
111
+ Thanks to [Paul De Goes](https://github.com/pauldegoes) for the idea for this gem. He
112
+ built a similar gem for internal use at LivingSocial.
113
+
70
114
  ## License
71
115
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -17,6 +17,7 @@ end
17
17
 
18
18
  APP_RAKEFILE = File.expand_path("../spec/test_app/Rakefile", __FILE__)
19
19
  load "rails/tasks/engine.rake"
20
+ Rails.application.load_tasks
20
21
 
21
22
  load "rails/tasks/statistics.rake"
22
23
 
@@ -1,19 +1,18 @@
1
1
  form.button_to {
2
2
  display: inline;
3
- margin: 0;
4
3
  padding: 0;
5
4
  }
6
5
  form.button_to div { display: inline; }
7
6
  form.button_to input[type=submit] {
8
- margin: 0;
9
- padding: 0;
10
- -webkit-appearance: caret;
11
- background: none;
12
- border: none;
13
- font-size: inherit;
14
- font-family: inherit;
15
- cursor: pointer;
16
- text-decoration: underline;
17
- color: #0000FF;
18
- }
7
+ margin: 0;
8
+ padding: 0;
9
+ -webkit-appearance: caret;
10
+ -moz-appearance: caret;
11
+ background: none;
12
+ border: none;
13
+ font-size: inherit;
14
+ font-family: inherit;
15
+ cursor: pointer;
16
+ text-decoration: underline;
17
+ color: #0000FF;
19
18
  }
@@ -1,19 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
  module Omniauth
3
3
  module Rails
4
- module RequireAuthentication
4
+ module AuthenticationConcern
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do
8
8
  include Omniauth::Rails::ApplicationHelper
9
+ end
10
+
11
+ module ClassMethods
12
+ private
9
13
 
10
- # TODO: Do not add this before_action in dev_mode
11
- before_action :require_authentication
14
+ def require_authentication
15
+ before_action :require_authentication
16
+ end
12
17
  end
13
18
 
14
19
  private
15
20
 
16
21
  def require_authentication
22
+ if Configuration.dev_mode
23
+ ::Rails.logger.info "Omniauth::Rails: dev_mode is enabled. Skipping 'require_authentication'"
24
+ return
25
+ end
26
+
17
27
  redirect_to_sign_in_url unless authenticated?
18
28
  end
19
29
 
@@ -1,9 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  module Omniauth
3
3
  module Rails
4
- module RequireAuthorization
4
+ module AuthorizationConcern
5
5
  def self.included(klass)
6
- klass.include Omniauth::Rails::RequireAuthentication
7
6
  klass.extend ClassMethods
8
7
  end
9
8
 
@@ -11,7 +10,6 @@ module Omniauth
11
10
  private
12
11
 
13
12
  def require_authorization(params)
14
- # TODO: Do not add this before_action in dev_mode
15
13
  before_action { |c| c.require_authorization(params) }
16
14
  end
17
15
  end
@@ -19,7 +17,14 @@ module Omniauth
19
17
  protected
20
18
 
21
19
  def require_authorization(params)
22
- redirect_to_sign_in_url unless authorized?(params)
20
+ if Configuration.dev_mode
21
+ ::Rails.logger.info "Omniauth::Rails: dev_mode is enabled. Skipping 'require_authorization'"
22
+ return
23
+ end
24
+
25
+ require_authentication # Require authentication before authorization.
26
+ return if performed?
27
+ render_403_forbidden unless authorized?(params)
23
28
  end
24
29
 
25
30
  private
@@ -27,6 +32,10 @@ module Omniauth
27
32
  def authorized?(params)
28
33
  AuthorizationChecker.new(email: authenticated_email, params: params).authorized?
29
34
  end
35
+
36
+ def render_403_forbidden
37
+ render "omniauth/rails/forbidden", status: :forbidden, layout: false
38
+ end
30
39
  end
31
40
  end
32
41
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+ module Omniauth
3
+ module Rails
4
+ module ControllersConcern
5
+ def self.included(klass)
6
+ klass.include Omniauth::Rails::AuthenticationConcern
7
+ klass.include Omniauth::Rails::AuthorizationConcern
8
+ end
9
+ end
10
+ end
11
+ end
@@ -5,39 +5,20 @@ module Omniauth
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  def set_url_to_return_to_after_authentication
8
- # TODO: Sanitize these urls, to avoid phishing attacks
8
+ # Use caution when setting these urls.
9
+ # There are phishing risks associated with redirection, as described here:
9
10
  # See https://www.owasp.org/index.php/Unvalidated_Redirects_and_Forwards_Cheat_Sheet
10
11
  flash[:url_to_return_to_after_authentication] =
11
- # url_to_return_to_after_authentication_from_params ||
12
12
  url_to_return_to_after_authentication_from_flash ||
13
- # url_to_return_to_after_authentication_from_referer ||
14
13
  default_url_to_return_to_after_authentication
15
14
  end
16
15
 
17
16
  private
18
17
 
19
- # def url_to_return_to_after_authentication_from_params
20
- # return nil unless allow_url_to_return_to_after_authentication_from_params?
21
- # params[:return_to]
22
- # end
23
-
24
- # def allow_url_to_return_to_after_authentication_from_params?
25
- # false
26
- # end
27
-
28
18
  def url_to_return_to_after_authentication_from_flash
29
19
  flash[:url_to_return_to_after_authentication]
30
20
  end
31
21
 
32
- # def url_to_return_to_after_authentication_from_referer
33
- # return nil unless allow_url_to_return_to_after_authentication_from_referer?
34
- # request.referer
35
- # end
36
-
37
- # def allow_url_to_return_to_after_authentication_from_referer?
38
- # false
39
- # end
40
-
41
22
  def default_url_to_return_to_after_authentication
42
23
  Configuration.authenticated_root
43
24
  end
@@ -7,7 +7,6 @@ module Omniauth
7
7
  end
8
8
 
9
9
  def persist(authentication_session)
10
- # TODO: Store the provider in the session
11
10
  authentication_session.email = email
12
11
  authentication_session.expire_in(session_duration)
13
12
  end
@@ -17,7 +16,11 @@ module Omniauth
17
16
  attr_reader :request
18
17
 
19
18
  def email
20
- request.env["omniauth.auth"].info.email
19
+ info.email
20
+ end
21
+
22
+ def info
23
+ request.env["omniauth.auth"].info
21
24
  end
22
25
 
23
26
  def session_duration
@@ -0,0 +1 @@
1
+ ACCESS DENIED
@@ -1,6 +1,6 @@
1
- <div class='notification'>
2
- You have been logged out.
1
+ <p>
2
+ You are logged out.
3
3
  Click
4
4
  <%= link_to "here", omniauth_rails.sign_in_url, target: '_self' %>
5
5
  to log back in.
6
- </div>
6
+ </p>
@@ -1,35 +1,2 @@
1
1
  # frozen_string_literal: true
2
-
3
- config_hash = YAML.load(ERB.new(File.read("#{Rails.root}/config/omniauth_rails.yml")).result)[Rails.env]
4
-
5
- OmniAuth.config.logger = Rails.logger
6
-
7
- # TODO
8
- # OmniAuth.config.path_prefix = "/auth"
9
-
10
- Rails.application.config.middleware.use OmniAuth::Builder do
11
- if config_hash.present?
12
- raise "You must provide at least one oauth provider" unless config_hash["providers"]
13
- config_hash["providers"].each do |provider, provider_config|
14
- case provider
15
- when "google_oauth2"
16
- raise "Provider #{provider} requires a client_id" unless provider_config["client_id"]
17
- raise "Provider #{provider} requires a client_secret" unless provider_config["client_secret"]
18
-
19
- provider(:google_oauth2, provider_config["client_id"], provider_config["client_secret"],
20
- access_type: "online", approval_prompt: "auto")
21
- else
22
- raise "#{provider} is not currently handled by omniauth_rails."
23
- end
24
- end
25
- end
26
- end
27
-
28
- if config_hash["session_duration_in_seconds"].present?
29
- Omniauth::Rails::Configuration.session_duration = config_hash["session_duration_in_seconds"].seconds
30
- end
31
-
32
- raise "authenticated_root is required" if config_hash["authenticated_root"].blank?
33
- Omniauth::Rails::Configuration.authenticated_root = config_hash["authenticated_root"]
34
- raise "unauthenticated_root is required" if config_hash["unauthenticated_root"].blank?
35
- Omniauth::Rails::Configuration.unauthenticated_root = config_hash["unauthenticated_root"]
2
+ Omniauth::Rails::Configurator.from_default_config_file.configure
@@ -2,6 +2,8 @@
2
2
  require "omniauth/rails/engine"
3
3
 
4
4
  require "omniauth/rails/configuration"
5
+ require "omniauth/rails/configurator"
6
+ require "omniauth/rails/provider"
5
7
 
6
8
  module Omniauth
7
9
  module Rails
@@ -2,7 +2,11 @@
2
2
  module Omniauth
3
3
  module Rails
4
4
  class Configuration
5
- ATTRIBUTES = %i(authenticated_root unauthenticated_root session_duration logger).freeze
5
+ ATTRIBUTES = %i(
6
+ authenticated_root include_concern_in_application_controller
7
+ unauthenticated_root session_duration logger
8
+ dev_mode automount
9
+ ).freeze
6
10
 
7
11
  @session_duration = 1.hour
8
12
  @logger = ::Rails.logger
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+ module Omniauth
3
+ module Rails
4
+ class Configurator
5
+ REQUIRED_SETTINGS = %i(providers authenticated_root unauthenticated_root).freeze
6
+
7
+ def self.default_config_file
8
+ "#{::Rails.root}/config/omniauth_rails.yml"
9
+ end
10
+
11
+ def self.from_default_config_file
12
+ ::Rails.logger.info "Omniauth::Rails::Configurator: Loading from " \
13
+ "default_config_file=#{default_config_file}"
14
+ from_yaml(default_config_file)
15
+ end
16
+
17
+ def self.from_yaml(file)
18
+ new(YAML.load(ERB.new(File.read(file)).result)[::Rails.env])
19
+ end
20
+
21
+ def initialize(data)
22
+ @data = data
23
+ end
24
+
25
+ def configure
26
+ validate!
27
+
28
+ configure_omni_auth_settings
29
+ configure_providers
30
+
31
+ Configuration.automount = automount
32
+ Configuration.authenticated_root = authenticated_root
33
+ Configuration.unauthenticated_root = unauthenticated_root
34
+ Configuration.include_concern_in_application_controller = include_concern_in_application_controller
35
+ Configuration.session_duration = session_duration.seconds if session_duration.present?
36
+ Configuration.dev_mode = dev_mode
37
+ end
38
+
39
+ private
40
+
41
+ attr_reader :data
42
+
43
+ def configure_omni_auth_settings
44
+ OmniAuth.config.logger = ::Rails.logger
45
+ OmniAuth.config.path_prefix = path_prefix
46
+ end
47
+
48
+ def dev_mode
49
+ data["dev_mode"] == true
50
+ end
51
+
52
+ def validate!
53
+ REQUIRED_SETTINGS.each do |setting|
54
+ raise "#{setting} is required" unless send(setting).present?
55
+ end
56
+
57
+ if dev_mode
58
+ raise "dev_mode may not be used in #{::Rails.env}" unless dev_mode_allowed?
59
+ ::Rails.logger.info "Omniauth::Rails: dev_mode is enabled. Authentication and " \
60
+ "authorization are disabled."
61
+ end
62
+ end
63
+
64
+ def dev_mode_allowed?
65
+ ::Rails.env.development?
66
+ end
67
+
68
+ def automount
69
+ data["automount"] != false
70
+ end
71
+
72
+ def path_prefix
73
+ data["path_prefix"] || "/auth"
74
+ end
75
+
76
+ def authenticated_root
77
+ data["authenticated_root"]
78
+ end
79
+
80
+ def unauthenticated_root
81
+ data["unauthenticated_root"]
82
+ end
83
+
84
+ def session_duration
85
+ data["session_duration_in_seconds"]
86
+ end
87
+
88
+ def providers
89
+ data["providers"]
90
+ end
91
+
92
+ def include_concern_in_application_controller
93
+ data["autoload_in_application_controller"] != false
94
+ end
95
+
96
+ def configure_providers
97
+ providers.each do |provider, provider_config|
98
+ Provider.configure(provider, provider_config)
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end