google_sign_in 0.1.4 → 1.0.0

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.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +12 -0
  3. data/.travis.yml +18 -0
  4. data/Gemfile.lock +130 -10
  5. data/README.md +114 -47
  6. data/Rakefile +31 -1
  7. data/SECURITY.md +15 -0
  8. data/app/controllers/google_sign_in/authorizations_controller.rb +17 -0
  9. data/app/controllers/google_sign_in/base_controller.rb +15 -0
  10. data/app/controllers/google_sign_in/callbacks_controller.rb +27 -0
  11. data/app/helpers/google_sign_in/button_helper.rb +7 -0
  12. data/bin/rails +16 -0
  13. data/config/routes.rb +4 -0
  14. data/google_sign_in.gemspec +9 -6
  15. data/lib/google_sign_in.rb +9 -1
  16. data/lib/google_sign_in/engine.rb +28 -0
  17. data/lib/google_sign_in/identity.rb +10 -21
  18. data/lib/google_sign_in/redirect_protector.rb +25 -0
  19. data/test/certificate.pem +19 -0
  20. data/test/controllers/authorizations_controller_test.rb +26 -0
  21. data/test/controllers/callbacks_controller_test.rb +36 -0
  22. data/test/dummy/.ruby-version +1 -0
  23. data/test/dummy/Rakefile +6 -0
  24. data/test/dummy/app/assets/config/manifest.js +3 -0
  25. data/test/dummy/app/assets/images/.keep +0 -0
  26. data/test/dummy/app/assets/javascripts/application.js +15 -0
  27. data/test/dummy/app/assets/javascripts/cable.js +13 -0
  28. data/test/dummy/app/assets/javascripts/channels/.keep +0 -0
  29. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  30. data/test/dummy/app/channels/application_cable/channel.rb +4 -0
  31. data/test/dummy/app/channels/application_cable/connection.rb +4 -0
  32. data/test/dummy/app/controllers/application_controller.rb +2 -0
  33. data/test/dummy/app/controllers/concerns/.keep +0 -0
  34. data/test/dummy/app/helpers/application_helper.rb +2 -0
  35. data/test/dummy/app/jobs/application_job.rb +2 -0
  36. data/test/dummy/app/mailers/application_mailer.rb +4 -0
  37. data/test/dummy/app/models/application_record.rb +3 -0
  38. data/test/dummy/app/models/concerns/.keep +0 -0
  39. data/test/dummy/app/views/layouts/application.html.erb +15 -0
  40. data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
  41. data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
  42. data/test/dummy/bin/bundle +3 -0
  43. data/test/dummy/bin/rails +4 -0
  44. data/test/dummy/bin/rake +4 -0
  45. data/test/dummy/bin/setup +36 -0
  46. data/test/dummy/bin/update +31 -0
  47. data/test/dummy/bin/yarn +11 -0
  48. data/test/dummy/config.ru +5 -0
  49. data/test/dummy/config/application.rb +20 -0
  50. data/test/dummy/config/boot.rb +5 -0
  51. data/test/dummy/config/cable.yml +10 -0
  52. data/test/dummy/config/database.yml +25 -0
  53. data/test/dummy/config/environment.rb +5 -0
  54. data/test/dummy/config/environments/development.rb +32 -0
  55. data/test/dummy/config/environments/production.rb +57 -0
  56. data/test/dummy/config/environments/test.rb +33 -0
  57. data/test/dummy/config/initializers/application_controller_renderer.rb +8 -0
  58. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  59. data/test/dummy/config/initializers/content_security_policy.rb +25 -0
  60. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  61. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  62. data/test/dummy/config/initializers/google_sign_in.rb +4 -0
  63. data/test/dummy/config/initializers/inflections.rb +16 -0
  64. data/test/dummy/config/initializers/mime_types.rb +4 -0
  65. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  66. data/test/dummy/config/locales/en.yml +33 -0
  67. data/test/dummy/config/puma.rb +34 -0
  68. data/test/dummy/config/routes.rb +2 -0
  69. data/test/dummy/config/spring.rb +6 -0
  70. data/test/dummy/config/storage.yml +34 -0
  71. data/test/dummy/lib/assets/.keep +0 -0
  72. data/test/dummy/log/.keep +0 -0
  73. data/test/dummy/package.json +5 -0
  74. data/test/dummy/public/404.html +67 -0
  75. data/test/dummy/public/422.html +67 -0
  76. data/test/dummy/public/500.html +66 -0
  77. data/test/dummy/public/apple-touch-icon-precomposed.png +0 -0
  78. data/test/dummy/public/apple-touch-icon.png +0 -0
  79. data/test/dummy/public/favicon.ico +0 -0
  80. data/test/helpers/button_helper_test.rb +36 -0
  81. data/test/key.pem +27 -0
  82. data/test/models/identity_test.rb +76 -0
  83. data/test/models/redirect_protector_test.rb +34 -0
  84. data/test/test_helper.rb +27 -3
  85. metadata +200 -10
  86. data/lib/google_sign_in/helper.rb +0 -76
  87. data/lib/google_sign_in/railtie.rb +0 -12
  88. data/test/identity_test.rb +0 -13
