simple_google_auth 0.0.5 → 0.0.6
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 +4 -4
- data/README.md +33 -1
- data/lib/simple_google_auth.rb +8 -1
- data/lib/simple_google_auth/controller.rb +29 -0
- data/lib/simple_google_auth/http_client.rb +30 -0
- data/lib/simple_google_auth/oauth.rb +51 -0
- data/lib/simple_google_auth/receiver.rb +5 -41
- data/lib/simple_google_auth/version.rb +1 -1
- metadata +13 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b07e9d444f3a69575224aae7742706c4e857fd6b
|
4
|
+
data.tar.gz: 03baf12262054337668111cd951ea4b8e259faa1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2fa8cf9287ed2bff1db2be4b8f347b65bc5ca6031f0b754758d886a8a9439c9ed0e6aa776d3c19f400982134a1b11d761ba97a2ec574386f0331b62125e6617f
|
7
|
+
data.tar.gz: e8f0d7c17256ec5ac1b7dca2a75adb48e9a4a767702044cc2b283ea11a58b9295abbb7d222b2510965b7adfd7af3a0eec2cdbdf4c5b4239d4f926e3c8e68075c
|
data/README.md
CHANGED
@@ -60,7 +60,6 @@ a different redirect URI. Just pop them on the end of the file.
|
|
60
60
|
config.redirect_uri = "https://mysite.com/google-callback"
|
61
61
|
end
|
62
62
|
|
63
|
-
|
64
63
|
## How do I tell who is logged in?
|
65
64
|
|
66
65
|
Call `#google_auth_data` from your controller or view and you'll get the identification hash that Google sends back.
|
@@ -69,6 +68,39 @@ Call `#google_auth_data` from your controller or view and you'll get the identif
|
|
69
68
|
|
70
69
|
Take a look at https://developers.google.com/accounts/docs/OAuth2Login#obtainuserinfo to find out more about the fields in the hash.
|
71
70
|
|
71
|
+
## Refreshing tokens and offline mode
|
72
|
+
|
73
|
+
By default simple_google_auth doesn't check the expiry time
|
74
|
+
on the credentials after they've been loaded from google the first time.
|
75
|
+
This is less hassle if all you want is simple authentication for your site,
|
76
|
+
but prevents you from using the credentials for other uses (eg. GCal integration)
|
77
|
+
because the oauth tokens will expire and google won't accept them anymore.
|
78
|
+
|
79
|
+
If you want the tokens to be refreshed when they expire then you need to
|
80
|
+
add an extra line to your config. Doing so will ensure that your
|
81
|
+
google auth tokens never get stale and allow you to use offline mode.
|
82
|
+
|
83
|
+
SimpleGoogleAuth.configure do |config|
|
84
|
+
config.refresh_stale_tokens = true
|
85
|
+
end
|
86
|
+
|
87
|
+
Whenever the google_auth_data is requested in a controller it will first
|
88
|
+
be checked to make sure it's not stale. If it is stale the tokens will be
|
89
|
+
refreshed before being returned.
|
90
|
+
|
91
|
+
If your users have already allowed your site access to a certain set of scopes
|
92
|
+
google won't re-issue you a refresh_token automatically. You'll need to set an
|
93
|
+
extra param in the request_parameters configuration hash to force google to
|
94
|
+
send you the refresh token every time your users authenticate.
|
95
|
+
|
96
|
+
SimpleGoogleAuth.configure do |config|
|
97
|
+
config.refresh_stale_tokens = true
|
98
|
+
config.request_parameters.merge!({ approval_prompt: "force" })
|
99
|
+
end
|
100
|
+
|
101
|
+
For more details on offline mode and approval_prompt refer to the google OAuth docs, as of
|
102
|
+
writing you can find them #[here](https://developers.google.com/accounts/docs/OAuth2WebServer).
|
103
|
+
|
72
104
|
## Configuring
|
73
105
|
|
74
106
|
There are a few configuration options that can be set using `SimpleGoogleAuth.configure` as in the example above.
|
data/lib/simple_google_auth.rb
CHANGED
@@ -13,7 +13,8 @@ module SimpleGoogleAuth
|
|
13
13
|
:google_token_url,
|
14
14
|
:state_session_key_name,
|
15
15
|
:data_session_key_name,
|
16
|
-
:request_parameters
|
16
|
+
:request_parameters,
|
17
|
+
:refresh_stale_tokens
|
17
18
|
) do
|
18
19
|
def get_or_call(attribute)
|
19
20
|
value = send(attribute)
|
@@ -26,6 +27,10 @@ module SimpleGoogleAuth
|
|
26
27
|
|
27
28
|
def self.configure
|
28
29
|
yield config
|
30
|
+
|
31
|
+
if config.refresh_stale_tokens
|
32
|
+
config.request_parameters.merge!({ access_type: "offline" })
|
33
|
+
end
|
29
34
|
end
|
30
35
|
|
31
36
|
def self.uri(state)
|
@@ -51,6 +56,8 @@ SimpleGoogleAuth.configure do |config|
|
|
51
56
|
config.authenticate = lambda { raise "You must define an authenticate lambda that sets the session" }
|
52
57
|
end
|
53
58
|
|
59
|
+
require 'simple_google_auth/http_client'
|
60
|
+
require 'simple_google_auth/oauth'
|
54
61
|
require 'simple_google_auth/engine'
|
55
62
|
require 'simple_google_auth/controller'
|
56
63
|
require 'simple_google_auth/receiver'
|
@@ -11,7 +11,36 @@ module SimpleGoogleAuth
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def google_auth_data
|
14
|
+
return unless google_auth_data_from_session
|
15
|
+
|
16
|
+
if should_refresh_google_auth_data?
|
17
|
+
refresh_google_auth_data
|
18
|
+
end
|
19
|
+
google_auth_data_from_session
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def refresh_google_auth_data
|
25
|
+
api = SimpleGoogleAuth::OAuth.new(SimpleGoogleAuth.config)
|
26
|
+
|
27
|
+
auth_data = api.refresh_auth_token!(google_auth_data_from_session["refresh_token"])
|
28
|
+
|
29
|
+
session[SimpleGoogleAuth.config.data_session_key_name] = auth_data
|
30
|
+
end
|
31
|
+
|
32
|
+
def google_auth_data_from_session
|
14
33
|
session[SimpleGoogleAuth.config.data_session_key_name]
|
15
34
|
end
|
35
|
+
|
36
|
+
def should_refresh_google_auth_data?
|
37
|
+
SimpleGoogleAuth.config.refresh_stale_tokens && google_auth_data_stale?
|
38
|
+
end
|
39
|
+
|
40
|
+
def google_auth_data_stale?
|
41
|
+
expiry_time = google_auth_data_from_session["expires_at"]
|
42
|
+
|
43
|
+
expiry_time.nil? || Time.parse(expiry_time).past?
|
44
|
+
end
|
16
45
|
end
|
17
46
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module SimpleGoogleAuth
|
2
|
+
class HttpClient
|
3
|
+
def initialize(url, ca_path)
|
4
|
+
@uri = URI(url)
|
5
|
+
@http = Net::HTTP.new(@uri.host, @uri.port)
|
6
|
+
setup_https(ca_path)
|
7
|
+
end
|
8
|
+
|
9
|
+
def request(params)
|
10
|
+
request = Net::HTTP::Post.new(@uri.request_uri)
|
11
|
+
request.set_form_data(params)
|
12
|
+
response = @http.request(request)
|
13
|
+
response.body
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def setup_https(ca_path)
|
18
|
+
if @uri.scheme == "https"
|
19
|
+
@http.use_ssl = true
|
20
|
+
if ca_path
|
21
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
22
|
+
@http.ca_path = ca_path
|
23
|
+
else
|
24
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
25
|
+
Rails.logger.warn "SimpleGoogleAuth does not have a ca_path configured; SSL with Google is not protected"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module SimpleGoogleAuth
|
2
|
+
class OAuth
|
3
|
+
def initialize(config)
|
4
|
+
@config = config
|
5
|
+
@client = HttpClient.new(@config.google_token_url, @config.ca_path)
|
6
|
+
end
|
7
|
+
|
8
|
+
def exchange_code_for_auth_token!(code)
|
9
|
+
response = @client.request(
|
10
|
+
code: code,
|
11
|
+
grant_type: "authorization_code",
|
12
|
+
client_id: @config.client_id,
|
13
|
+
client_secret: @config.client_secret,
|
14
|
+
redirect_uri: @config.redirect_uri)
|
15
|
+
|
16
|
+
parse_auth_response(response)
|
17
|
+
end
|
18
|
+
|
19
|
+
def refresh_auth_token!(refresh_token)
|
20
|
+
return if refresh_token.blank?
|
21
|
+
|
22
|
+
response = @client.request(
|
23
|
+
refresh_token: refresh_token,
|
24
|
+
client_id: @config.client_id,
|
25
|
+
client_secret: @config.client_secret,
|
26
|
+
grant_type: "refresh_token")
|
27
|
+
|
28
|
+
parse_auth_response(response).merge("refresh_token" => refresh_token)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def parse_auth_response(response)
|
33
|
+
auth_data = JSON.parse(response)
|
34
|
+
|
35
|
+
auth_data["expires_at"] = calculate_expiry(auth_data).to_s
|
36
|
+
|
37
|
+
id_data = decode_id_data(auth_data.delete("id_token"))
|
38
|
+
auth_data.merge!(id_data)
|
39
|
+
end
|
40
|
+
|
41
|
+
def calculate_expiry(auth_data)
|
42
|
+
Time.now + auth_data["expires_in"] - 5.seconds
|
43
|
+
end
|
44
|
+
|
45
|
+
def decode_id_data(id_data)
|
46
|
+
id_data_64 = id_data.split(".")[1]
|
47
|
+
id_data_64 << "=" until id_data_64.length % 4 == 0
|
48
|
+
JSON.parse(Base64.decode64(id_data_64))
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -5,14 +5,14 @@ module SimpleGoogleAuth
|
|
5
5
|
def call(env)
|
6
6
|
request = Rack::Request.new(env)
|
7
7
|
config = SimpleGoogleAuth.config
|
8
|
-
|
9
8
|
ensure_params_are_correct(request, config)
|
10
|
-
auth_data = obtain_authentication_data(request.params["code"], config)
|
11
|
-
id_data = decode_id_data(auth_data.delete("id_token"))
|
12
9
|
|
13
|
-
|
10
|
+
api = SimpleGoogleAuth::OAuth.new(config)
|
11
|
+
auth_data = api.exchange_code_for_auth_token!(request.params["code"])
|
12
|
+
|
13
|
+
raise Error, "Authentication failed" unless config.authenticate.call(auth_data)
|
14
14
|
|
15
|
-
request.session[config.data_session_key_name] =
|
15
|
+
request.session[config.data_session_key_name] = auth_data
|
16
16
|
|
17
17
|
path = request.session[config.state_session_key_name][32..-1]
|
18
18
|
path = "/" if path.blank?
|
@@ -35,41 +35,5 @@ module SimpleGoogleAuth
|
|
35
35
|
raise Error, "No authentication code returned"
|
36
36
|
end
|
37
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.get_or_call(:client_id),
|
58
|
-
client_secret: config.get_or_call(: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(id_data)
|
70
|
-
id_data_64 = id_data.split(".")[1]
|
71
|
-
id_data_64 << "=" until id_data_64.length % 4 == 0
|
72
|
-
JSON.parse(Base64.decode64(id_data_64))
|
73
|
-
end
|
74
38
|
end
|
75
39
|
end
|
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple_google_auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roger Nesbitt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 3.2.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 3.2.0
|
27
27
|
description: An extremely easy way to protect your site by requiring Google logins
|
@@ -32,15 +32,17 @@ executables: []
|
|
32
32
|
extensions: []
|
33
33
|
extra_rdoc_files: []
|
34
34
|
files:
|
35
|
+
- MIT-LICENSE
|
36
|
+
- README.md
|
37
|
+
- Rakefile
|
35
38
|
- config/routes.rb
|
39
|
+
- lib/simple_google_auth.rb
|
36
40
|
- lib/simple_google_auth/controller.rb
|
37
41
|
- lib/simple_google_auth/engine.rb
|
42
|
+
- lib/simple_google_auth/http_client.rb
|
43
|
+
- lib/simple_google_auth/oauth.rb
|
38
44
|
- lib/simple_google_auth/receiver.rb
|
39
45
|
- lib/simple_google_auth/version.rb
|
40
|
-
- lib/simple_google_auth.rb
|
41
|
-
- MIT-LICENSE
|
42
|
-
- Rakefile
|
43
|
-
- README.md
|
44
46
|
homepage: https://github.com/mogest/simple_google_auth
|
45
47
|
licenses:
|
46
48
|
- MIT
|
@@ -51,17 +53,17 @@ require_paths:
|
|
51
53
|
- lib
|
52
54
|
required_ruby_version: !ruby/object:Gem::Requirement
|
53
55
|
requirements:
|
54
|
-
- -
|
56
|
+
- - ">="
|
55
57
|
- !ruby/object:Gem::Version
|
56
58
|
version: '0'
|
57
59
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
60
|
requirements:
|
59
|
-
- -
|
61
|
+
- - ">="
|
60
62
|
- !ruby/object:Gem::Version
|
61
63
|
version: '0'
|
62
64
|
requirements: []
|
63
65
|
rubyforge_project:
|
64
|
-
rubygems_version: 2.
|
66
|
+
rubygems_version: 2.2.2
|
65
67
|
signing_key:
|
66
68
|
specification_version: 4
|
67
69
|
summary: Super simple Google authentication for your Rails site
|