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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +92 -0
- data/Rakefile +20 -0
- data/config/routes.rb +3 -0
- data/lib/simple_google_auth/controller.rb +17 -0
- data/lib/simple_google_auth/engine.rb +8 -0
- data/lib/simple_google_auth/receiver.rb +75 -0
- data/lib/simple_google_auth/version.rb +3 -0
- data/lib/simple_google_auth.rb +48 -0
- metadata +68 -0
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,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,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,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: []
|