@@ -0,0 +1,34 @@
1
+ require 'test_helper'
2
+ require 'google_sign_in/redirect_protector'
3
+
4
+ class GoogleSignIn::RedirectProtectorTest < ActiveSupport::TestCase
5
+ test "disallows URL target with different host than source" do
6
+ assert_raises GoogleSignIn::RedirectProtector::Violation do
7
+ GoogleSignIn::RedirectProtector.ensure_same_origin 'https://malicious.example.com', 'https://basecamp.com'
8
+ end
9
+ end
10
+
11
+ test "disallows URL target with different port than source" do
12
+ assert_raises GoogleSignIn::RedirectProtector::Violation do
13
+ GoogleSignIn::RedirectProtector.ensure_same_origin 'https://basecamp.com:10443', 'https://basecamp.com'
14
+ end
15
+ end
16
+
17
+ test "disallows URL target with different protocol than source" do
18
+ assert_raises GoogleSignIn::RedirectProtector::Violation do
19
+ GoogleSignIn::RedirectProtector.ensure_same_origin 'http://basecamp.com', 'https://basecamp.com'
20
+ end
21
+ end
22
+
23
+ test "allows URL target with same origin as source" do
24
+ assert_nothing_raised do
25
+ GoogleSignIn::RedirectProtector.ensure_same_origin 'https://basecamp.com', 'https://basecamp.com'
26
+ end
27
+ end
28
+
29
+ test "allows path target" do
30
+ assert_nothing_raised do
31
+ GoogleSignIn::RedirectProtector.ensure_same_origin '/callback', 'https://basecamp.com'
32
+ end
33
+ end
34
+ end
@@ -1,4 +1,28 @@
1
- require 'bundler/setup'
2
- require 'active_support'
3
- require 'active_support/testing/autorun'
1
+ ENV['RAILS_ENV'] = 'test'
2
+
3
+ FAKE_GOOGLE_CLIENT_ID = '86179201039-eks5VfVc46WoFYyZVUDpQHeZFDRCqno3.apps.googleusercontent.com'
4
+ FAKE_GOOGLE_CLIENT_SECRET = 'r(XsBajmyMddruvf$jDgLyPK'
5
+
6
+ require_relative '../test/dummy/config/environment'
7
+
8
+ require 'rails/test_help'
9
+ require 'webmock/minitest'
4
10
  require 'byebug'
11
+
12
+ require 'openssl'
13
+ GOOGLE_PRIVATE_KEY = OpenSSL::PKey::RSA.new(File.read(File.expand_path('key.pem', __dir__)))
14
+ GOOGLE_X509_CERTIFICATE = OpenSSL::X509::Certificate.new(File.read(File.expand_path('certificate.pem', __dir__)))
15
+
16
+ if GOOGLE_X509_CERTIFICATE.not_after <= Time.now
17
+ raise "Test certificate is expired. Generate a new one and run the tests again: `bundle exec rake test:certificate:generate`."
18
+ end
19
+
20
+ require 'google-id-token'
21
+ GoogleSignIn::Identity.validator = GoogleIDToken::Validator.new(x509_cert: GOOGLE_X509_CERTIFICATE)
22
+
23
+ class ActionView::TestCase
24
+ private
25
+ def assert_dom_equal(expected, actual, message = nil)
26
+ super expected.remove(/(\A|\n)\s*/), actual, message
27
+ end
28
+ end
metadata CHANGED
@@ -1,29 +1,30 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google_sign_in
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
+ - George Claghorn
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2018-01-14 00:00:00.000000000 Z
12
+ date: 2018-09-05 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
- name: activesupport
15
+ name: rails
15
16
  requirement: !ruby/object:Gem::Requirement
16
17
  requirements:
17
18
  - - ">="
18
19
  - !ruby/object:Gem::Version
19
- version: '5.1'
20
+ version: 5.2.0
20
21
  type: :runtime
21
22
  prerelease: false
22
23
  version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
25
  - - ">="
25
26
  - !ruby/object:Gem::Version
26
- version: '5.1'
27
+ version: 5.2.0
27
28
  - !ruby/object:Gem::Dependency
