omniauth-rails 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (140) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +71 -0
  4. data/Rakefile +41 -0
  5. data/app/assets/config/omniauth_rails_manifest.js +1 -0
  6. data/app/assets/stylesheets/omniauth/rails/application.css +19 -0
  7. data/app/controllers/omniauth/rails/application_controller.rb +8 -0
  8. data/app/controllers/omniauth/rails/flash.rb +46 -0
  9. data/app/controllers/omniauth/rails/require_authentication.rb +26 -0
  10. data/app/controllers/omniauth/rails/require_authorization.rb +32 -0
  11. data/app/controllers/omniauth/rails/sessions_controller.rb +55 -0
  12. data/app/helpers/omniauth/rails/application_helper.rb +16 -0
  13. data/app/models/omniauth/rails/authentication_data_store.rb +31 -0
  14. data/app/models/omniauth/rails/authentication_request.rb +28 -0
  15. data/app/models/omniauth/rails/authentication_session.rb +53 -0
  16. data/app/models/omniauth/rails/authorization_checker.rb +28 -0
  17. data/app/models/omniauth/rails/authorization_types/base.rb +17 -0
  18. data/app/models/omniauth/rails/authorization_types/domains.rb +22 -0
  19. data/app/models/omniauth/rails/authorization_types/emails.rb +18 -0
  20. data/app/models/omniauth/rails/authorization_types/regex.rb +18 -0
  21. data/app/models/omniauth/rails/omni_auth_route_builder.rb +18 -0
  22. data/app/views/omniauth/rails/sessions/destroy.html.erb +6 -0
  23. data/config/initializers/omniauth_rails.rb +35 -0
  24. data/config/routes.rb +6 -0
  25. data/lib/omniauth/rails/configuration.rb +15 -0
  26. data/lib/omniauth/rails/engine.rb +22 -0
  27. data/lib/omniauth/rails/test/controller_helpers.rb +17 -0
  28. data/lib/omniauth/rails/test/request_helpers.rb +25 -0
  29. data/lib/omniauth/rails/version.rb +6 -0
  30. data/lib/omniauth/rails.rb +9 -0
  31. data/spec/controllers/application_controller_spec.rb +9 -0
  32. data/spec/examples.txt +19 -0
  33. data/spec/models/omniauth/rails/authorization_types/emails_spec.rb +28 -0
  34. data/spec/models/omniauth/rails/authorization_types/regex_spec.rb +28 -0
  35. data/spec/omniauth_rails_spec.rb +10 -0
  36. data/spec/rails_helper_for_engine.rb +62 -0
  37. data/spec/spec_helper.rb +93 -0
  38. data/spec/test_app/Rakefile +12 -0
  39. data/spec/test_app/app/assets/config/manifest.js +4 -0
  40. data/spec/test_app/app/assets/javascripts/application.js +13 -0
  41. data/spec/test_app/app/assets/stylesheets/application.css +15 -0
  42. data/spec/test_app/app/controllers/application_controller.rb +4 -0
  43. data/spec/test_app/app/controllers/private_controller.rb +9 -0
  44. data/spec/test_app/app/controllers/public_controller.rb +6 -0
  45. data/spec/test_app/app/helpers/application_helper.rb +3 -0
  46. data/spec/test_app/app/mailers/application_mailer.rb +5 -0
  47. data/spec/test_app/app/models/application_record.rb +4 -0
  48. data/spec/test_app/app/views/layouts/application.html.erb +24 -0
  49. data/spec/test_app/app/views/private/show.html.erb +1 -0
  50. data/spec/test_app/app/views/public/show.html.erb +1 -0
  51. data/spec/test_app/bin/bundle +4 -0
  52. data/spec/test_app/bin/rails +5 -0
  53. data/spec/test_app/bin/rake +5 -0
  54. data/spec/test_app/bin/setup +35 -0
  55. data/spec/test_app/bin/update +30 -0
  56. data/spec/test_app/config/application.rb +23 -0
  57. data/spec/test_app/config/boot.rb +6 -0
  58. data/spec/test_app/config/environment.rb +6 -0
  59. data/spec/test_app/config/environments/development.rb +55 -0
  60. data/spec/test_app/config/environments/production.rb +89 -0
  61. data/spec/test_app/config/environments/test.rb +43 -0
  62. data/spec/test_app/config/initializers/application_controller_renderer.rb +7 -0
  63. data/spec/test_app/config/initializers/assets.rb +12 -0
  64. data/spec/test_app/config/initializers/backtrace_silencers.rb +10 -0
  65. data/spec/test_app/config/initializers/cookies_serializer.rb +6 -0
  66. data/spec/test_app/config/initializers/filter_parameter_logging.rb +5 -0
  67. data/spec/test_app/config/initializers/inflections.rb +17 -0
  68. data/spec/test_app/config/initializers/mime_types.rb +5 -0
  69. data/spec/test_app/config/initializers/session_store.rb +4 -0
  70. data/spec/test_app/config/initializers/wrap_parameters.rb +15 -0
  71. data/spec/test_app/config/locales/en.yml +23 -0
  72. data/spec/test_app/config/omniauth_rails.yml +16 -0
  73. data/spec/test_app/config/puma.rb +48 -0
  74. data/spec/test_app/config/routes.rb +8 -0
  75. data/spec/test_app/config/secrets.yml +22 -0
  76. data/spec/test_app/config/spring.rb +7 -0
  77. data/spec/test_app/config.ru +6 -0
  78. data/spec/test_app/log/development.log +4451 -0
  79. data/spec/test_app/log/test.log +7601 -0
  80. data/spec/test_app/public/404.html +67 -0
  81. data/spec/test_app/public/422.html +67 -0
  82. data/spec/test_app/public/500.html +66 -0
  83. data/spec/test_app/public/apple-touch-icon-precomposed.png +0 -0
  84. data/spec/test_app/public/apple-touch-icon.png +0 -0
  85. data/spec/test_app/public/favicon.ico +0 -0
  86. data/spec/test_app/spec/controllers/private_controller_spec.rb +19 -0
  87. data/spec/test_app/spec/rails_helper.rb +54 -0
  88. data/spec/test_app/spec/requests/private_controller_spec.rb +26 -0
  89. data/spec/test_app/spec/requests/public_controller_spec.rb +13 -0
  90. data/spec/test_app/spec/requests/sessions_controller_spec.rb +87 -0
  91. data/spec/test_app/spec/spec_helper.rb +99 -0
  92. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/-5/-528MPRmC3ByNiAzVD1hs-NG3Muhf9FsYPaDbo4qIpI.cache +1 -0
  93. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/3v/3voyTxS8FmTTGPrz-QQ23N6AgGate2o7X5ZnZeTkQbs.cache +0 -0
  94. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/5V/5VAABbvE5t5bCDKmKjLivvfe1CqYdD4n4vtZQiMa4I0.cache +0 -0
  95. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/64/64siRwVaDPAW5fTe1O4rlGaq-0ExxAWA0-csPcik-uM.cache +0 -0
  96. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/Aa/AasprW2BgqWDcmZnsPRxs-R5D0VGpL7dHYMwtsC1tmE.cache +0 -0
  97. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/An/An3DVlfO1pzT7FAnm09q3Ok_2PmGYhiAvxuW9OgG9wc.cache +0 -0
  98. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/C-/C-_kx_I8fFV2TrLPw8CNFy1uLrN6G4yLPg_4vOhlohQ.cache +0 -0
  99. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/EG/EGN6771mS8m_7wi-Cr-GgFKv9U9IE3gpo9JQ-N3AYlQ.cache +0 -0
  100. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/Hl/HlzBaGDQ4NV3ctlz-qlmStUWDCELhxzVK1-SgLkPCH0.cache +0 -0
  101. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/IB/IBoXb9_P8EU8f7aPVNE8cWJybcus8fS7KGvi4HxKdMU.cache +1 -0
  102. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/K2/K28c2b37N3eRA-Pckb3MO3D3BvGXfbxDGNeRYIXG8Cg.cache +1 -0
  103. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/KJ/KJdFFU6zb4YpQWEm8bsXxx8kdQ01BdK0F0h6TTzpOiY.cache +0 -0
  104. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/KW/KWwCiQwwI6oqiIHZg_Qg2nrs1zXJISos9799GIL5viU.cache +0 -0
  105. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/Kh/KhKDGOFwOEJlSwLMaG8Yak8AktHsnEr-fUwLpl9d0tc.cache +1 -0
  106. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/NX/NXZl3HljnPNJmh2CNpp0skcYvQx4eSEp6vuG5o3lqqY.cache +0 -0
  107. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/NX/nxTv3sKVUQZADJyM3dPaVmUA78MIsMLD_K279yN_GsI.cache +0 -0
  108. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/Ob/ObDGu7gmDzQuH86CeAdhWRPf0sfv9Qo3CoxGK3VOYWI.cache +0 -0
  109. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/QG/QGjnK1OGVhAWzpma8R60Qdcr6v46sAWmpwQpeoWltX8.cache +1 -0
  110. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/Qn/Qn2TRz8mMz8dPVvXgHUfqXC19EPZQgG3XDqm5W_E-A0.cache +1 -0
  111. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/WC/WCTd8gm1KmkPKRB14gd1wwFv3x9NwMsmquXet4Z1DTU.cache +2 -0
  112. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/Z-/Z-3hfqbx8r350iW9zFPz_OdVHX0X4Z4bMk9YbS1eha8.cache +0 -0
  113. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/Z2/Z2DJdVm4jsJXg0HzuQVyAAmjJbVdzKntXlmd14iNVbU.cache +0 -0
  114. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/ZA/ZAzUlqsc-uLa_zcjt1t6EBkPqI8PkEoxz40i4FgrRlQ.cache +1 -0
  115. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/bN/bNCmkb6T3JKDzd6s7ZxOLn_WdC6gUnRARnBDHrMFS7o.cache +1 -0
  116. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/b_/b_Itlk9QZZd7Rvf8kcA4yLP1R5Acu7jB-m1xQiSU0qE.cache +0 -0
  117. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/d6/d6PosAq3dbPqxxvjAcaLgePkRuQ8w__EA-M42WarK_0.cache +1 -0
  118. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/fD/fDbKpwc4jlsYlnxTT3vnhsiBcSJF3imnAGUBp9nq_Bw.cache +1 -0
  119. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/fE/fEHvM7gLiXuJB6lDj2KNzgAx5L3BBn2NSsuodvPAryI.cache +0 -0
  120. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/fg/fgbqfgH_CvzP2H744Q3ywDzlqLRSgSw0AH6ifkC7roo.cache +1 -0
  121. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/g4/g4TbkEUbvKBMpO8z4ioPbq8ArdLl-scuF3pVaLJhmVI.cache +1 -0
  122. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/id/idcyFsf20F5Vd3GC1XtM_PxlNnROM6CxO1j11NG3RWk.cache +1 -0
  123. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/ih/ihflBRw1ToLzP0q8oKAJl_a6EHHbTdJUcVR5DANsIuA.cache +0 -0
  124. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/jz/jzXohzOyfczV5wKfQVQWgE1H0IMN4jaxEM3XlhHNgvk.cache +0 -0
  125. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/lH/lHLoBOtMavo_6UnfOn0DVLI2JQBT1W9sGR3IZzOD6o8.cache +2 -0
  126. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/mD/mDmWU5fLvNY4uggphc1wqYVQDn_w_U6Jz2XRSf59jDc.cache +0 -0
  127. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/mX/mX1nlsL_SWOB4y22W5FheRX0YEONKyOY7xUeIvRiHco.cache +0 -0
  128. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/n5/n5FDaqgvLV4Rc1Xm6TykMEFanDhSJJ77HPuPCEgCDQM.cache +1 -0
  129. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/n9/n9Nzbk_dEL3fNO-u56owqnrG7YQmhcvDgJ2fWWE_9jE.cache +0 -0
  130. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/nU/nUDR2L4CaIx5IszaYaaaACw519TTTzvpxsp7NMl6KyQ.cache +1 -0
  131. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/n_/n_xYqQYhwEMQknb3jFQnjlxxBE9TzMNHCdJ-bEyZFIw.cache +0 -0
  132. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/pc/pcFf9fij5Xa__QoHi-QzN_0Q_UGLhv6gihTXnoFX3sg.cache +1 -0
  133. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/q-/q-721tFv_0DZO9GZ_kHYUD_jn6GNRC09vb51mwyxbuI.cache +1 -0
  134. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/r6/r6saZ-BJCnX2-U353od1DgtZIGy5kXrCuXatXntMcTE.cache +0 -0
  135. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/wY/wYWiPwDGlToFGYId__oKg8QMPEeuRZoP1FhQahshfOo.cache +1 -0
  136. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/yD/yDj60NQvsiwl1QWQXH-iC4pgF1cmHkUFo-kkXBSjsIQ.cache +1 -0
  137. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/ym/ymCwqEVBkEs6bYteLf70KCA5pCKZtqjQ3TbZQzrIs3M.cache +0 -0
  138. data/spec/test_app/tmp/cache/assets/sprockets/v3.0/z0/z041WxjoEQvRhtSLORbkRlsNTgi68Rwx7XUyaDbPn0M.cache +1 -0
  139. data/spec/test_app/tmp/pids/server.pid +1 -0
  140. metadata +453 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d56083f2dbbbb8598f6740095b9df4dd967269be
