omniauth-rails 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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