28
29
  name: google-id-token
29
30
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +39,20 @@ dependencies:
38
39
  - - ">="
39
40
  - !ruby/object:Gem::Version
40
41
  version: 1.4.0
42
+ - !ruby/object:Gem::Dependency
43
+ name: oauth2
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: 1.4.0
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: 1.4.0
41
56
  - !ruby/object:Gem::Dependency
42
57
  name: bundler
43
58
  requirement: !ruby/object:Gem::Requirement
@@ -52,23 +67,130 @@ dependencies:
52
67
  - - "~>"
53
68
  - !ruby/object:Gem::Version
54
69
  version: '1.15'
70
+ - !ruby/object:Gem::Dependency
71
+ name: jwt
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: webmock
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
55
98
  description:
56
- email: david@basecamp.com
99
+ email:
100
+ - david@basecamp.com
101
+ - george@basecamp.com
57
102
  executables: []
58
103
  extensions: []
59
104
  extra_rdoc_files: []
60
105
  files:
106
+ - ".gitignore"
107
+ - ".travis.yml"
61
108
  - Gemfile
62
109
  - Gemfile.lock
63
110
  - MIT-LICENSE
64
111
  - README.md
65
112
  - Rakefile
113
+ - SECURITY.md
114
+ - app/controllers/google_sign_in/authorizations_controller.rb
115
+ - app/controllers/google_sign_in/base_controller.rb
116
+ - app/controllers/google_sign_in/callbacks_controller.rb
117
+ - app/helpers/google_sign_in/button_helper.rb
118
+ - bin/rails
119
+ - config/routes.rb
66
120
  - google_sign_in.gemspec
67
121
  - lib/google_sign_in.rb
68
- - lib/google_sign_in/helper.rb
122
+ - lib/google_sign_in/engine.rb
69
123
  - lib/google_sign_in/identity.rb
70
- - lib/google_sign_in/railtie.rb
71
- - test/identity_test.rb
124
+ - lib/google_sign_in/redirect_protector.rb
125
+ - test/certificate.pem
126
+ - test/controllers/authorizations_controller_test.rb
127
+ - test/controllers/callbacks_controller_test.rb
128
+ - test/dummy/.ruby-version
129
+ - test/dummy/Rakefile
130
+ - test/dummy/app/assets/config/manifest.js
131
+ - test/dummy/app/assets/images/.keep
132
+ - test/dummy/app/assets/javascripts/application.js
133
+ - test/dummy/app/assets/javascripts/cable.js
134
+ - test/dummy/app/assets/javascripts/channels/.keep
135
+ - test/dummy/app/assets/stylesheets/application.css
136
+ - test/dummy/app/channels/application_cable/channel.rb
137
+ - test/dummy/app/channels/application_cable/connection.rb
138
+ - test/dummy/app/controllers/application_controller.rb
139
+ - test/dummy/app/controllers/concerns/.keep
140
+ - test/dummy/app/helpers/application_helper.rb
141
+ - test/dummy/app/jobs/application_job.rb
142
+ - test/dummy/app/mailers/application_mailer.rb
143
+ - test/dummy/app/models/application_record.rb
144
+ - test/dummy/app/models/concerns/.keep
145
+ - test/dummy/app/views/layouts/application.html.erb
146
+ - test/dummy/app/views/layouts/mailer.html.erb
147
+ - test/dummy/app/views/layouts/mailer.text.erb
148
+ - test/dummy/bin/bundle
149
+ - test/dummy/bin/rails
150
+ - test/dummy/bin/rake
151
+ - test/dummy/bin/setup
152
+ - test/dummy/bin/update
153
+ - test/dummy/bin/yarn
154
+ - test/dummy/config.ru
155
+ - test/dummy/config/application.rb
156
+ - test/dummy/config/boot.rb
157
+ - test/dummy/config/cable.yml
158
+ - test/dummy/config/database.yml
159
+ - test/dummy/config/environment.rb
160
+ - test/dummy/config/environments/development.rb
161
+ - test/dummy/config/environments/production.rb
162
+ - test/dummy/config/environments/test.rb
163
+ - test/dummy/config/initializers/application_controller_renderer.rb
164
+ - test/dummy/config/initializers/backtrace_silencers.rb
165
+ - test/dummy/config/initializers/content_security_policy.rb
166
+ - test/dummy/config/initializers/cookies_serializer.rb
167
+ - test/dummy/config/initializers/filter_parameter_logging.rb
168
+ - test/dummy/config/initializers/google_sign_in.rb
169
+ - test/dummy/config/initializers/inflections.rb
170
+ - test/dummy/config/initializers/mime_types.rb
171
+ - test/dummy/config/initializers/wrap_parameters.rb
172
+ - test/dummy/config/locales/en.yml
173
+ - test/dummy/config/puma.rb
174
+ - test/dummy/config/routes.rb
175
+ - test/dummy/config/spring.rb
176
+ - test/dummy/config/storage.yml
177
+ - test/dummy/db/test.sqlite3
178
+ - test/dummy/lib/assets/.keep
179
+ - test/dummy/log/.keep
180
+ - test/dummy/package.json
181
+ - test/dummy/public/404.html
182
+ - test/dummy/public/422.html
183
+ - test/dummy/public/500.html
184
+ - test/dummy/public/apple-touch-icon-precomposed.png
185
+ - test/dummy/public/apple-touch-icon.png
186
+ - test/dummy/public/favicon.ico
187
+ - test/dummy/storage/.keep
188
+ - test/dummy/tmp/.keep
189
+ - test/dummy/tmp/storage/.keep
190
+ - test/helpers/button_helper_test.rb
191
+ - test/key.pem
192
+ - test/models/identity_test.rb
193
+ - test/models/redirect_protector_test.rb
72
194
  - test/test_helper.rb
