identity-toolkit-ruby-client 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.rdoc +66 -0
- data/lib/gitkit_client.rb +289 -0
- data/lib/rpc_helper.rb +209 -0
- metadata +103 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c99e7fd2191547c175870cb9656f018696d29a94
|
4
|
+
data.tar.gz: 6eb020bd9c8d326ca1790c175ce703528a67e1f1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5a2657585eef66bde0f66fb1e18af4ccef23ff5b7829d094a6e6a2fe60dcbc315ba7bb2930aaf546f5c2a9adde3f72eaba39696f44c3e72660c4ffbedfe93d14
|
7
|
+
data.tar.gz: 424ace8fdd5c630d0767ac4d31a2f360c468563532b8c686d087e0e79105b1d94d26240ad6795bb00eb1ce43282d7bf22064b75828cea2716534ee6a434f197a
|
data/README.rdoc
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
= Google Identity Toolkit Ruby Client
|
2
|
+
|
3
|
+
Google Identity Toolkit (Gitkit) ruby client library is for third party sites to easily integrate with Gitkit service.
|
4
|
+
|
5
|
+
=== Installation
|
6
|
+
|
7
|
+
gem install identity_toolkit_ruby_client
|
8
|
+
|
9
|
+
=== Examples
|
10
|
+
|
11
|
+
require 'gitkit_client'
|
12
|
+
|
13
|
+
# Create a server config file or download it from Google Developer Console
|
14
|
+
# The config file contains Gitkit library config in json format
|
15
|
+
# {
|
16
|
+
# "clientId" : "oauth2-web-client-id.apps.googleusercontent.com",
|
17
|
+
# "serviceAccountEmail" : "service-account-email@developer.gserviceaccount.com",
|
18
|
+
# "serviceAccountPrivateKeyFile" : "path-to-service-account-private-key-file.p12",
|
19
|
+
# "widgetUrl" : "full-url-of-gitkit-widget-on-your-site",
|
20
|
+
# "cookieName" : "gtoken",
|
21
|
+
# "serverKey" : "devconsole-server-key"
|
22
|
+
# }
|
23
|
+
|
24
|
+
# Create a Gitkit client
|
25
|
+
gitkit_client = GitkitLib::GitkitClient.create_from_config_file 'gitkit-server-config.json'
|
26
|
+
|
27
|
+
# Verify the Gitkit token in the incoming http request
|
28
|
+
token = request.cookies["gtoken"]
|
29
|
+
user = gitkit_client.verify_gitkit_token token
|
30
|
+
|
31
|
+
# Upload passwords
|
32
|
+
def calc_sha1(key, plain_text, salt)
|
33
|
+
hmac = OpenSSL::HMAC.new key, 'sha1'
|
34
|
+
hmac << plain_text
|
35
|
+
hmac << salt
|
36
|
+
hmac.digest
|
37
|
+
end
|
38
|
+
|
39
|
+
hash_key = 'hash-key'
|
40
|
+
|
41
|
+
user1 = GitkitLib::GitkitUser.new
|
42
|
+
user1.email = '1234@example.com'
|
43
|
+
user1.user_id = '1234'
|
44
|
+
user1.salt = 'salt-1'
|
45
|
+
user1.password_hash = calc_sha1(hash_key, '1111', 'salt-1')
|
46
|
+
|
47
|
+
user2 = GitkitLib::GitkitUser.new
|
48
|
+
user2.email = '5678@example.com'
|
49
|
+
user2.user_id = '5678'
|
50
|
+
user2.salt = 'salt-2'
|
51
|
+
user2.password_hash = calc_sha1(hash_key, '5555', 'salt-2')
|
52
|
+
user2.name = '56 78'
|
53
|
+
|
54
|
+
gitkit_client.upload_users 'HMAC_SHA1', hash_key, [user1, user2]
|
55
|
+
|
56
|
+
# Get user by email
|
57
|
+
user = gitkit_client.get_user_by_email('1234@example.com')
|
58
|
+
|
59
|
+
# Get user by id
|
60
|
+
user = gitkit_client.get_user_by_id('5678')
|
61
|
+
|
62
|
+
# Delete a user
|
63
|
+
gitkit_client.delete_user '5678'
|
64
|
+
|
65
|
+
# Download all accounts
|
66
|
+
gitkit_client.get_all_users(2) { |account| pp account}
|
@@ -0,0 +1,289 @@
|
|
1
|
+
# Copyright 2014 Google Inc. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require 'addressable/uri'
|
16
|
+
require 'jwt'
|
17
|
+
require 'json'
|
18
|
+
require 'rpc_helper'
|
19
|
+
require 'uri'
|
20
|
+
|
21
|
+
module GitkitLib
|
22
|
+
|
23
|
+
class GitkitClient
|
24
|
+
|
25
|
+
# Create a client from json config file
|
26
|
+
#
|
27
|
+
# @param [String] file file name of the json-format config
|
28
|
+
def self.create_from_config_file(file)
|
29
|
+
config = JSON.parse File.open(file, 'rb') { |io| io.read }
|
30
|
+
p12key = File.open(config['serviceAccountPrivateKeyFile'], 'rb') {
|
31
|
+
|io| io.read }
|
32
|
+
new(
|
33
|
+
config['clientId'],
|
34
|
+
config['serviceAccountEmail'],
|
35
|
+
p12key,
|
36
|
+
config['widgetUrl'],
|
37
|
+
config['serverApiKey'])
|
38
|
+
end
|
39
|
+
|
40
|
+
# Initializes a GitkitClient.
|
41
|
+
#
|
42
|
+
# @param [String] client_id Google oauth2 web client id of this site
|
43
|
+
# @param [String] service_account_email Google service account email
|
44
|
+
# @param [String] service_account_key Google service account private p12 key
|
45
|
+
# @param [String] widget_url url to host the Gitkit widget
|
46
|
+
# @param [String] server_api_key server-side Google API key
|
47
|
+
def initialize(client_id, service_account_email, service_account_key,
|
48
|
+
widget_url, server_api_key = nil)
|
49
|
+
@client_id = client_id
|
50
|
+
@widget_url = widget_url
|
51
|
+
@rpc_helper = RpcHelper.new(service_account_email, service_account_key,
|
52
|
+
server_api_key)
|
53
|
+
@certificates = {}
|
54
|
+
end
|
55
|
+
|
56
|
+
# Verifies a Gitkit token
|
57
|
+
#
|
58
|
+
# @param [String] token_string the token to be verified
|
59
|
+
# @return [GitkitUser, nil] for valid token, [nil, String] otherwise with
|
60
|
+
# error_message.
|
61
|
+
def verify_gitkit_token(token_string)
|
62
|
+
if token_string.nil?
|
63
|
+
return nil, 'no token'
|
64
|
+
end
|
65
|
+
begin
|
66
|
+
key_finder = lambda {|header|
|
67
|
+
key_id = header['kid']
|
68
|
+
unless @certificates.has_key? key_id
|
69
|
+
@certificates = Hash[get_certs.map {|key,cert|
|
70
|
+
[key, OpenSSL::X509::Certificate.new(cert)]}]
|
71
|
+
end
|
72
|
+
@certificates[key_id].public_key }
|
73
|
+
parsed_token = JWT.decode(token_string, nil, true, &key_finder).first
|
74
|
+
# check expiration time
|
75
|
+
if Time.new.to_i > parsed_token['exp']
|
76
|
+
return nil, 'token expired'
|
77
|
+
end
|
78
|
+
# check audience
|
79
|
+
if parsed_token['aud'] != @client_id
|
80
|
+
return nil, 'audience mismatch'
|
81
|
+
end
|
82
|
+
GitkitUser.parse_from_api_response parsed_token
|
83
|
+
rescue JWT::DecodeError => e
|
84
|
+
return nil, e.message
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Gets Gitkit public certs
|
89
|
+
#
|
90
|
+
# @api private
|
91
|
+
def get_certs
|
92
|
+
@rpc_helper.get_gitkit_certs()
|
93
|
+
end
|
94
|
+
|
95
|
+
# Gets user info by email
|
96
|
+
#
|
97
|
+
# @param [String] email user email
|
98
|
+
# @return [GitkitUser] for the email
|
99
|
+
def get_user_by_email(email)
|
100
|
+
response = @rpc_helper.get_user_by_email email
|
101
|
+
GitkitUser.parse_from_api_response response.fetch('users', [{}])[0]
|
102
|
+
end
|
103
|
+
|
104
|
+
# Gets user info by user id
|
105
|
+
#
|
106
|
+
# @param [String] id user id
|
107
|
+
# @return [GitkitUser] for the id
|
108
|
+
def get_user_by_id(id)
|
109
|
+
response = @rpc_helper.get_user_by_id id
|
110
|
+
GitkitUser.parse_from_api_response response.fetch('users', [{}])[0]
|
111
|
+
end
|
112
|
+
|
113
|
+
# Downloads all user accounts from Gitkit service
|
114
|
+
#
|
115
|
+
# @param [Fixnum] max_results pagination size of each request
|
116
|
+
# @yield [GitkitUser] individual user account
|
117
|
+
def get_all_users(max_results = 10)
|
118
|
+
next_page_token = nil
|
119
|
+
while true
|
120
|
+
next_page_token, accounts = @rpc_helper.download_account(
|
121
|
+
next_page_token, max_results)
|
122
|
+
accounts.each { |account|
|
123
|
+
yield GitkitUser.parse_from_api_response account }
|
124
|
+
if not next_page_token or accounts.length == 0
|
125
|
+
break
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Uploads multiple accounts to Gitkit service
|
131
|
+
#
|
132
|
+
# @param [String] hash_algorithm password hash algorithm
|
133
|
+
# @param [String] hash_key key of the hash algorithm
|
134
|
+
# @param [Array<GitkitUser>] accounts user accounts to be uploaded
|
135
|
+
def upload_users(hash_algorithm, hash_key, accounts)
|
136
|
+
account_request = accounts.collect { |account| account.to_request }
|
137
|
+
@rpc_helper.upload_account hash_algorithm, JWT.base64url_encode(hash_key),
|
138
|
+
account_request
|
139
|
+
end
|
140
|
+
|
141
|
+
# Deletes a user account from Gitkit service
|
142
|
+
#
|
143
|
+
# @param [String] local_id user id to be deleted
|
144
|
+
def delete_user(local_id)
|
145
|
+
@rpc_helper.delete_account local_id
|
146
|
+
end
|
147
|
+
|
148
|
+
# Get one-time out-of-band code for ResetPassword/ChangeEmail request
|
149
|
+
#
|
150
|
+
# @param [String] full_url the full URL of incoming request
|
151
|
+
# @param [Hash{String=>String}] param dict of HTTP POST params
|
152
|
+
# @param [String] user_ip end user's IP address
|
153
|
+
# @param [String] gitkit_token the gitkit token if user logged in
|
154
|
+
#
|
155
|
+
# @return [Hash] {
|
156
|
+
# email: user email who is asking reset password
|
157
|
+
# oobLink: the generated link to be send to user's email
|
158
|
+
# action: OobAction
|
159
|
+
# response_body: the http body to be returned
|
160
|
+
# }
|
161
|
+
def get_oob_result(full_url, param, user_ip, gitkit_token=nil)
|
162
|
+
if param.has_key? 'action'
|
163
|
+
begin
|
164
|
+
if param['action'] == 'resetPassword'
|
165
|
+
oob_link = build_oob_link(full_url,
|
166
|
+
password_reset_request(param, user_ip),
|
167
|
+
param['action'])
|
168
|
+
return password_reset_response(oob_link, param)
|
169
|
+
elsif param['action'] == 'changeEmail'
|
170
|
+
unless gitkit_token
|
171
|
+
return failure_msg('login is required')
|
172
|
+
end
|
173
|
+
oob_link = build_oob_link(full_url,
|
174
|
+
change_email_request(param, user_ip, gitkit_token),
|
175
|
+
param['action'])
|
176
|
+
return email_change_response(oob_link, param)
|
177
|
+
end
|
178
|
+
rescue GitkitClientError => error
|
179
|
+
return failure_msg(error.message)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
failure_msg('unknown request type')
|
183
|
+
end
|
184
|
+
|
185
|
+
def password_reset_request(param, user_ip)
|
186
|
+
{
|
187
|
+
'email' => param['email'],
|
188
|
+
'userIp' => user_ip,
|
189
|
+
'challenge' => param['challenge'],
|
190
|
+
'captchaResp' => param['response'],
|
191
|
+
'requestType' => 'PASSWORD_RESET'
|
192
|
+
}
|
193
|
+
end
|
194
|
+
|
195
|
+
def change_email_request(param, user_ip, gitkit_token)
|
196
|
+
{
|
197
|
+
'email' => param['oldEmail'],
|
198
|
+
'newEmail' => param['newEmail'],
|
199
|
+
'userIp' => user_ip,
|
200
|
+
'idToken' => gitkit_token,
|
201
|
+
'requestType' => 'NEW_EMAIL_ACCEPT'
|
202
|
+
}
|
203
|
+
end
|
204
|
+
|
205
|
+
def build_oob_link(full_url, param, mode)
|
206
|
+
code = @rpc_helper.get_oob_code(param)
|
207
|
+
if code
|
208
|
+
oob_link = Addressable::URI.parse full_url
|
209
|
+
oob_link.path = @widget_url
|
210
|
+
oob_link.query_values = { 'mode' => mode, 'oobCode' => code}
|
211
|
+
return oob_link.to_s
|
212
|
+
end
|
213
|
+
nil
|
214
|
+
end
|
215
|
+
|
216
|
+
def failure_msg(msg)
|
217
|
+
{:response_body => {'error' => msg}}.to_json
|
218
|
+
end
|
219
|
+
|
220
|
+
def email_change_response(oob_link, param)
|
221
|
+
{
|
222
|
+
:oldEmail => param['email'],
|
223
|
+
:newEmail => param['newEmail'],
|
224
|
+
:oobLink => oob_link,
|
225
|
+
:action => :CHANGE_EMAIL,
|
226
|
+
:response_body => {'success' => true}.to_json
|
227
|
+
}
|
228
|
+
end
|
229
|
+
|
230
|
+
def password_reset_response(oob_link, param)
|
231
|
+
{
|
232
|
+
:email => param['email'],
|
233
|
+
:oobLink => oob_link,
|
234
|
+
:action => :RESET_PASSWORD,
|
235
|
+
:response_body => {'success' => true}.to_json
|
236
|
+
}
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
class GitkitUser
|
241
|
+
attr_accessor :email, :user_id, :name, :photo_url, :provider_id,
|
242
|
+
:email_verified, :password_hash, :salt, :password, :provider_info
|
243
|
+
|
244
|
+
def self.parse_from_api_response(api_response)
|
245
|
+
user = self.new
|
246
|
+
user.email = api_response.fetch('email', nil)
|
247
|
+
user.user_id = api_response.fetch('user_id',
|
248
|
+
api_response.fetch('localId', nil))
|
249
|
+
user.name = api_response.fetch('displayName', nil)
|
250
|
+
user.photo_url = api_response.fetch('photoUrl', nil)
|
251
|
+
user.provider_id = api_response.fetch('provider_id',
|
252
|
+
api_response.fetch('providerId', nil))
|
253
|
+
user.email_verified = api_response.fetch('emailVerified',
|
254
|
+
api_response.fetch('verified', nil))
|
255
|
+
user.password_hash = api_response.fetch('passwordHash', nil)
|
256
|
+
user.salt = api_response.fetch('salt', nil)
|
257
|
+
user.password = api_response.fetch('password', nil)
|
258
|
+
user.provider_info = api_response.fetch('providerUserInfo', {})
|
259
|
+
user
|
260
|
+
end
|
261
|
+
|
262
|
+
# Convert to gitkit api request (a dict)
|
263
|
+
def to_request
|
264
|
+
request = {}
|
265
|
+
request['email'] = @email if @email
|
266
|
+
request['localId'] = @user_id if @user_id
|
267
|
+
request['displayName'] = @name if @name
|
268
|
+
request['photoUrl'] = @photo_url if @photo_url
|
269
|
+
request['emailVerified'] = @email_verified if @email_verified != nil
|
270
|
+
request['passwordHash'] =
|
271
|
+
JWT.base64url_encode @password_hash if @password_hash
|
272
|
+
request['salt'] = JWT.base64url_encode @salt if @salt
|
273
|
+
request['providerUserInfo'] = @provider_info if @provider_info != nil
|
274
|
+
request
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
class GitkitClientError < StandardError
|
279
|
+
def initialize(message)
|
280
|
+
super
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
class GitkitServerError < StandardError
|
285
|
+
def initialize(message)
|
286
|
+
super
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
data/lib/rpc_helper.rb
ADDED
@@ -0,0 +1,209 @@
|
|
1
|
+
# Copyright 2014 Google Inc. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require 'jwt'
|
16
|
+
require 'json'
|
17
|
+
require 'faraday'
|
18
|
+
require 'gitkit_client'
|
19
|
+
require 'openssl'
|
20
|
+
|
21
|
+
module GitkitLib
|
22
|
+
class RpcHelper
|
23
|
+
attr_accessor :access_token, :token_issued_at, :token_duration
|
24
|
+
|
25
|
+
TOKEN_ENDPOINT = 'https://accounts.google.com/o/oauth2/token'
|
26
|
+
GITKIT_SCOPE = 'https://www.googleapis.com/auth/identitytoolkit'
|
27
|
+
GITKIT_API_URL =
|
28
|
+
'https://www.googleapis.com/identitytoolkit/v3/relyingparty/'
|
29
|
+
|
30
|
+
def initialize(service_account_email, service_account_key, server_api_key,
|
31
|
+
google_token_endpoint = TOKEN_ENDPOINT)
|
32
|
+
@service_account_email = service_account_email
|
33
|
+
@google_api_url = google_token_endpoint
|
34
|
+
@connection = Faraday::Connection.new
|
35
|
+
@service_account_key =
|
36
|
+
OpenSSL::PKCS12.new(service_account_key, 'notasecret').key
|
37
|
+
@server_api_key = server_api_key
|
38
|
+
@token_duration = 3600
|
39
|
+
@token_issued_at = 0
|
40
|
+
@access_token = nil
|
41
|
+
end
|
42
|
+
|
43
|
+
# GetAccountInfo by email
|
44
|
+
#
|
45
|
+
# @api private
|
46
|
+
# @param [String] email account email to be queried
|
47
|
+
# @return [JSON] account info
|
48
|
+
def get_user_by_email(email)
|
49
|
+
invoke_gitkit_api('getAccountInfo', {'email' => [email]})
|
50
|
+
end
|
51
|
+
|
52
|
+
# GetAccountInfo by id
|
53
|
+
#
|
54
|
+
# @api private
|
55
|
+
# @param [String] id account id to be queried
|
56
|
+
# @return [JSON] account info
|
57
|
+
def get_user_by_id(id)
|
58
|
+
invoke_gitkit_api('getAccountInfo', {'localId' => [id]})
|
59
|
+
end
|
60
|
+
|
61
|
+
# Get out-of-band code for ResetPassword/ChangeEmail etc. operation
|
62
|
+
#
|
63
|
+
# @api private
|
64
|
+
# @param [Hash<String, String>] request the oob request
|
65
|
+
# @return <String> the oob code
|
66
|
+
def get_oob_code(request)
|
67
|
+
response = invoke_gitkit_api('getOobConfirmationCode', request)
|
68
|
+
response.fetch('oobCode', nil)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Download all accounts
|
72
|
+
#
|
73
|
+
# @api private
|
74
|
+
# @param [String] next_page_token pagination token for next page
|
75
|
+
# @param [Fixnum] max_results pagination size
|
76
|
+
# @return [Array<JSON>] user account info
|
77
|
+
def download_account(next_page_token, max_results)
|
78
|
+
param = {}
|
79
|
+
if next_page_token
|
80
|
+
param['nextPageToken'] = next_page_token
|
81
|
+
end
|
82
|
+
if max_results
|
83
|
+
param['maxResults'] = max_results
|
84
|
+
end
|
85
|
+
response = invoke_gitkit_api('downloadAccount', param)
|
86
|
+
return response.fetch('nextPageToken', nil), response.fetch('users', {})
|
87
|
+
end
|
88
|
+
|
89
|
+
# Delete an account
|
90
|
+
#
|
91
|
+
# @api private
|
92
|
+
# @param <String> local_id user id to be deleted
|
93
|
+
def delete_account(local_id)
|
94
|
+
invoke_gitkit_api('deleteAccount', {'localId' => local_id})
|
95
|
+
end
|
96
|
+
|
97
|
+
# Upload batch accounts
|
98
|
+
#
|
99
|
+
# @api private
|
100
|
+
# @param <String> hash_algorithm hash algorithm
|
101
|
+
# @param <String> hash_key hash key
|
102
|
+
# @param <Array<GitkitUser>> accounts account to be uploaded
|
103
|
+
def upload_account(hash_algorithm, hash_key, accounts)
|
104
|
+
param = {
|
105
|
+
'hashAlgorithm' => hash_algorithm,
|
106
|
+
'signerKey' => hash_key,
|
107
|
+
'users' => accounts
|
108
|
+
}
|
109
|
+
invoke_gitkit_api('uploadAccount', param)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Creates a signed jwt assertion
|
113
|
+
#
|
114
|
+
# @api private
|
115
|
+
# @return [String] jwt assertion
|
116
|
+
def sign_assertion
|
117
|
+
now = Time.new
|
118
|
+
assertion = {
|
119
|
+
'iss' => @service_account_email,
|
120
|
+
'scope' => GITKIT_SCOPE,
|
121
|
+
'aud' => @google_api_url,
|
122
|
+
'exp' => (now + @token_duration).to_i,
|
123
|
+
'iat' => now.to_i
|
124
|
+
}
|
125
|
+
JWT.encode(assertion, @service_account_key, 'RS256')
|
126
|
+
end
|
127
|
+
|
128
|
+
# Get an access token, from Google server if cached one is expired
|
129
|
+
#
|
130
|
+
# @api private
|
131
|
+
def fetch_access_token
|
132
|
+
if is_token_expired
|
133
|
+
assertion = sign_assertion
|
134
|
+
post_body = {
|
135
|
+
'assertion' => assertion,
|
136
|
+
'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer'}
|
137
|
+
headers = {'Content-type' => 'application/x-www-form-urlencoded'}
|
138
|
+
response = @connection.post(RpcHelper::TOKEN_ENDPOINT, post_body,
|
139
|
+
headers)
|
140
|
+
@access_token = JSON.parse(response.env[:body])['access_token']
|
141
|
+
@token_issued_at = Time.new.to_i
|
142
|
+
end
|
143
|
+
@access_token
|
144
|
+
end
|
145
|
+
|
146
|
+
# Check whether the cached access token is expired
|
147
|
+
#
|
148
|
+
# @api private
|
149
|
+
# @return <Boolean> whether the access token is expired
|
150
|
+
def is_token_expired
|
151
|
+
@access_token == nil ||
|
152
|
+
Time.new.to_i > @token_issued_at + @token_duration - 30
|
153
|
+
end
|
154
|
+
|
155
|
+
# Invoke Gitkit API, with optional access token for service account
|
156
|
+
# operations
|
157
|
+
#
|
158
|
+
# @api private
|
159
|
+
# @param [String] method Gitkit API method name
|
160
|
+
# @param [Hash<String, String>] params api request params
|
161
|
+
# @param [bool] need_service_account whether the request needs to be
|
162
|
+
# authenticated
|
163
|
+
# @return <JSON> the Gitkit api response
|
164
|
+
def invoke_gitkit_api(method, params, need_service_account=true)
|
165
|
+
post_body = JSON.generate(params)
|
166
|
+
headers = {'Content-type' => 'application/json'}
|
167
|
+
if need_service_account
|
168
|
+
@connection.authorization :Bearer, fetch_access_token
|
169
|
+
end
|
170
|
+
response = @connection.post(GITKIT_API_URL + method, post_body, headers)
|
171
|
+
check_gitkit_error JSON.parse(response.env[:body])
|
172
|
+
end
|
173
|
+
|
174
|
+
# Download the Gitkit public certs
|
175
|
+
#
|
176
|
+
# @api private
|
177
|
+
# @return <JSON> the public certs
|
178
|
+
def get_gitkit_certs
|
179
|
+
if @server_api_key.nil?
|
180
|
+
@connection.authorization :Bearer, fetch_access_token
|
181
|
+
response = @connection.get(GITKIT_API_URL + 'publicKeys')
|
182
|
+
else
|
183
|
+
response = @connection.get [GITKIT_API_URL, 'publicKeys?key=',
|
184
|
+
@server_api_key].join
|
185
|
+
end
|
186
|
+
MultiJson.load response.body
|
187
|
+
end
|
188
|
+
|
189
|
+
# Checks the Gitkit response
|
190
|
+
#
|
191
|
+
# @api private
|
192
|
+
# @param [JSON] response the response received
|
193
|
+
# @return [JSON] the response if no error
|
194
|
+
def check_gitkit_error(response)
|
195
|
+
if response.has_key? 'error'
|
196
|
+
error = response['error']
|
197
|
+
if error.has_key? 'code'
|
198
|
+
code = error['code']
|
199
|
+
raise GitkitClientError, error['message'] if code.to_s.match(/^4/)
|
200
|
+
raise GitkitServerError, error['message']
|
201
|
+
else
|
202
|
+
raise GitkitServerError, 'null error code from Gitkit server'
|
203
|
+
end
|
204
|
+
else
|
205
|
+
response
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: identity-toolkit-ruby-client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jin Liu
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-09-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: addressable
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.3.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.3.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faraday
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.9.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.9.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: multi_json
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.0.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.0.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: jwt
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.0.0
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.0.0
|
69
|
+
description: Google Identity Toolkit Ruby client library
|
70
|
+
email:
|
71
|
+
executables: []
|
72
|
+
extensions: []
|
73
|
+
extra_rdoc_files:
|
74
|
+
- README.rdoc
|
75
|
+
files:
|
76
|
+
- README.rdoc
|
77
|
+
- lib/gitkit_client.rb
|
78
|
+
- lib/rpc_helper.rb
|
79
|
+
homepage: https://developers.google.com/identity-toolkit/v3
|
80
|
+
licenses:
|
81
|
+
- Apache 2.0
|
82
|
+
metadata: {}
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options: []
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
requirements: []
|
98
|
+
rubyforge_project:
|
99
|
+
rubygems_version: 2.2.2
|
100
|
+
signing_key:
|
101
|
+
specification_version: 4
|
102
|
+
summary: Google Identity Toolkit Ruby client
|
103
|
+
test_files: []
|