google_client_login 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in google_client_login.gemspec
4
+ gemspec
@@ -0,0 +1,24 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ google_client_login (0.3.0)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.1.2)
10
+ rspec (2.4.0)
11
+ rspec-core (~> 2.4.0)
12
+ rspec-expectations (~> 2.4.0)
13
+ rspec-mocks (~> 2.4.0)
14
+ rspec-core (2.4.0)
15
+ rspec-expectations (2.4.0)
16
+ diff-lcs (~> 1.1.2)
17
+ rspec-mocks (2.4.0)
18
+
19
+ PLATFORMS
20
+ ruby
21
+
22
+ DEPENDENCIES
23
+ google_client_login!
24
+ rspec (>= 2.0.0)
data/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2010 Toon Willems
4
+
5
+ Permission is hereby granted, free of charge, to any person
6
+ obtaining a copy of this software and associated documentation
7
+ files (the "Software"), to deal in the Software without
8
+ restriction, including without limitation the rights to use,
9
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the
11
+ Software is furnished to do so, subject to the following
12
+ conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,139 @@
1
+ h1. Google_Client_Login Gem
2
+
3
+ This gem provides authorization for access to Google API-based services using Google's ClientLogin scheme. Add this gem to a Rails application to gain access to Google services that require login to a user's Google account.
4
+
5
+ The Google ClientLogin scheme is described in this document: "http://code.google.com/apis/accounts/docs/AuthForInstalledApps.html":http://code.google.com/apis/accounts/docs/AuthForInstalledApps.html
6
+
7
+ h2. Similar Gems
8
+
9
+ For an alternative implementation, see Jason L. Perry's "https://github.com/ambethia/google-client_login":https://github.com/ambethia/google-client_login. Note the similarity in gem names. Jason L. Perry's gem is "google-client_login" (with one hyphen and one underscore). This gem is "google_client_login" (with two underscores).
10
+
11
+ h2. Implementation
12
+
13
+ h3. What Is Implemented
14
+
15
+ Given an email address and a password, this gem will request an authorization token from Google. The gem accommodates all error conditions with robust exception handling, including conditions where Google presents a CAPTCHA challenge.
16
+
17
+ h3. What Is Not Implemented
18
+
19
+ By itself, this gem is not sufficient to implement access to any Google API. It only provides an authorization token. Access to most Google APIs requires additional code to provide details such as a developer identity token in addition to the authorization token.
20
+
21
+ h3. An Example: Accessing the Google AdWords API
22
+
23
+ Using the Google AdWords API, you can control most aspects of an AdWords campaign programmatically. A developer applies for AdWords API access from within an AdWords "My Client Center" (MCC) account. The developer is assigned a "developer token" once the application is approved. This unique text string of letters, numbers and symbols must be included in every API request to the servers. In addition to supplying the developer token in every API request, the application also must provide an "authorization token". The authorization token is sent as part of the API request as a form of proof that you are who you claim to be, and that you are allowed access to the API. Your application obtains authorization separately from API requests, making it a two step process: first retrieve a token, and then include it with your requests. You obtain an authorization token by sending a login request to Google's servers, providing an email address and password that matches your Google account. This gem provides the library that allows you to obtain the authorization token.
24
+
25
+ Here is Google's documentation about how ClientLogin works with the AdWords API: "http://adwordsapi.blogspot.com/2010/07/discover-v2009-working-with-authtokens.html":http://adwordsapi.blogspot.com/2010/07/discover-v2009-working-with-authtokens.html
26
+
27
+ h2. Dependencies
28
+
29
+ This app is based on the Ruby language version 1.8.7 or 1.9.2 and has been tested with Rails 3.0.3.
30
+
31
+ Check that appropriate versions of Ruby and Rails are installed in your development environment:
32
+
33
+ <pre>
34
+ $ ruby -v
35
+ $ rails -v
36
+ </pre>
37
+
38
+ h2. Usage
39
+
40
+ h3. Basic Usage
41
+
42
+ Include this gem in your Gemfile:
43
+
44
+ @gem "google_client_login"@
45
+
46
+ Be sure to run @bundle install@.
47
+
48
+ Create a method for authentication in a Rails model or controller. This example would be suitable for access to the AdWords API:
49
+
50
+ <pre>
51
+ def authenticate(email, password)
52
+ login_service = GoogleClientLogin::GoogleAuth.new(:accountType => 'GOOGLE',
53
+ :service => 'adwords',
54
+ :source => 'companyName-applicationName-versionID')
55
+ login_service.authenticate(email, password)
56
+ auth_token = login_service.auth
57
+ end
58
+ </pre>
59
+
60
+ Three parameters are supplied to the initialization method: service, source and (optionally) accountType.
61
+
62
+ * :service - the service identifier (see your Google API documentation)
63
+ * :source - the name of your application, like "companyName-applicationName-versionID"
64
+ * :accountType - "GOOGLE", "HOSTED", "HOSTED_OR_GOOGLE" (default)
65
+
66
+ After initializing an instance of GoogleAuth and calling the @authenticate@ method, if there is no exception thrown, you can obtain the authentication token by calling the @auth@ method.
67
+
68
+ In the response, Google provides additional values, labeled "SID" and "LSID", which are not useful (Google says they "are not currently active and should not be used"). You could use the @sid@ and @lsid@ methods to obtain these values.
69
+
70
+ h3. Advanced Usage (Handling CAPTCHA)
71
+
72
+ To block automated attempts to obtain user passwords, Google may add a visual CAPTCHA™ to the authentication process; this usually happens when the server suspects an illegal intrusion, such as after too many incorrect login attempts. A CAPTCHA ensures that a real person is trying to log in. When this happens the @authenticate@ method will raise an exception (@CaptchaRequired@).
73
+
74
+ The URL to the CAPTCHA is accesible via the @captcha_url@ method. Extending the example given above:
75
+
76
+ <pre>
77
+ login_service.captcha_url
78
+ => http://www.google.com/accounts/Captcha?ctoken=HiteT4b0Bk5Xg18_AcVoP6-yFkHPibe7O9EqxeiI7lUSN
79
+ </pre>
80
+
81
+ You can write code to catch the @CaptchaRequired@ exception and display the CAPTCHA image. After the user has interpreted the CAPTCHA, you can resubmit the authentication request including the user's CAPTCHA response.
82
+
83
+ @login_service.authenticate email, password, captcha_response@
84
+
85
+ You can use a convenient block construct. If you give a block to the @authenticate@ method, the block will be called with the CAPTCHA URL. The return value from the block should be the CAPTCHA answer. And it will attempt to authenticate again automatically.
86
+
87
+ h2. Testing
88
+
89
+ The gem includes tests created with RSpec. If you've obtained the source code for the gem, you can run the tests:
90
+
91
+ @rake spec@
92
+
93
+ h2. Documentation and Support
94
+
95
+ This application is provided without additional documentation or support.
96
+
97
+ Any issues? Please create an "Issue":http://github.com/fortuity/google_client_login/issues on GitHub.
98
+
99
+ h2. Contributing
100
+
101
+ If you make improvements to this application, please share with others.
102
+
103
+ * Fork the project on GitHub.
104
+ * Make your feature addition or bug fix.
105
+ * Commit with Git.
106
+ * Send the author a pull request.
107
+
108
+ If you add functionality to this application, create an alternative implementation, or build an application that shows how this gem can be used, please contact me and I'll add a note to the README so that others can find your work.
109
+
110
+ h2. Credits
111
+
112
+ Toon Willems ("http://twitter.com/nudded":http://twitter.com/nudded) created the Ruby library.
113
+
114
+ Daniel Kehoe ("http://twitter.com/yaxdotcom":http://twitter.com/yaxdotcom) created the gem.
115
+
116
+ h2. MIT License
117
+
118
+ Copyright (c) 2010 Toon Willems
119
+
120
+ Permission is hereby granted, free of charge, to any person
121
+ obtaining a copy of this software and associated documentation
122
+ files (the "Software"), to deal in the Software without
123
+ restriction, including without limitation the rights to use,
124
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
125
+ copies of the Software, and to permit persons to whom the
126
+ Software is furnished to do so, subject to the following
127
+ conditions:
128
+
129
+ The above copyright notice and this permission notice shall be
130
+ included in all copies or substantial portions of the Software.
131
+
132
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
133
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
134
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
135
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
136
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
137
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
138
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
139
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,9 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake'
5
+ require "rspec/core/rake_task"
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ task :default => [:spec]
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "google_client_login/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "google_client_login"
7
+ s.version = GoogleClientLogin::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Daniel Kehoe"]
10
+ s.email = ["kehoe@fortuity.com"]
11
+ s.homepage = "http://github.com/fortuity/google_client_login"
12
+ s.summary = %q{Authentication for Google APIs using the Google ClientLogin.}
13
+ s.description = %q{Use this gem for access to Google services protected by a user's Google or Google Apps account.}
14
+
15
+ s.rubyforge_project = "google_client_login"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ s.add_development_dependency "rspec", ">= 2.0.0"
22
+ end
@@ -0,0 +1,137 @@
1
+ require "net/https"
2
+ require "uri"
3
+
4
+ module GoogleClientLogin
5
+
6
+ # Use this Class to get an auth-token
7
+ class GoogleAuth
8
+
9
+ # Base Exception class
10
+ LoginError = Class.new Exception
11
+
12
+ # All the possible exceptions
13
+ [
14
+ "BadAuthentication",
15
+ "NotVerified",
16
+ "TermsNotAgreed",
17
+ "CaptchaRequired",
18
+ "Unknown",
19
+ "AccountDeleted",
20
+ "AccountDisabled",
21
+ "ServiceDisabled",
22
+ "ServiceUnavailable",
23
+ ].each do |const|
24
+ const_set const, Class.new(LoginError)
25
+ end
26
+
27
+ DEFAULTS = {
28
+ :accountType => 'HOSTED_OR_GOOGLE' ,
29
+ :source => 'companyName-applicationName-versionID',
30
+ :service => 'service-identifier'
31
+ }
32
+
33
+ attr_reader :auth, :sid, :lsid, :captcha_url
34
+
35
+ # specify the :service, :source and optionally :accountType
36
+ #
37
+ # [:service] the service identifier, check the google api documentation.
38
+ #
39
+ # [:source] the name of your application. String should be in the form
40
+ # "companyName-applicationName-versionID".
41
+ #
42
+ # [:accountType] one of the following values:
43
+ # "GOOGLE", "HOSTED", "HOSTED_OR_GOOGLE" (default if none
44
+ # given)
45
+ def initialize(arghash = {})
46
+ @options = DEFAULTS.merge arghash
47
+ end
48
+
49
+
50
+ # authenticate a user, which sets the auth, sid and lsid instance_variables
51
+ # if you provide a block, it will be called with a captcha url if google
52
+ # forces you to answer the captcha. Make sure you return the answer in the block.
53
+ #
54
+ # if no block is given, this will raise a CaptchaRequired error.
55
+ # you can rescue them and show the url via the captcha_url method.
56
+ #
57
+ # you can then call authenticate and as 3rd parameter you provide the
58
+ # captcha answer.
59
+ #
60
+ # all Exceptions this raises are subclasses of ClientLogin::LoginError.
61
+ # so make sure you handle them.
62
+ #
63
+ # This is a list of all the possible errors and their meaning
64
+ # Error code:: Description
65
+ # BadAuthentication:: The login request used a username or password that is not recognized.
66
+ # NotVerified:: The account email address has not been verified. The user will need to access their Google account directly to resolve the issue before logging in using a non-Google application.
67
+ # TermsNotAgreed:: The user has not agreed to terms. The user will need to access their Google account directly to resolve the issue before logging in using a non-Google application.
68
+ # CaptchaRequired:: A CAPTCHA is required. (A response with this error code will also contain an image URL and a CAPTCHA token.)
69
+ # Unknown:: The error is unknown or unspecified; the request contained invalid input or was malformed.
70
+ # AccountDeleted:: The user account has been deleted.
71
+ # AccountDisabled:: The user account has been disabled.
72
+ # ServiceDisabled:: The user's access to the specified service has been disabled. (The user account may still be valid.)
73
+ # ServiceUnavailable:: The service is not available; try again later.
74
+ def authenticate(username, password, captcha_response = nil)
75
+ @options[:Email], @options[:Passwd] = username, password
76
+ # set logincaptcha, captchatoken will already be set
77
+ @options[:logincaptcha] = captcha_response if captcha_response
78
+
79
+ parse_response perform_request
80
+
81
+ rescue CaptchaRequired
82
+ if block_given?
83
+ @options[:logincaptcha] = yield captcha_url
84
+ retry
85
+ else
86
+ raise CaptchaRequired
87
+ end
88
+ end
89
+
90
+ private
91
+
92
+ def perform_request
93
+ request = Net::HTTP::Post.new '/accounts/ClientLogin'
94
+ request.form_data = @options
95
+
96
+ https = Net::HTTP.new 'www.google.com', 443
97
+ https.use_ssl = true
98
+
99
+ https.request request
100
+ end
101
+
102
+ def parse_body(response_body)
103
+ response_body.scan(/(\w+)=(.+)\n/).each do |key, value|
104
+ instance_variable_set "@#{key.downcase}" , value
105
+ end
106
+ end
107
+
108
+ def parse_response(response)
109
+ if response.code_type == Net::HTTPOK
110
+ parse_body response.body
111
+ else
112
+ handle_error response.body
113
+ end
114
+ end
115
+
116
+
117
+ def handle_error(response_body)
118
+ error_message = response_body.match(/Error=(\w+)\n/)[1].strip
119
+
120
+ if error_message == "CaptchaRequired"
121
+ @options[:logintoken] = response_body.match(/CaptchaToken=(.+)\n/)[1]
122
+ self.captcha_url = response_body.match(/CaptchaUrl=(.+)\n/)[1]
123
+ end
124
+
125
+ raise_error_class error_message
126
+ end
127
+
128
+ def raise_error_class(error_message)
129
+ raise self.class.const_get error_message
130
+ end
131
+
132
+ def captcha_url=(url)
133
+ @captcha_url = "http://www.google.com/accounts/" << url
134
+ end
135
+
136
+ end
137
+ end
@@ -0,0 +1,3 @@
1
+ module GoogleClientLogin
2
+ VERSION = "0.3.1"
3
+ end
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+
3
+ describe "login attempt" do
4
+
5
+ context "successful login" do
6
+
7
+ it "should have an authentication token"
8
+
9
+ end
10
+
11
+ context "failed login" do
12
+
13
+ it "should not have an authentication token"
14
+
15
+ end
16
+
17
+
18
+ end
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'google_client_login' # and any other gems you need
5
+
6
+ RSpec.configure do |config|
7
+ # some (optional) config here
8
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: google_client_login
3
+ version: !ruby/object:Gem::Version
4
+ hash: 17
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 3
9
+ - 1
10
+ version: 0.3.1
11
+ platform: ruby
12
+ authors:
13
+ - Daniel Kehoe
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-13 00:00:00 -08:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rspec
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 15
30
+ segments:
31
+ - 2
32
+ - 0
33
+ - 0
34
+ version: 2.0.0
35
+ type: :development
36
+ version_requirements: *id001
37
+ description: Use this gem for access to Google services protected by a user's Google or Google Apps account.
38
+ email:
39
+ - kehoe@fortuity.com
40
+ executables: []
41
+
42
+ extensions: []
43
+
44
+ extra_rdoc_files: []
45
+
46
+ files:
47
+ - .gitignore
48
+ - Gemfile
49
+ - Gemfile.lock
50
+ - LICENSE
51
+ - README.textile
52
+ - Rakefile
53
+ - google_client_login.gemspec
54
+ - lib/google_client_login.rb
55
+ - lib/google_client_login/version.rb
56
+ - spec/login_spec.rb
57
+ - spec/spec_helper.rb
58
+ has_rdoc: true
59
+ homepage: http://github.com/fortuity/google_client_login
60
+ licenses: []
61
+
62
+ post_install_message:
63
+ rdoc_options: []
64
+
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ hash: 3
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ hash: 3
82
+ segments:
83
+ - 0
84
+ version: "0"
85
+ requirements: []
86
+
87
+ rubyforge_project: google_client_login
88
+ rubygems_version: 1.3.7
89
+ signing_key:
90
+ specification_version: 3
91
+ summary: Authentication for Google APIs using the Google ClientLogin.
92
+ test_files:
93
+ - spec/login_spec.rb
94
+ - spec/spec_helper.rb