73
195
  homepage: https://github.com/basecamp/google_sign_in
74
196
  licenses:
@@ -95,5 +217,73 @@ signing_key:
95
217
  specification_version: 4
96
218
  summary: Sign in (or up) with Google for Rails applications
97
219
  test_files:
98
- - test/identity_test.rb
220
+ - test/certificate.pem
221
+ - test/controllers/authorizations_controller_test.rb
222
+ - test/controllers/callbacks_controller_test.rb
223
+ - test/dummy/.ruby-version
224
+ - test/dummy/Rakefile
225
+ - test/dummy/app/assets/config/manifest.js
226
+ - test/dummy/app/assets/images/.keep
227
+ - test/dummy/app/assets/javascripts/application.js
228
+ - test/dummy/app/assets/javascripts/cable.js
229
+ - test/dummy/app/assets/javascripts/channels/.keep
230
+ - test/dummy/app/assets/stylesheets/application.css
231
+ - test/dummy/app/channels/application_cable/channel.rb
232
+ - test/dummy/app/channels/application_cable/connection.rb
233
+ - test/dummy/app/controllers/application_controller.rb
234
+ - test/dummy/app/controllers/concerns/.keep
235
+ - test/dummy/app/helpers/application_helper.rb
236
+ - test/dummy/app/jobs/application_job.rb
237
+ - test/dummy/app/mailers/application_mailer.rb
238
+ - test/dummy/app/models/application_record.rb
239
+ - test/dummy/app/models/concerns/.keep
240
+ - test/dummy/app/views/layouts/application.html.erb
241
+ - test/dummy/app/views/layouts/mailer.html.erb
242
+ - test/dummy/app/views/layouts/mailer.text.erb
243
+ - test/dummy/bin/bundle
244
+ - test/dummy/bin/rails
245
+ - test/dummy/bin/rake
246
+ - test/dummy/bin/setup
247
+ - test/dummy/bin/update
248
+ - test/dummy/bin/yarn
249
+ - test/dummy/config.ru
250
+ - test/dummy/config/application.rb
251
+ - test/dummy/config/boot.rb
252
+ - test/dummy/config/cable.yml
253
+ - test/dummy/config/database.yml
254
+ - test/dummy/config/environment.rb
255
+ - test/dummy/config/environments/development.rb
256
+ - test/dummy/config/environments/production.rb
257
+ - test/dummy/config/environments/test.rb
258
+ - test/dummy/config/initializers/application_controller_renderer.rb
259
+ - test/dummy/config/initializers/backtrace_silencers.rb
260
+ - test/dummy/config/initializers/content_security_policy.rb
261
+ - test/dummy/config/initializers/cookies_serializer.rb
262
+ - test/dummy/config/initializers/filter_parameter_logging.rb
263
+ - test/dummy/config/initializers/google_sign_in.rb
264
+ - test/dummy/config/initializers/inflections.rb
265
+ - test/dummy/config/initializers/mime_types.rb
266
+ - test/dummy/config/initializers/wrap_parameters.rb
267
+ - test/dummy/config/locales/en.yml
268
+ - test/dummy/config/puma.rb
269
+ - test/dummy/config/routes.rb
270
+ - test/dummy/config/spring.rb
271
+ - test/dummy/config/storage.yml
272
+ - test/dummy/db/test.sqlite3
273
+ - test/dummy/lib/assets/.keep
274
+ - test/dummy/log/.keep
275
+ - test/dummy/package.json
276
+ - test/dummy/public/404.html
277
+ - test/dummy/public/422.html
278
+ - test/dummy/public/500.html
279
+ - test/dummy/public/apple-touch-icon-precomposed.png
280
+ - test/dummy/public/apple-touch-icon.png
281
+ - test/dummy/public/favicon.ico
282
+ - test/dummy/storage/.keep
283
+ - test/dummy/tmp/.keep
284
+ - test/dummy/tmp/storage/.keep
285
+ - test/helpers/button_helper_test.rb
286
+ - test/key.pem
287
+ - test/models/identity_test.rb
288
+ - test/models/redirect_protector_test.rb
99
289
  - test/test_helper.rb
