identity-toolkit-ruby-client 0.1.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.
- 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: []
|