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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 17bdbddcd052da79050cd43d146b6ba3070a808d
4
- data.tar.gz: 565fffa60eaef47bb69710a1830ee4315e73bf59
3
+ metadata.gz: b07e9d444f3a69575224aae7742706c4e857fd6b
4
+ data.tar.gz: 03baf12262054337668111cd951ea4b8e259faa1
5
5
  SHA512:
6
- metadata.gz: a83902d120549033da2bd08cd155e4f419dd9e512ef9a3a9240a654c3238119b36d9818feacdcdc8fcdd85ed8d2cb22a08e5df4a2fa0d7102c493e2360c85730
7
- data.tar.gz: 08e7e440d0c2c27142c7229e1cc88d9a26df65d4ce3ff7d45f3e2195e495a4cef5136c81b08d42cd2acf4517b8cda8b02d73e749c3f04dbf30ff8a3606ae7b23
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.
@@ -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
- raise Error, "Authentication failed" unless config.authenticate.call(id_data)
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] = id_data.merge(auth_data)
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
@@ -1,3 +1,3 @@
1
1
  module SimpleGoogleAuth
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  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.5
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: 2014-11-05 00:00:00.000000000 Z
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.0.14
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