@@ -1,76 +0,0 @@
1
- require 'google_sign_in/identity'
2
-
3
- module GoogleSignIn
4
- module Helper
5
- def google_sign_in(**form_options, &block)
6
- content_for :head,
7
- google_sign_in_javacript_include_tag +
8
- google_sign_in_client_id_meta_tag +
9
- turbolinks_reload_meta_tag
10
-
11
- google_sign_in_javascript_tag +
12
- google_sign_in_hidden_form_tag(**form_options) +
13
- google_sign_in_click_handler(&block)
14
- end
15
-
16
- private
17
- def google_sign_in_javacript_include_tag
18
- javascript_include_tag "https://apis.google.com/js/api.js", async: true, defer: true,
19
- onload: "this.onload=function(){};setupGoogleSignIn()",
20
- onreadystatechange: "if (this.readyState === 'complete') this.onload()"
21
- end
22
-
23
- def google_sign_in_client_id_meta_tag
24
- tag.meta name: "google-signin-client_id", content: GoogleSignIn::Identity.client_id
25
- end
26
-
27
- def turbolinks_reload_meta_tag
28
- tag.meta name: "turbolinks-visit-control", content: "reload"
29
- end
30
-
31
- def google_sign_in_hidden_form_tag(**options)
32
- options.reverse_merge!(html: { style: "display: none" })
33
-
34
- form_with(**options) do |form|
35
- form.hidden_field(:google_id_token, id: "google_sign_in_token") + form.submit(id: "google_sign_in_submit")
36
- end
37
- end
38
-
39
- def google_sign_in_click_handler(&block)
40
- tag.div(id: "google_sign_in_container", style: "visibility: hidden") { capture(&block) }
41
- end
42
-
43
- def google_sign_in_javascript_tag
44
- javascript_tag <<-JS.strip_heredoc
45
- (function() {
46
- function installAuthClient(callback) {
47
- gapi.load("client:auth2", function() {
48
- gapi.auth2.init().then(callback)
49
- })
50
- }
51
-
52
- function installClickHandler() {
53
- var element = document.getElementById("google_sign_in_container")
54
- var options = new gapi.auth2.SigninOptionsBuilder()
55
- options.setPrompt("select_account")
56
- gapi.auth2.getAuthInstance().attachClickHandler(element, options, handleSignIn)
57
- element.style.visibility = "visible"
58
- }
59
-
60
- function handleSignIn(googleUser) {
61
- var token = googleUser.getAuthResponse().id_token
62
- if (token) {
63
- document.getElementById("google_sign_in_token").value = token
64
- document.getElementById("google_sign_in_submit").click()
65
- gapi.auth2.getAuthInstance().signOut()
66
- }
67
- }
68
-
69
- window.setupGoogleSignIn = function() {
70
- installAuthClient(installClickHandler)
71
- }
72
- })()
73
- JS
74
- end
75
- end
76
- end
@@ -1,12 +0,0 @@
1
- require 'rails/railtie'
2
- require 'google_sign_in/helper'
3
-
4
- module GoogleSignIn
5
- class Engine < ::Rails::Engine
6
- initializer :google_sign_in do |app|
7
- ActiveSupport.on_load :action_controller do
8
- ActionController::Base.send :helper, GoogleSignIn::Helper
9
- end
10
- end
11
- end
12
- end
@@ -1,13 +0,0 @@
1
- require 'test_helper'
2
- require 'google_sign_in/identity'
3
-
4
- class GoogleSignIn::IdentityTest < ActiveSupport::TestCase
5
- test "client_id must be set" do
6
- GoogleSignIn::Identity.client_id = nil
7
- assert_raises(ArgumentError) { GoogleSignIn::Identity.new("some_fake_token") }
8
- end
9
-
10
- test "client_id must be part of the audience" do
11
- # FIXME: Need to build a mock/simulate the google token to test this
12
- end
13
- end