simple_google_auth 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 916acd1b268b0efded641b43215512f3e85961e3
4
+ data.tar.gz: b3568a7dc9b1ed4cb78044350aaeab5a9d991ee5
5
+ SHA512:
6
+ metadata.gz: 6bf85eb9a1d6f43fdd0f017828638ccb9cf00d43e1365f33ac50fb3fd3447b145dfe84af6f421a8efcfc9f55dfaad3cdefdb4760123a6290de23e19804fc0875
7
+ data.tar.gz: eef11d06ec10dd9d3c26173fa6715269028d039895e1fd5676b378f2d23db51ffa27909190b84a83bfbba7c35bf1ed49086629876591da5d05a6ce81bba710fd
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2014 Roger Nesbitt
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,92 @@
1
+ # SimpleGoogleAuth
2
+
3
+ Want an extremely easy integration of Google's authentication system in your Rails site?
4
+
5
+ This is a dead simple gem that allows you to require a Google login for parts of your site.
6
+ You can allow any user with a Google account, or limit access to certain users based on their
7
+ Google e-mail address.
8
+
9
+ Being simple, it's slightly limited in what it can do. But if your goal is to put your site
10
+ behind a Google login instead of a crusty basic auth box, it'll do the trick.
11
+ If you're after more power, there are quite a few gems that'll do what you're looking for,
12
+ such as OmniAuth's Google strategy.
13
+
14
+ ## Installation
15
+
16
+ Follow these five steps to integrate with your site.
17
+
18
+ Step 1: Make yourself a project at https://cloud.google.com/console, if you haven't already.
19
+
20
+ Step 2: In that project, go to the "APIs & auth" tab, then the "Credentials" tab. Create a new client ID of application type "Web application". Set the Authorized Redirect URI to
21
+ `http://yoursite.com/google-callback`. You might want to put in `http://localhost:3000/google-callback` so you can test locally too.
22
+
23
+ Step 3: Add simple_google_auth to your Gemfile
24
+
25
+ gem 'simple_google_auth'
26
+
27
+ Step 4: In your application.rb, put down some code inside the Application class:
28
+
29
+ SimpleGoogleAuth.configure do |config|
30
+ config.client_id = "the client ID as supplied by Google in step 2"
31
+ config.client_secret = "the client secret as supplied by Google in step 2"
32
+ config.redirect_uri = "http://localhost:3000/google-callback"
33
+ config.authenticate = lambda do |data|
34
+ data["email"] == "your.email@example.com"
35
+ end
36
+ end
37
+
38
+ Step 5: In your application_controller.rb, add a before filter:
39
+
40
+ before_filter :redirect_if_not_google_authenticated
41
+
42
+ Done! Any request to your site will now redirect off to Google for authentication.
43
+ A route that captures requests coming in to /google-callback is automatically created and handled for you.
44
+
45
+ If you log in with `your.email@example.com`, it'll let you in to the site and take you to the page you were initially trying to go to.
46
+ Otherwise it'll redirect to `/` (by default) with `params[:message]` set to the authentication error.
47
+
48
+ ## Setting up multiple environments
49
+
50
+ You might want to put a different configure block in your development.rb and production.rb, each specifying
51
+ a different redirect URI. Just pop them on the end of the file.
52
+
53
+ # development.rb
54
+ SimpleGoogleAuth.configure do |config|
55
+ config.redirect_uri = "http://localhost:3000/google-callback"
56
+ end
57
+
58
+ # production.rb
59
+ SimpleGoogleAuth.configure do |config|
60
+ config.redirect_uri = "https://mysite.com/google-callback"
61
+ end
62
+
63
+
64
+ ## How do I tell who is logged in?
65
+
66
+ Call `#google_auth_data` from your controller or view and you'll get the identification hash that Google sends back.
67
+
68
+ Welcome, <%= google_auth_data["email"] %>!
69
+
70
+ Take a look at https://developers.google.com/accounts/docs/OAuth2Login#obtainuserinfo to find out more about the fields in the hash.
71
+
72
+ ## Configuring
73
+
74
+ There are a few configuration options that can be set using `SimpleGoogleAuth.configure` as in the example above.
75
+
76
+ Option | Default | Description
77
+ --- | --- | ---
78
+ client_id | (required) | Client ID as provided by Google.
79
+ client_secret | (required) | Client secret as provided by Google.
80
+ redirect_uri | (required) | Where Google should redirect to after authentication.
81
+ redirect_path | `nil` | A route is created at this path. If no path is specified, the path is taken from redirect_uri.
82
+ authenticate | (required) | A lambda that's run to determine whether the user should be accepted as valid or not. Takes one argument, a hash of identification data as provided by Google. Should return true on success, or false if the login should not proceed.
83
+ failed_login_path | `"/"` | Where to redirect to upon a failed login. `params[:message]` will be set with the error that occurred.
84
+ ca_path | `"/etc/ssl/certs"` | A path or file of SSL certificates, used to check that we're really talking to the Google servers.
85
+ google_auth_url | `"https://accounts.google.com/o/oauth2/auth"` | Google's authentication URL.
86
+ google_token_url | `"https://accounts.google.com/o/oauth2/token"` | Google's token URL.
87
+ state_session_key_name | `"simple-google-auth.state"` | The name of the session variable used to store a random string used to prevent CSRF attacks during authentication.
88
+ data_session_key_name | `"simple-google-auth.data"` | The name of the session variable used to store identification data from Google.
89
+
90
+ ## Licence
91
+
92
+ MIT.
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'SimpleGoogleAuth'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+
20
+ Bundler::GemHelper.install_tasks
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ Rails.application.routes.draw do
2
+ get SimpleGoogleAuth.config.redirect_path || URI(SimpleGoogleAuth.config.redirect_uri).path, to: SimpleGoogleAuth::Receiver.new
3
+ end
@@ -0,0 +1,17 @@
1
+ module SimpleGoogleAuth
2
+ module Controller
3
+ protected
4
+ def redirect_if_not_google_authenticated
5
+ redirect_to google_authentication_uri if google_auth_data.nil?
6
+ end
7
+
8
+ def google_authentication_uri
9
+ state = session[SimpleGoogleAuth.config.state_session_key_name] = SecureRandom.hex + request.path
10
+ SimpleGoogleAuth.uri(state)
11
+ end
12
+
13
+ def google_auth_data
14
+ session[SimpleGoogleAuth.config.data_session_key_name]
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,8 @@
1
+ module SimpleGoogleAuth
2
+ class Engine < ::Rails::Engine
3
+ initializer "simple_google_auth.load_helpers" do
4
+ ActionController::Base.send :include, SimpleGoogleAuth::Controller
5
+ ActionController::Base.send :helper_method, :google_auth_data
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,75 @@
1
+ module SimpleGoogleAuth
2
+ class Receiver
3
+ Error = Class.new(StandardError)
4
+
5
+ def call(env)
6
+ request = Rack::Request.new(env)
7
+ config = SimpleGoogleAuth.config
8
+
9
+ ensure_params_are_correct(request, config)
10
+ auth_data = obtain_authentication_data(request.params["code"], config)
11
+ id_data = decode_id_data(auth_data)
12
+
13
+ raise Error, "Authentication failed" unless config.authenticate.call(id_data)
14
+
15
+ request.session[config.data_session_key_name] = id_data
16
+
17
+ path = request.session[config.state_session_key_name][32..-1]
18
+ path = "/" if path.blank?
19
+ [302, {"Location" => path}, [" "]]
20
+
21
+ rescue Error => e
22
+ uri = URI(config.failed_login_path)
23
+ uri.query = uri.query ? "#{uri.query}&" : ""
24
+ uri.query += "message=#{CGI.escape e.message}"
25
+ [302, {"Location" => uri.to_s}, [" "]]
26
+ end
27
+
28
+ protected
29
+ def ensure_params_are_correct(request, config)
30
+ if request.params["state"] != request.session[config.state_session_key_name]
31
+ raise Error, "Invalid state returned from Google"
32
+ elsif request.params["error"]
33
+ raise Error, "Authentication failed: #{request.params["error"]}"
34
+ elsif request.params["code"].nil?
35
+ raise Error, "No authentication code returned"
36
+ end
37
+ end
38
+
39
+ def obtain_authentication_data(code, config)
40
+ uri = URI(config.google_token_url)
41
+
42
+ http = Net::HTTP.new(uri.host, uri.port)
43
+ if uri.scheme == "https"
44
+ http.use_ssl = true
45
+ if config.ca_path
46
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
47
+ http.ca_path = config.ca_path
48
+ else
49
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
50
+ Rails.logger.warn "SimpleGoogleAuth does not have a ca_path configured; SSL with Google is not protected"
51
+ end
52
+ end
53
+
54
+ request = Net::HTTP::Post.new(uri.request_uri)
55
+ request.set_form_data(
56
+ code: code,
57
+ client_id: config.client_id,
58
+ client_secret: config.client_secret,
59
+ redirect_uri: config.redirect_uri,
60
+ grant_type: "authorization_code"
61
+ )
62
+
63
+ response = http.request(request)
64
+ raise Error, "Failed to get an access token" unless response.is_a?(Net::HTTPSuccess)
65
+
66
+ JSON.parse(response.body)
67
+ end
68
+
69
+ def decode_id_data(auth_data)
70
+ id_data_64 = auth_data["id_token"].split(".")[1]
71
+ id_data_64 << "=" until id_data_64.length % 3 == 0
72
+ id_data = JSON.parse(Base64.decode64(id_data_64))
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,3 @@
1
+ module SimpleGoogleAuth
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,48 @@
1
+ module SimpleGoogleAuth
2
+ Config = Struct.new(
3
+ :client_id,
4
+ :client_secret,
5
+ :redirect_uri,
6
+ :redirect_path,
7
+ :failed_login_path,
8
+ :authenticate,
9
+ :ca_path,
10
+ :google_auth_url,
11
+ :google_token_url,
12
+ :state_session_key_name,
13
+ :data_session_key_name
14
+ )
15
+
16
+ mattr_accessor :config
17
+ self.config = Config.new
18
+
19
+ def self.configure
20
+ yield config
21
+ end
22
+
23
+ def self.uri(state)
24
+ query = {
25
+ response_type: "code",
26
+ client_id: config.client_id,
27
+ redirect_uri: config.redirect_uri,
28
+ scope: "openid email",
29
+ state: state
30
+ }
31
+
32
+ "#{config.google_auth_url}?" + query.map {|k, v| "#{k}=#{CGI.escape v}"}.join("&")
33
+ end
34
+ end
35
+
36
+ SimpleGoogleAuth.configure do |config|
37
+ config.ca_path = %w(/etc/ssl/certs).detect {|dir| Dir.exists?(dir)}
38
+ config.google_auth_url = "https://accounts.google.com/o/oauth2/auth"
39
+ config.google_token_url = "https://accounts.google.com/o/oauth2/token"
40
+ config.state_session_key_name = "simple-google-auth.state"
41
+ config.data_session_key_name = "simple-google-auth.data"
42
+ config.failed_login_path = "/"
43
+ config.authenticate = lambda { raise "You must define an authenticate lambda that sets the session" }
44
+ end
45
+
46
+ require 'simple_google_auth/engine'
47
+ require 'simple_google_auth/controller'
48
+ require 'simple_google_auth/receiver'
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_google_auth
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Roger Nesbitt
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 3.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 3.2.0
27
+ description: An extremely easy way to protect your site by requiring Google logins
28
+ without having to set up a traditional authentication system
29
+ email:
30
+ - roger@seriousorange.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - config/routes.rb
36
+ - lib/simple_google_auth/controller.rb
37
+ - lib/simple_google_auth/engine.rb
38
+ - lib/simple_google_auth/receiver.rb
39
+ - lib/simple_google_auth/version.rb
40
+ - lib/simple_google_auth.rb
41
+ - MIT-LICENSE
42
+ - Rakefile
43
+ - README.md
44
+ homepage: https://github.com/mogest/simple_google_auth
45
+ licenses:
46
+ - MIT
47
+ metadata: {}
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubyforge_project:
64
+ rubygems_version: 2.1.11
65
+ signing_key:
66
+ specification_version: 4
67
+ summary: Super simple Google authentication for your Rails site
68
+ test_files: []