4
+ data.tar.gz: 905900d024010eee45dc8025a958e80a167ea269
5
+ SHA512:
6
+ metadata.gz: 418f5a1cafc19fd179bd4bb78b80ec45962c410a3f9aef1f41dc5eaa6aaaddf83b65cb13d0d51234d484d6a5535df8f0c5b6a2f7ae3594f654d6e57449414d29
7
+ data.tar.gz: 69b3d71ee4887a09f8283c0304391901483b921384f9976805b80b10e109e6149364365cd189dce427cf5133a80a0cd529b873c8f8100ff29e437d4bfcbfc306
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2016 Dan Rabinowitz
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.
data/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # Omniauth::Rails
2
+ A Rails Engine to make it as easy as possible to add oauth authentication to a Rails app.
3
+
4
+ The canonical use case is this:
5
+ You build a simple Rails app for your company. It is for internal use only. Your company uses Google Apps for gmail.
6
+
7
+ Most existing authentication and authorization systems, like Devise, require a table of Users, and permissions. That requires that users maintain a separate password, and it requires someone to disable an account when an employee leaves.
8
+
9
+ OmniAuth solves these problems, but can take some effort to configure properly. It is highly flexible and customizable. But adding it can require updates to controllers, the routes file, an initializer. The biggest challenge is that after it authenticates the user, it leaves *persisting* that user's identify as something for the developer to handle.
10
+
11
+ OmniAuth::Rails makes it as easy as possible to create an admin site. See Usage, below.
12
+
13
+ Authorization is handled separately.
14
+
15
+ ## TODO
16
+
17
+ * Add a "dev mode" override which simply skips all authentication.
18
+
19
+ * Search for "TODO" in the code.
20
+
21
+ ## Usage
22
+
23
+ 1. Add the gem to your Gemfile
24
+ gem 'omniauth-rails'
25
+
26
+ 2. Add a config/omniauth_rails.yml with something like this:
27
+ ```yml
28
+ development:
29
+ providers:
30
+ google_oauth2:
31
+ client_id: <%= ENV["CLIENT_ID"] %>
32
+ client_secret: <%= ENV["CLIENT_SECRET"] %>
33
+ authenticated_root: "/private"
34
+ unauthenticated_root: "/public"
35
+ session_duration_in_seconds: 5 # The default is 3600 (which is 1 hour)
36
+ test:
37
+ providers:
38
+ google_oauth2:
39
+ client_id: 1
40
+ client_secret: 2
41
+ authenticated_root: "/private"
42
+ unauthenticated_root: "/public"
43
+ session_duration_in_seconds: 5 # The default is 3600 (which is 1 hour)
44
+ production:
45
+ providers:
46
+ google_oauth2:
47
+ client_id: <%= ENV["CLIENT_ID"] %>
48
+ client_secret: <%= ENV["CLIENT_SECRET"] %>
49
+ authenticated_root: "/private"
50
+ unauthenticated_root: "/public"
51
+ session_duration_in_seconds: 3600 # The default is 3600 (which is 1 hour)
52
+ ```
53
+
54
+ 3. In any controllers which require authentication, add this line:
55
+ ```ruby
56
+ include Omniauth::Rails::RequireAuthentication
57
+ ```
58
+
59
+ ## Logging out
60
+
61
+ In general, there's not much point in "logging out". It wipes the Omniauth::Rails session,
62
+ but the browser is still logged in to the provider, which has granted access to the application
63
+ (generally) with no expiration. So logging back in requires no credentials.
64
+
65
+ Bottom line: There's usually no reason to have a logout button when using Omniauth::Rails
66
+
67
+ ## Contributing
68
+ PRs are welcome!
69
+
70
+ ## License
71
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
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
+ require "rdoc/task"
9
+
10
+ RDoc::Task.new(:rdoc) do |rdoc|
11
+ rdoc.rdoc_dir = "rdoc"
12
+ rdoc.title = "Omniauth::Rails"
13
+ rdoc.options << "--line-numbers"
14
+ rdoc.rdoc_files.include("README.md")
15
+ rdoc.rdoc_files.include("lib/**/*.rb")
16
+ end
17
+
18
+ APP_RAKEFILE = File.expand_path("../spec/test_app/Rakefile", __FILE__)
19
+ load "rails/tasks/engine.rake"
20
+
21
+ load "rails/tasks/statistics.rake"
22
+
23
+ require "bundler/gem_tasks"
24
+
25
+ require "rspec/core"
26
+ require "rspec/core/rake_task"
27
+
28
+ desc "Run all specs in spec directory (excluding plugin specs)"
29
+ task("spec").clear
30
+ RSpec::Core::RakeTask.new do |t|
31
+ t.verbose = false
32
+ end
33
+
34
+ require "rubocop/rake_task"
35
+ desc "Run RuboCop"
36
+ RuboCop::RakeTask.new(:rubocop) do |tsk|
37
+ tsk.fail_on_error = true
38
+ tsk.options = ["-DR", "--format=html", "--out=tmp/rubocop.html", "--format=progress"]
39
+ end
40
+
41
+ task default: [:spec, :rubocop]
@@ -0,0 +1 @@
1
+ //= link_directory ../stylesheets/omniauth/rails .css
@@ -0,0 +1,19 @@
1
+ form.button_to {
2
+ display: inline;
3
+ margin: 0;
4
+ padding: 0;
5
+ }
6
+ form.button_to div { display: inline; }
7
+ 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
+ }
19
+ }
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ module Omniauth
3
+ module Rails
4
+ class ApplicationController < ActionController::Base
5
+ protect_from_forgery with: :exception
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+ module Omniauth
3
+ module Rails
4
+ module Flash
5
+ extend ActiveSupport::Concern
6
+
7
+ def set_url_to_return_to_after_authentication
8
+ # TODO: Sanitize these urls, to avoid phishing attacks
9
+ # See https://www.owasp.org/index.php/Unvalidated_Redirects_and_Forwards_Cheat_Sheet
10
+ flash[:url_to_return_to_after_authentication] =
11
+ # url_to_return_to_after_authentication_from_params ||
12
+ url_to_return_to_after_authentication_from_flash ||
13
+ # url_to_return_to_after_authentication_from_referer ||
14
+ default_url_to_return_to_after_authentication
15
+ end
16
+
17
+ private
18
+
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
+ def url_to_return_to_after_authentication_from_flash
29
+ flash[:url_to_return_to_after_authentication]
30
+ end
31
+
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
+ def default_url_to_return_to_after_authentication
42
+ Configuration.authenticated_root
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ module Omniauth
3
+ module Rails
4
+ module RequireAuthentication
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ include Omniauth::Rails::ApplicationHelper
9
+
10
+ # TODO: Do not add this before_action in dev_mode
11
+ before_action :require_authentication
12
+ end
13
+
14
+ private
15
+
16
+ def require_authentication
17
+ redirect_to_sign_in_url unless authenticated?
18
+ end
19
+
20
+ def redirect_to_sign_in_url
21
+ flash[:url_to_return_to_after_authentication] = request.original_url
22
+ redirect_to omniauth_rails.sign_in_url
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ module Omniauth
3
+ module Rails
4
+ module RequireAuthorization
5
+ def self.included(klass)
6
+ klass.include Omniauth::Rails::RequireAuthentication
7
+ klass.extend ClassMethods
8
+ end
9
+
10
+ module ClassMethods
11
+ private
12
+
13
+ def require_authorization(params)
14
+ # TODO: Do not add this before_action in dev_mode
15
+ before_action { |c| c.require_authorization(params) }
16
+ end
17
+ end
18
+
19
+ protected
20
+
21
+ def require_authorization(params)
22
+ redirect_to_sign_in_url unless authorized?(params)
23
+ end
24
+
25
+ private
26
+
27
+ def authorized?(params)
28
+ AuthorizationChecker.new(email: authenticated_email, params: params).authorized?
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+ module Omniauth
3
+ module Rails
4
+ class SessionsController < ApplicationController
5
+ include Omniauth::Rails::ApplicationHelper
6
+ include Omniauth::Rails::Flash
7
+
8
+ # GET /sign_in
9
+ def new
10
+ # Set a flash variable, so we know where to go after a successful authentication.
11
+ set_url_to_return_to_after_authentication
12
+
13
+ # If we are already authenticated, do not attempt to authenticate again.
14
+ # Instead, redirect to where we would go after authentication
15
+ if authenticated?
16
+ redirect_to flash[:url_to_return_to_after_authentication]
17
+ else
18
+ redirect_to omniauth_route
19
+ end
20
+ end
21
+
22
+ # DELETE /sign_out
23
+ def destroy
24
+ authentication_session.reset
25
+
26
+ if Configuration.unauthenticated_root.present?
27
+ redirect_to Configuration.unauthenticated_root
28
+ else
29
+ render layout: false
30
+ end
31
+ end
32
+
33
+ # GET /:provider/callback
34
+ def create
35
+ persist_authentication_data
36
+ redirect_to flash[:url_to_return_to_after_authentication] ||
37
+ default_url_to_return_to_after_authentication
38
+ end
39
+
40
+ private
41
+
42
+ def omniauth_route
43
+ OmniAuthRouteBuilder.new.route
44
+ end
45
+
46
+ def persist_authentication_data
47
+ authentication_request.persist(authentication_session)
48
+ end
49
+
50
+ def authentication_request
51
+ AuthenticationRequest.new(request)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+ module Omniauth
3
+ module Rails
4
+ module ApplicationHelper
5
+ delegate :authenticated?, to: :authentication_session
6
+
7
+ def authenticated_email
8
+ authentication_session.email
9
+ end
10
+
11
+ def authentication_session
12
+ AuthenticationSession.new(session)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+ module Omniauth
3
+ module Rails
4
+ class AuthenticationDataStore
5
+ SCOPE = "OmniauthRailsAuthData"
6
+
7
+ def initialize(session)
8
+ @session = session
9
+ freeze
10
+ end
11
+
12
+ def get(key)
13
+ return nil if session[SCOPE].nil?
14
+ session[SCOPE][key]
15
+ end
16
+
17
+ def set(key, value)
18
+ session[SCOPE] ||= {}
19
+ session[SCOPE][key] = value
20
+ end
21
+
22
+ def reset
23
+ session[SCOPE] = {}
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :session
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ module Omniauth
3
+ module Rails
4
+ class AuthenticationRequest
5
+ def initialize(request)
6
+ @request = request
7
+ end
8
+
9
+ def persist(authentication_session)
10
+ # TODO: Store the provider in the session
11
+ authentication_session.email = email
12
+ authentication_session.expire_in(session_duration)
13
+ end
14
+
15
+ private
16
+
17
+ attr_reader :request
18
+
19
+ def email
20
+ request.env["omniauth.auth"].info.email
21
+ end
22
+
23
+ def session_duration
24
+ Configuration.session_duration
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+ module Omniauth
3
+ module Rails
4
+ class AuthenticationSession
5
+ EMAIL_KEY = "email"
6
+ EXPIRE_AT_KEY = "expire_at"
7
+
8
+ def initialize(session)
9
+ @session = session
10
+ reset if expired?
11
+ freeze
12
+ end
13
+
14
+ delegate :reset, to: :data_store
15
+
16
+ def authenticated?
17
+ email.present?
18
+ end
19
+
20
+ def email
21
+ data_store.get(EMAIL_KEY)
22
+ end
23
+
24
+ def email=(email)
25
+ data_store.set(EMAIL_KEY, email)
26
+ end
27
+
28
+ def expire_in(duration)
29
+ self.expire_at = (Time.now.to_i + duration)
30
+ end
31
+
32
+ def expire_at
33
+ data_store.get(EXPIRE_AT_KEY)
34
+ end
35
+
36
+ def expire_at=(expire_at)
37
+ data_store.set(EXPIRE_AT_KEY, expire_at)
38
+ end
39
+
40
+ private
41
+
42
+ attr_reader :session
43
+
44
+ def data_store
45
+ @data_store ||= AuthenticationDataStore.new(session)
46
+ end
47
+
48
+ def expired?
49
+ expire_at.present? && expire_at < Time.now.to_i
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ module Omniauth
3
+ module Rails
4
+ class AuthorizationChecker
5
+ AUTHORIZATION_TYPES = {
6
+ domains: AuthorizationTypes::Domains,
7
+ emails: AuthorizationTypes::Emails,
8
+ regex: AuthorizationTypes::Regex,
9
+ }.freeze
10
+
11
+ def initialize(email:, params:)
12
+ @email = email
13
+ @params = params
14
+ end
15
+
16
+ def authorized?
17
+ params.map do |key, value|
18
+ raise "Invalid key for authorization constraint" unless AUTHORIZATION_TYPES.key?(key)
19
+ AUTHORIZATION_TYPES[key].new(email: email, value: value).authorized?
20
+ end.all?
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :email, :params
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+ module Omniauth
3
+ module Rails
4
+ module AuthorizationTypes
5
+ class Base
6
+ def initialize(email:, value:)
7
+ @email = email
8
+ @value = value
9
+ end
10
+
11
+ private
12
+
13
+ attr_reader :email, :value
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ module Omniauth
3
+ module Rails
4
+ module AuthorizationTypes
5
+ class Domains < Base
6
+ def authorized?
7
+ domains.any? { |domain| email_domain.casecmp(domain).zero? }
8
+ end
9
+
10
+ private
11
+
12
+ def email_domain
13
+ @email_domain ||= email.split("@").last.to_s
14
+ end
15
+
16
+ def domains
17
+ value
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ module Omniauth
3
+ module Rails
4
+ module AuthorizationTypes
5
+ class Emails < Base
6
+ def authorized?
7
+ emails.any? { |allowed_email| allowed_email.to_s.casecmp(email).zero? }
8
+ end
9
+
10
+ private
11
+
12
+ def emails
13
+ value
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ module Omniauth
3
+ module Rails
4
+ module AuthorizationTypes
5
+ class Regex < Base
6
+ def authorized?
7
+ !regex.match(email).nil?
8
+ end
9
+
10
+ private
11
+
12
+ def regex
13
+ value
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ module Omniauth
3
+ module Rails
4
+ class OmniAuthRouteBuilder
5
+ def initialize
6
+ @provider = "google_oauth2"
7
+ end
8
+
9
+ def route
10
+ "/auth/#{provider}"
11
+ end
12
+
13
+ private
14
+
15
+ attr_reader :provider
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,6 @@
1
+ <div class='notification'>
2
+ You have been logged out.
3
+ Click
4
+ <%= link_to "here", omniauth_rails.sign_in_url, target: '_self' %>
5
+ to log back in.
6
+ </div>
@@ -0,0 +1,35 @@
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"]
data/config/routes.rb ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+ Omniauth::Rails::Engine.routes.draw do
3
+ get "/sign_in", to: "sessions#new", as: :sign_in
4
+ delete "/sign_out", to: "sessions#destroy", as: :sign_out
5
+ get "/:provider/callback", to: "sessions#create"
6
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ module Omniauth
3
+ module Rails
4
+ class Configuration
5
+ ATTRIBUTES = %i(authenticated_root unauthenticated_root session_duration logger).freeze
6
+
7
+ @session_duration = 1.hour
8
+ @logger = ::Rails.logger
9
+
10
+ class << self
11
+ attr_accessor(*ATTRIBUTES)
12
+ end
13
+ end
14
+ end
15
+ end