google_sign_in 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ce2cbe6f38376f6f4ec06a59c7b0fcb916ed1611
4
+ data.tar.gz: 4acaea345f5840be79e9a2d77b301e96e2eaaf90
5
+ SHA512:
6
+ metadata.gz: db6f84a43691f47461ad4d7572d165fd23b2010fbc1f28b96dd81c624eef1e1af3b5070b56d1dce1fcb8293ce85d8dd74e3b134ca75aa14d24b6be94216d633d
7
+ data.tar.gz: 7c3a4756ceaf4e6a7a96fee9ddf361843b6c46f61c825023ab2319290d46f0cdcb799fa24eea4d88f0e7bc34eaa62a3074badd56b51035a13f311a59a319b514
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'rake'
6
+ gem 'byebug'
@@ -0,0 +1,40 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ google_sign_in (0.1)
5
+ activesupport (>= 5.1)
6
+ google-id-token (>= 1.3.1)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activesupport (5.1.1)
12
+ concurrent-ruby (~> 1.0, >= 1.0.2)
13
+ i18n (~> 0.7)
14
+ minitest (~> 5.1)
15
+ tzinfo (~> 1.1)
16
+ byebug (9.0.6)
17
+ concurrent-ruby (1.0.5)
18
+ google-id-token (1.3.1)
19
+ jwt
20
+ multi_json
21
+ i18n (0.8.1)
22
+ jwt (1.5.6)
23
+ minitest (5.10.2)
24
+ multi_json (1.12.1)
25
+ rake (12.0.0)
26
+ thread_safe (0.3.6)
27
+ tzinfo (1.2.3)
28
+ thread_safe (~> 0.1)
29
+
30
+ PLATFORMS
31
+ ruby
32
+
33
+ DEPENDENCIES
34
+ bundler (~> 1.15)
35
+ byebug
36
+ google_sign_in!
37
+ rake
38
+
39
+ BUNDLED WITH
40
+ 1.15.0
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2017 David Heinemeier Hansson, Basecamp
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.
@@ -0,0 +1,73 @@
1
+ # Google Sign-In for Rails
2
+
3
+ Google Sign-In provides an easy and secure way to let users signin into and up for your service,
4
+ without adding yet-another per-app email/password combination. Integrating it into your Rails app
5
+ should be drop-in easy. This gem makes it so.
6
+
7
+ The only configuration needed is setting the Google client id for your application. [Google has a
8
+ tutorial on how to setup a client id](https://developers.google.com/identity/sign-in/web/server-side-flow#step_1_create_a_client_id_and_client_secret).
9
+
10
+ Once you have your client id, create a `config/initializers/google_sign_in_client_id.rb` file with this:
11
+ `GoogleSignIn::Identity.client_id = <THAT CLIENT ID YOU GOT FROM GOOGLE>`
12
+
13
+ Now you can use the sign-in integration on your signup or sigin screen.
14
+
15
+ ## Example
16
+
17
+ Here's the most basic example:
18
+
19
+ ```ruby
20
+ # app/views/sessions/new.html.erb
21
+ <%= google_sign_in(url: session_path) do %>
22
+ <%= button_tag("Signin with Google") %>
23
+ <% end %>
24
+ ```
25
+
26
+ The `url` option is the URL that the hidden form will be submitted against along with the Google ID Token
27
+ that's set after the user has picked the account and authenticated in the pop-up window Google provides.
28
+
29
+ You can then use that in a sessions controller like so:
30
+
31
+ ```ruby
32
+ class SessionsController < ApplicationController
33
+ def new
34
+ end
35
+
36
+ def create
37
+ if user = authenticate_via_google
38
+ cookies.signed[:user_id] = user.id
39
+ redirect_to user
40
+ else
41
+ redirect_to new_session_url, alert: "authentication_failed"
42
+ end
43
+ end
44
+
45
+ private
46
+ def authenticate_via_google
47
+ if params[:google_id_token].present?
48
+ User.find_by google_id: GoogleSignIn::Identity.new(params[:google_id_token]).user_id
49
+ end
50
+ end
51
+ end
52
+ ```
53
+
54
+ (This example assumes that a user has already signed up for your service using Google Sign-In and that
55
+ you're storing the Google user id in the `User#google_id` attribute).
56
+
57
+ That's it! You can checkout the `GoogleSignIn::Identity` class for the thin wrapping it provides around
58
+ the decoding of the Google ID Token using the google-id-token library. Interrogating this identity object
59
+ for profile details is particularly helpful when you use Google for signup, as you can get the name, email
60
+ address, avatar url, and locale through it.
61
+
62
+ ## Unreleased gem caveat
63
+
64
+ The gem google-id-token is currently behind its GitHub repository on the release schedule. The latest release
65
+ is version 1.3.1 from 2015. So for now, you should depend on the github version in your app's Gemfile:
66
+
67
+ ```ruby
68
+ gem 'google-id-token', github: 'google/google-id-token'
69
+ ```
70
+
71
+ ## License
72
+
73
+ Google Sign-In for Rails is released under the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,10 @@
1
+ require "bundler/setup"
2
+ require "bundler/gem_tasks"
3
+ require "rake/testtask"
4
+
5
+ Rake::TestTask.new do |test|
6
+ test.libs << "test"
7
+ test.test_files = FileList["test/*_test.rb"]
8
+ end
9
+
10
+ task default: :test
@@ -0,0 +1,19 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'google_sign_in'
3
+ s.version = '0.1'
4
+ s.authors = 'David Heinemeier Hansson'
5
+ s.email = 'david@basecamp.com'
6
+ s.summary = 'Sign in (or up) with Google for Rails applications'
7
+ s.homepage = 'https://github.com/basecamp/google_sign_in'
8
+ s.license = 'MIT'
9
+
10
+ s.required_ruby_version = '>= 1.9.3'
11
+
12
+ s.add_dependency 'activesupport', '>= 5.1'
13
+ s.add_dependency 'google-id-token', '>= 1.3.1'
14
+
15
+ s.add_development_dependency 'bundler', '~> 1.15'
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- test/*`.split("\n")
19
+ end
@@ -0,0 +1,2 @@
1
+ require 'google_sign_in/identity'
2
+ require 'google_sign_in/railtie' if defined?(Rails)
@@ -0,0 +1,60 @@
1
+ require 'google_sign_in/identity'
2
+
3
+ module GoogleSignIn
4
+ module Helper
5
+ def google_sign_in(url:, &block)
6
+ content_for :head,
7
+ google_sign_in_javacript_include_tag +
8
+ google_sign_in_client_id_meta_tag
9
+
10
+ google_sign_in_javascript_tag +
11
+ google_sign_in_hidden_form_tag(url: url) +
12
+ google_sign_in_click_handler(&block)
13
+ end
14
+
15
+ private
16
+ def google_sign_in_javacript_include_tag
17
+ javascript_include_tag "https://apis.google.com/js/platform.js?onload=setupGoogleSignIn", async: true, defer: true
18
+ end
19
+
20
+ def google_sign_in_client_id_meta_tag
21
+ tag.meta name: "google-signin-client_id", content: GoogleSignIn::Identity.client_id
22
+ end
23
+
24
+ def google_sign_in_hidden_form_tag(url:)
25
+ form_with url: url, id: "google_signin", html: { style: "display: none" } do |form|
26
+ form.hidden_field :google_id_token, id: "google_id_token"
27
+ end
28
+ end
29
+
30
+ def google_sign_in_click_handler(&block)
31
+ tag.div(onclick: 'selectGoogleSignInAccount(event)') { capture(&block) }
32
+ end
33
+
34
+ def google_sign_in_javascript_tag
35
+ javascript_tag(<<-EOS
36
+ function setupGoogleSignIn() {
37
+ gapi.load("auth2", function () { gapi.auth2.init() })
38
+ }
39
+
40
+ function selectGoogleSignInAccount(event) {
41
+ event.preventDefault()
42
+
43
+ options = new gapi.auth2.SigninOptionsBuilder
44
+ options.setPrompt("select_account")
45
+
46
+ gapi.auth2.getAuthInstance().signIn(options).then(function (googleUser) {
47
+ var token = googleUser.getAuthResponse().id_token
48
+
49
+ if (token !== null) {
50
+ document.getElementById('google_id_token').value = token
51
+ document.getElementById('google_signin').submit()
52
+ gapi.auth2.getAuthInstance().signOut()
53
+ }
54
+ })
55
+ }
56
+ EOS
57
+ )
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,63 @@
1
+ require 'google-id-token'
2
+ require 'active_support/core_ext/class/attribute'
3
+ require 'active_support/core_ext/numeric/time'
4
+
5
+ module GoogleSignIn
6
+ class Identity
7
+ class_attribute :client_id
8
+
9
+ class_attribute :token_expiry
10
+ self.token_expiry = 5.minutes
11
+
12
+ class_attribute :logger
13
+ self.logger = defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
14
+
15
+ def initialize(token)
16
+ ensure_client_id_present
17
+ set_extracted_payload(token)
18
+ ensure_proper_audience
19
+ end
20
+
21
+ def user_id
22
+ @payload["sub"]
23
+ end
24
+
25
+ def name
26
+ @payload["name"]
27
+ end
28
+
29
+ def email_address
30
+ @payload["email"]
31
+ end
32
+
33
+ def email_verified?
34
+ @payload["email_verified"] == "true"
35
+ end
36
+
37
+ def avatar_url
38
+ @payload["picture"]
39
+ end
40
+
41
+ def locale
42
+ @payload["locale"]
43
+ end
44
+
45
+ private
46
+ def ensure_client_id_present
47
+ if client_id.blank?
48
+ raise ArgumentError, "GoogleSignIn.client_id must be set to validate identity"
49
+ end
50
+ end
51
+
52
+ def set_extracted_payload(token)
53
+ @payload = GoogleIDToken::Validator.new(expiry: token_expiry).check(token, client_id)
54
+ rescue GoogleIDToken::ValidationError => e
55
+ logger.error "Google token failed to validate (#{e.message})"
56
+ @payload = {}
57
+ end
58
+
59
+ def ensure_proper_audience
60
+ @payload["aud"].include?(client_id)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,12 @@
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
@@ -0,0 +1,9 @@
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
+ end
@@ -0,0 +1,4 @@
1
+ require 'bundler/setup'
2
+ require 'active_support'
3
+ require 'active_support/testing/autorun'
4
+ require 'byebug'
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: google_sign_in
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - David Heinemeier Hansson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '5.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '5.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: google-id-token
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.3.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 1.3.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.15'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.15'
55
+ description:
56
+ email: david@basecamp.com
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - Gemfile
62
+ - Gemfile.lock
63
+ - MIT-LICENSE
64
+ - README.md
65
+ - Rakefile
66
+ - google_sign_in.gemspec
67
+ - lib/google_sign_in.rb
68
+ - lib/google_sign_in/helper.rb
69
+ - lib/google_sign_in/identity.rb
70
+ - lib/google_sign_in/railtie.rb
71
+ - test/identity_test.rb
72
+ - test/test_helper.rb
73
+ homepage: https://github.com/basecamp/google_sign_in
74
+ licenses:
75
+ - MIT
76
+ metadata: {}
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: 1.9.3
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 2.6.11
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: Sign in (or up) with Google for Rails applications
97
+ test_files:
98
+ - test/identity_test.rb
99
+ - test/test_helper.rb