intuit_ids_aggcat 0.0.5

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,396 @@
1
+ # forward classdefs for mapping
2
+ class DateTimeNode < XML::Mapping::SingleAttributeNode
3
+ def initialize(*args)
4
+ path,*args = super(*args)
5
+ @path = XML::XXPath.new(path)
6
+ args
7
+ end
8
+
9
+ def extract_attr_value(xml)
10
+ # without millisecs
11
+ r1 = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}-\d{2}:\d{2}/
12
+ # with millisecs
13
+ r2 = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}-\d{2}:\d{2}/
14
+ dt_format = ""
15
+ dt_string = default_when_xpath_err{ @path.first(xml).text }
16
+ if dt_string =~ r1
17
+ dt_format = "%Y-%m-%dT%H:%M:%S%z"
18
+ elsif dt_string =~ r2
19
+ dt_format = "%Y-%m-%dT%H:%M:%S.%L%z"
20
+ end
21
+ DateTime.strptime(dt_string, dt_format)
22
+ end
23
+
24
+ def set_attr_value(xml, value)
25
+ @path.first(xml,:ensure_created=>true).text = value
26
+ end
27
+ end
28
+
29
+ XML::Mapping.add_node_class DateTimeNode
30
+
31
+ module IntuitIdsAggcat
32
+ class Institution; end
33
+ class Address; end
34
+ class Key; end
35
+ class Credentials; end
36
+ class Credential; end
37
+ class Challenge; end
38
+ class ChallengeResponses; end
39
+ class Account; end
40
+ class BankingAccount < Account; end
41
+ class CreditAccount < Account; end
42
+ class Choice; end
43
+ class Transaction; end
44
+ class BankingTransaction < Transaction; end
45
+ class CreditCardTransaction < Transaction; end
46
+ class InvestmentBankingTransaction < Transaction; end
47
+ class InvestmentTransaction < Transaction; end
48
+ class LoanTransaction < Transaction; end
49
+ class RewardsTransaction < Transaction; end
50
+ class TransactionList; end
51
+ #class Common; end
52
+ class Context; end
53
+
54
+ class Institutions
55
+ include XML::Mapping
56
+ array_node :institutions, "institution", :class=>Institution, :default_value => []
57
+ end
58
+
59
+ class Institution
60
+ include XML::Mapping
61
+ numeric_node :id, "institutionId", :default_value => nil
62
+ text_node :name, "institutionName", :default_value => nil
63
+ text_node :url, "homeUrl", :default_value => nil
64
+ text_node :phone, "phoneNumber", :default_value => nil
65
+ boolean_node :virtual, "virtual", "true", "false", :default_value => true
66
+ end
67
+
68
+ class InstitutionDetail
69
+ include XML::Mapping
70
+ numeric_node :id, "institutionId", :default_value => nil
71
+ text_node :name, "institutionName", :default_value => nil
72
+ text_node :url, "homeUrl", :default_value => nil
73
+ text_node :phone, "phoneNumber", :default_value => nil
74
+ boolean_node :virtual, "virtual", "true", "false", :default_value => true
75
+ text_node :currency_code, "currencyCode", :default_value => nil
76
+ text_node :email_address, "emailAddress", :default_value => nil
77
+ text_node :special_text, "specialText", :default_value => nil
78
+ object_node :address, "address", :default_value => nil
79
+ array_node :keys, "keys/key", :class=>Key, :default_value => []
80
+ end
81
+
82
+ class Address
83
+ include XML::Mapping
84
+ text_node :address1, "address1", :default_value => nil
85
+ text_node :address2, "address2", :default_value => nil
86
+ text_node :address3, "address3", :default_value => nil
87
+ text_node :city, "city", :default_value => nil
88
+ text_node :state, "state", :default_value => nil
89
+ text_node :postal_code, "postalCode", :default_value => nil
90
+ text_node :country, "country", :default_value => nil
91
+ end
92
+
93
+ class Key
94
+ include XML::Mapping
95
+ text_node :name, "name", :default_value => nil
96
+ text_node :status, "status", :default_value => nil
97
+ text_node :min_length, "valueLengthMin", :default_value => nil
98
+ text_node :max_length, "valueLengthMax", :default_value => nil
99
+ boolean_node :is_displayed, "displayFlag", "true", "false", :default_value => true
100
+ boolean_node :is_masked, "mask", "true", "false", :default_value => false
101
+ text_node :display_order, "displayOrder", :default_value => nil
102
+ text_node :instructions, "instructions", :default_value => nil
103
+ text_node :description, "description", :default_value => nil
104
+ end
105
+
106
+ class InstitutionLogin
107
+ include XML::Mapping
108
+ # added namespaces to make root element compliant with Intuit's expectation
109
+ def post_save xml, options={:mapping=>:_default}
110
+ # using REXML's element namespace method doesn't seem to set the namespace correctly...?
111
+ xml.root.add_attributes("xmlns"=>"http://schema.intuit.com/platform/fdatafeed/institutionlogin/v1")
112
+ xml.root.add_namespace "xsi", "http://www.w3.org/2001/XMLSchema-instance"
113
+ xml.root.add_namespace "xsd", "http://www.w3.org/2001/XMLSchema"
114
+ # for challengeResponses/response
115
+ xml.each_element("//response") do |x|
116
+ x.add_namespace "v11", "http://schema.intuit.com/platform/fdatafeed/challenge/v1"
117
+ x.name = "v11:response"
118
+ end
119
+ # for challengeResponses root
120
+ xml.each_element("//challengeResponses") do |x|
121
+ x.add_namespace "v1", "http://schema.intuit.com/platform/fdatafeed/institutionlogin/v1"
122
+ x.name = "challengeResponses"
123
+ end
124
+ end
125
+
126
+ self.root_element_name "InstitutionLogin"
127
+ object_node :credentials, "credentials", :default_value => nil
128
+ object_node :challenge_responses, "challengeResponses", :default_value => nil
129
+ end
130
+
131
+ class Credentials
132
+ include XML::Mapping
133
+ array_node :credential, "credential", :default_value => nil
134
+ end
135
+
136
+ class Credential
137
+ include XML::Mapping
138
+ text_node :name, "name", :default_value => nil
139
+ text_node :value, "value", :default_value => nil
140
+ end
141
+
142
+ class Challenges
143
+ include XML::Mapping
144
+ array_node :challenge, "challenge", :class => Challenge, :default_value => nil
145
+ end
146
+
147
+ class Choice
148
+ include XML::Mapping
149
+ text_node :text, "text", :default_value => nil
150
+ text_node :val, "val", :default_value => nil
151
+ end
152
+
153
+ class Challenge
154
+ include XML::Mapping
155
+ text_node :text, "text", :default_value => nil
156
+ text_node :image, "image", :default_value => nil
157
+ array_node :choice, "choice", :class => Choice, :default_value => nil
158
+ end
159
+
160
+ class ChallengeResponses
161
+ include XML::Mapping
162
+ def post_save xml, options={:mapping=>:_default}
163
+ # using REXML's element na1espace method doesn't seem to set the namespace correctly...?
164
+ xml.root.add_namespace "v1", "http://schema.intuit.com/platform/fdatafeed/institutionlogin/v1"
165
+ xml.each_element("//response"){|x| x.add_namespace "v11", "http://schema.intuit.com/platform/fdatafeed/challenge/v1"}
166
+ xml
167
+ end
168
+ self.root_element_name "ChallengeResponses"
169
+ array_node :response, "response", :class => String
170
+ end
171
+
172
+ class AccountList
173
+ include XML::Mapping
174
+ array_node :banking_accounts, "BankingAccount", :class => BankingAccount, :default_value => nil
175
+ array_node :credit_accounts, "CreditAccount", :class => CreditAccount, :default_value => nil
176
+ #array_node :loan_accounts, "LoanAccount", :default_value => nil
177
+ #array_node :investment_accounts, "InvestmentAccount", :default_value => nil
178
+ #array_node :rewards_accounts, "RewardsAccount", :default_value => nil
179
+ #array_node :other_accounts, "OtherAccount", :default_value => nil
180
+ end
181
+
182
+ class Account
183
+ include XML::Mapping
184
+ numeric_node :account_id, "accountId", :default_value => nil
185
+ text_node :status, "status", :default_value => nil
186
+ text_node :account_number, "accountNumber", :default_value => nil
187
+ text_node :account_number_real, "accountNumberReal", :default_value => nil
188
+ text_node :account_nickname, "accountNickname", :default_value => nil
189
+ numeric_node :display_position, "displayPosition", :default_value => nil
190
+ numeric_node :institution_id, "institutionId", :default_value => nil
191
+ text_node :description, "description", :default_value => nil
192
+ text_node :registered_user_name, "registeredUserName", :default_value => nil
193
+ numeric_node :balance_amount, "balanceAmount", :default_value => nil
194
+ date_time_node :balance_date, "balanceDate", :default_value => nil
195
+ numeric_node :balance_previous_amount, "balancePreviousAmount", :default_value => nil
196
+ date_time_node :last_transaction_date, "lastTxnDate", :default_value => nil
197
+ date_time_node :aggregation_success_date, "aggrSuccessDate", :default_value => nil
198
+ date_time_node :aggregation_attempt_date, "aggrAttemptDate", :default_value => nil
199
+ text_node :currency_code, "currencyCode", :default_value => nil
200
+ text_node :bank_id, "bankId", :default_value => nil
201
+ numeric_node :institution_login_id, "institutionLongId", :default_value => nil
202
+ end
203
+
204
+ class BankingAccount < Account
205
+ include XML::Mapping
206
+ text_node :banking_account_type, "bankingAccountType", :default_value => nil
207
+ date_time_node :posted_date, "postedDate", :default_value => nil
208
+ numeric_node :available_balance_amount, "availableBalanceAmount", :default_value => nil
209
+ date_time_node :origination_date, "originationDate", :default_value => nil
210
+ date_time_node :open_date, "openDate", :default_value => nil
211
+ numeric_node :period_interest_rate, "periodInterestRate", :default_value => nil
212
+ numeric_node :period_deposit_amount, "periodDepositAmount", :default_value => nil
213
+ numeric_node :period_interest_amount, "periodInterestAmount", :default_value => nil
214
+ numeric_node :interest_amount_ytd, "interestAmountYtd", :default_value => nil
215
+ numeric_node :interest_prior_amount_ytd, "interestPriorAmountYtd", :default_value => nil
216
+ date_time_node :maturity_date, "maturityDate", :default_value => nil
217
+ numeric_node :maturity_amount, "maturityAmount", :default_value => nil
218
+ end
219
+
220
+ class CreditAccount < Account
221
+ include XML::Mapping
222
+ text_node :credit_account_type, "creditAccountType", :default_value => nil
223
+ text_node :detailed_description, "detailedDescription", :default_value => nil
224
+ numeric_node :interest_rate, "interestRate", :default_value => nil
225
+ numeric_node :credit_available_amount, "creditAvailableAmount", :default_value => nil
226
+ numeric_node :credit_max_amount, "creditMaxAmount", :default_value => nil
227
+ numeric_node :cash_advance_max_amount, "cashAdvanceMaxAmount", :default_value => nil
228
+ numeric_node :cash_advance_balance, "cashAdvanceBalance", :default_value => nil
229
+ numeric_node :cash_advance_interest_rate, "cashAdvanceInterestRate", :default_value => nil
230
+ numeric_node :current_balance, "currentBalance", :default_value => nil
231
+ numeric_node :payment_min_amount, "paymentMinAmount", :default_value => nil
232
+ date_time_node :payment_due_date, "paymentDueDate", :default_value => nil
233
+ numeric_node :previous_balance, "previousBalance", :default_value => nil
234
+ date_time_node :statement_end_date, "statementEndDate", :default_value => nil
235
+ numeric_node :statement_purchase_amount, "statementPurchaseAmount", :default_value => nil
236
+ numeric_node :statement_finance_amount, "statementFinanceAmount", :default_value => nil
237
+ numeric_node :past_due_amount, "pastDueAmount", :default_value => nil
238
+ numeric_node :last_payment_amount, "lastPaymentAmount", :default_value => nil
239
+ date_time_node :last_payment_date, "lastPaymentDate", :default_value => nil
240
+ numeric_node :statement_close_balance, "statementCloseBalance", :default_value => nil
241
+ numeric_node :statement_last_fee_amount, "statementLastFeeAmount", :default_value => nil
242
+ end
243
+
244
+ class Common
245
+ include XML::Mapping
246
+ text_node :normalized_payee_name, "normalizedPayeeName", :default_value => nil
247
+ end
248
+
249
+ class Context
250
+ include XML::Mapping
251
+ text_node :source, "source", :default_value => nil
252
+ text_node :category_name, "categoryName", :default_value => nil
253
+ end
254
+
255
+ class Categorization
256
+ include XML::Mapping
257
+ object_node :common, "common", :class => Common, :default_value => nil
258
+ object_node :context, "context", :class => Context, :default_value => nil
259
+ end
260
+
261
+ class Transaction
262
+ include XML::Mapping
263
+ numeric_node :id, "id", :default_value => nil
264
+ text_node :currency_type, "currencyType", :default_value => nil
265
+ text_node :institution_transaction_id, "institutionTransactionId", :default_value => nil
266
+ text_node :correct_institution_transaction_id, "correctInstitutionTransactionId", :default_value => nil
267
+ text_node :correct_action, "correctAction", :default_value => nil
268
+ text_node :server_transaction_id, "serverTransactionId", :default_value => nil
269
+ text_node :check_number, "checkNumber", :default_value => nil
270
+ text_node :ref_number, "refNumber", :default_value => nil
271
+ text_node :confirmation_number, "confirmationNumber", :default_value => nil
272
+ text_node :payee_id, "payeeId", :default_value => nil
273
+ text_node :payee_name, "payeeName", :default_value => nil
274
+ text_node :normalized_payee_name, "normalizedPayeeName", :default_value => nil
275
+ text_node :memo, "memo", :default_value => nil
276
+ text_node :category, "category", :default_value => nil
277
+ text_node :type, "type", :default_value => nil
278
+ text_node :value_type, "valueType", :default_value => nil
279
+ text_node :category_name, "categoryName", :default_value => nil
280
+ text_node :ofx_category_name, "ofxCategoryName", :default_value => nil
281
+ numeric_node :currency_rate, "currencyRate", :default_value => nil
282
+ boolean_node :original_currency, "originalCurrency", "true", "false", :default_value => nil
283
+ date_time_node :posted_date, "postedDate", :default_value => nil
284
+ date_time_node :user_date, "userDate", :default_value => nil
285
+ date_time_node :available_date, "availableDate", :default_value => nil
286
+ numeric_node :amount, "amount", :default_value => nil
287
+ numeric_node :running_balance_amount, "runningBalanceAmount", :default_value => nil
288
+ numeric_node :sic, "sic", :default_value => nil
289
+ boolean_node :pending, "pending", "true", "false", :default_value => nil
290
+ object_node :categorization, "categorization", :class => Categorization, :default_value => nil
291
+ end
292
+
293
+ class BankingTransaction < Transaction
294
+ include XML::Mapping
295
+ use_mapping :_default
296
+ end
297
+
298
+ class CreditCardTransaction < Transaction
299
+ include XML::Mapping
300
+ use_mapping :_default
301
+ end
302
+
303
+ class InvestmentBankingTransaction < Transaction
304
+ include XML::Mapping
305
+ text_node :banking_transaction_type, "bankingTransactionType", :default_value => nil
306
+ text_node :subaccount_fund_type, "subaccountFundType", :default_value => nil
307
+ text_node :banking_401k_source_type, "banking401KSourceType", :default_value => nil
308
+ end
309
+
310
+ class LoanTransaction < Transaction
311
+ include XML::Mapping
312
+ numeric_node :principal_amount, "principalAmount", :default_value => nil
313
+ numeric_node :interest_amount, "interestAmount", :default_value => nil
314
+ numeric_node :escrow_total_amount, "escrowTotalAmount", :default_value => nil
315
+ numeric_node :escrow_tax_amount, "escrowTaxAmount", :default_value => nil
316
+ numeric_node :escrow_insurance_amount, "escrowInsuranceAmount", :default_value => nil
317
+ numeric_node :escrow_pmi_amount, "escrowPmiAmount", :default_value => nil
318
+ numeric_node :escrow_fees_amount, "escrowFeesAmount", :default_value => nil
319
+ numeric_node :escrow_other_amount, "escrowOtherAmount", :default_value => nil
320
+ end
321
+
322
+ # TODO - map InvestmentTransaction
323
+ class InvestmentTransaction < Transaction
324
+ include XML::Mapping
325
+ text_node :reversal_institution_transaction_id, "reversalInstitutionTransactionId", :default_value => nil
326
+ text_node :description, "description", :default_value => nil
327
+ text_node :buy_type, "buyType", :default_value => nil
328
+ text_node :income_type, "incomeType", :default_value => nil
329
+ text_node :inv_401k_source, "inv401ksource", :default_value => nil
330
+ text_node :loan_id, "loadId", :default_value => nil
331
+ text_node :options_action_type, "optionsActionType", :default_value => nil
332
+ text_node :options_buy_type, "optionsBuyType", :default_value => nil
333
+ text_node :options_sell_type, "optionsSellType", :default_value => nil
334
+ text_node :position_type, "positionType", :default_value => nil
335
+ text_node :related_institution_trade_id, "relatedInstitutionTradeId", :default_value => nil
336
+ text_node :related_options_trans_type, "relatedOptionsTransType", :default_value => nil
337
+ text_node :secured_type, "securedType", :default_value => nil
338
+ text_node :sell_reason, "sellReason", :default_value => nil
339
+ text_node :sell_type, "sellType", :default_value => nil
340
+ text_node :subaccount_from_type, "subaccountFromType", :default_value => nil
341
+ text_node :subaccount_fund_type, "subaccountFundType", :default_value => nil
342
+ text_node :subaccount_security_type, "subaccountSecurityType", :default_value => nil
343
+ text_node :subaccount_to_type, "subaccountToType", :default_value => nil
344
+ text_node :transfer_action, "transferAction", :default_value => nil
345
+ text_node :unit_type, "unitType", :default_value => nil
346
+ text_node :cusip, "cusip", :default_value => nil
347
+ text_node :symbol, "symbol", :default_value => nil
348
+ text_node :unit_action, "unitAction", :default_value => nil
349
+ text_node :options_security, "optionsSecurity", :default_value => nil
350
+ date_time_node :trade_date, "tradeDate", :default_value => nil
351
+ date_time_node :settle_date, "settleDate", :default_value => nil
352
+ numeric_node :accrued_interest_amount, "accruedInterestAmount", :default_value => nil
353
+ numeric_node :average_cost_basis_amount, "averageCostBasisAmount", :default_value => nil
354
+ numeric_node :commission_amount, "commissionAmount", :default_value => nil
355
+ numeric_node :denominator, "denominator", :default_value => nil
356
+ date_time_node :payroll_date, "payrollDate", :default_value => nil
357
+ date_time_node :purchase_date, "purchaseDate", :default_value => nil
358
+ numeric_node :gain_amount, "gainAmount", :default_value => nil
359
+ numeric_node :fees_amount, "feesAmount", :default_value => nil
360
+ numeric_node :fractional_units_cash_amount, "fractionalUnitsCashAmount", :default_value => nil
361
+ numeric_node :load_amount, "loadAmount", :default_value => nil
362
+ numeric_node :loan_interest_amount, "loadInterestAmount", :default_value => nil
363
+ numeric_node :loan_principal_amount, "loanPrincipalAmount", :default_value => nil
364
+ numeric_node :markdown_amount, "markdownAmount", :default_value => nil
365
+ numeric_node :markup_amount, "markupAmount", :default_value => nil
366
+ numeric_node :new_units, "newUnits", :default_value => nil
367
+ numeric_node :numerator, "numerator", :default_value => nil
368
+ numeric_node :old_units, "oldUnits", :default_value => nil
369
+ numeric_node :penatly_amount, "penaltyAmount", :default_value => nil
370
+ boolean_node :prior_year_contribution, "priorYearContribution", :default_value => nil
371
+ numeric_node :shares_per_contract, "sharesPerContract", :default_value => nil
372
+ numeric_node :state_withholding, "stateWithholding", :default_value => nil
373
+ numeric_node :total_amount, "totalAmount", :default_value => nil
374
+ numeric_node :taxes_amount, "taxesAmount", :default_value => nil
375
+ boolean_node :tax_exmpty, "taxExmpty", :default_value => nil
376
+ numeric_node :unit_price, "unitPrice", :default_value => nil
377
+ numeric_node :units, "units", :default_value => nil
378
+ numeric_node :withholding_amount, "withholdingAmount", :default_value => nil
379
+ numeric_node :options_shares_per_contract, "optionsSharesPerContract", :default_value => nil
380
+ end
381
+
382
+ class RewardsTransaction < Transaction
383
+ include XML::Mapping
384
+ use_mapping :_default
385
+ end
386
+
387
+ class TransactionList
388
+ include XML::Mapping
389
+ array_node :banking_transactions, "BankingTransaction", :class => BankingTransaction, :default_value => nil
390
+ array_node :credit_card_transactions, "CreditCardTransaction", :class => CreditCardTransaction, :default_value => nil
391
+ array_node :investment_banking_transactions, "InvestmentBankingTransaction", :class => InvestmentBankingTransaction, :default_value => nil
392
+ array_node :loan_transactions, "LoanTransaction", :class => LoanTransaction, :default_value => nil
393
+ array_node :investment_transactions, "InvestmentTransaction", :class => InvestmentTransaction, :default_value => nil
394
+ array_node :rewards_transactions, "RewardsTransaction", :class => RewardsTransaction, :default_value => nil
395
+ end
396
+ end
@@ -0,0 +1,126 @@
1
+ require 'openssl'
2
+ require 'nokogiri'
3
+ require 'base64'
4
+ require 'securerandom'
5
+ require 'active_support'
6
+ require 'net/https'
7
+ require 'cgi'
8
+ require 'uri'
9
+
10
+ module IntuitIdsAggcat
11
+
12
+ module Client
13
+
14
+ class Saml
15
+ @token_timeout = 600
16
+ class << self
17
+
18
+ def get_saml_assertion_xml issuer_id, username = "default", private_key_path, private_key_string, private_key_password, instant
19
+ id = "_#{SecureRandom.uuid.gsub!(/-/, '')}"
20
+ time_format = "%Y-%m-%dT%T.%LZ"
21
+ before = instant - 5*60
22
+ after = instant + @token_timeout
23
+ saml_assertion_xml = <<-EOF_XML
24
+ <?xml version="1.0" encoding="UTF-8"?><saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="#{id}" IssueInstant="#{instant.utc.strftime(time_format)}" Version="2.0"><saml2:Issuer>#{issuer_id}</saml2:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><ds:Reference URI="##{id}"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>%%DIGEST%%</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>%%SIGNATURE%%</ds:SignatureValue></ds:Signature><saml2:Subject><saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">#{username}</saml2:NameID><saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"/></saml2:Subject><saml2:Conditions NotBefore="#{before.utc.strftime(time_format)}" NotOnOrAfter="#{after.utc.strftime(time_format)}"><saml2:AudienceRestriction><saml2:Audience>#{issuer_id}</saml2:Audience></saml2:AudienceRestriction></saml2:Conditions><saml2:AuthnStatement AuthnInstant="#{instant.utc.strftime(time_format)}" SessionIndex="#{id}"><saml2:AuthnContext><saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml2:AuthnContextClassRef></saml2:AuthnContext></saml2:AuthnStatement></saml2:Assertion>
25
+ EOF_XML
26
+ digestible_xml = get_digestible_xml(saml_assertion_xml)
27
+ digest = calc_digest(digestible_xml).strip
28
+ signed_info_xml = get_signed_info_xml(id, digest)
29
+ signature_value = get_signature_value(signed_info_xml, private_key_path, private_key_string, private_key_password)
30
+ saml_assertion_xml.gsub!(/%%DIGEST%%/, digest)
31
+ saml_assertion_xml.gsub!(/%%SIGNATURE%%/, signature_value)
32
+ return saml_assertion_xml
33
+
34
+ end
35
+
36
+ def get_signature_value(signed_info_xml, private_key_path, private_key_string, private_key_password)
37
+ if !private_key_path.nil?
38
+ pkey = OpenSSL::PKey::RSA.new(File.read(private_key_path), private_key_password)
39
+ else
40
+ pkey = OpenSSL::PKey::RSA.new(private_key_string, private_key_password)
41
+ end
42
+ signed_info_xml_canon = Nokogiri::XML(signed_info_xml).canonicalize
43
+ digest = OpenSSL::Digest::SHA1.new
44
+ signature = Base64.encode64 pkey.sign(digest, signed_info_xml_canon)
45
+ signature.gsub!(/\n/,'') #remove newline
46
+ return signature
47
+ end
48
+
49
+ def get_signed_info_xml(id, digest)
50
+ signed_info_xml = <<-EOF_XML
51
+ <ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><ds:Reference URI="##{id}"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>#{digest.strip}</ds:DigestValue></ds:Reference></ds:SignedInfo>
52
+ EOF_XML
53
+ signed_info_xml = signed_info_xml.strip
54
+ return signed_info_xml
55
+ end
56
+
57
+ def calc_digest(digestible_xml)
58
+ doc = Nokogiri::XML(digestible_xml)
59
+ doc_canonicalized = doc.canonicalize(mode=Nokogiri::XML::XML_C14N_1_1)
60
+ digest = OpenSSL::Digest::SHA1.new.digest(doc_canonicalized)
61
+ digest_b64 = Base64.encode64(digest)
62
+ return digest_b64
63
+ end
64
+
65
+ def get_digestible_xml(saml_assertion_xml)
66
+ doc = Nokogiri::XML(saml_assertion_xml)
67
+ doc.xpath('//ds:Signature', 'ds' => "http://www.w3.org/2000/09/xmldsig#" ).each do |node|
68
+ node.remove
69
+ end
70
+ new_xml = doc.root.to_s
71
+ doc = Nokogiri::XML(new_xml)
72
+ doc.xpath('//text()[not(normalize-space())]').remove
73
+ doc_canonical = doc.canonicalize(mode=Nokogiri::XML::XML_C14N_1_1)
74
+ return doc_canonical.to_s.strip
75
+ end
76
+
77
+ def send_saml_assertion(saml_assertion_b64, oauth_consumer_key, oauth_consumer_secret)
78
+
79
+ oauth_url="https://oauth.intuit.com/oauth/v1/get_access_token_by_saml"
80
+
81
+ uri = URI.parse(oauth_url)
82
+ if IntuitIdsAggcat.config.proxy.nil?
83
+ http = Net::HTTP.new(uri.host, uri.port)
84
+ else
85
+ proxy_uri = URI.parse(IntuitIdsAggcat.config.proxy)
86
+ http = Net::HTTP::Proxy(proxy_uri.host,proxy_uri.port).new(uri.host, uri.port)
87
+ end
88
+ request = Net::HTTP::Post.new(uri.request_uri)
89
+ request["Content-Type"] = "application/x-www-form-urlencoded"
90
+ request["Content-Language"] = "en-US"
91
+ request["Content-Length"] = saml_assertion_b64.length
92
+ request["Authorization"] = "OAuth oauth_consumer_key=\"#{oauth_consumer_key}\""
93
+ request["Host"] = "financialdatafeed.platform.intuit.com"
94
+ request.set_form_data({"saml_assertion"=>saml_assertion_b64})
95
+ http.use_ssl = true
96
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
97
+ #http.set_debug_output($stdout)
98
+ response = http.request(request)
99
+ params = CGI::parse(response.body)
100
+ return {oauth_token_secret: params["oauth_token_secret"][0],
101
+ oauth_token: params["oauth_token"][0] }
102
+
103
+ end
104
+ def get_oauth_info issuer_id, username, oauth_consumer_key, oauth_consumer_secret, private_key_path, private_key_string, private_key_password
105
+ instant = Time.now
106
+ saml_assertion_xml = get_saml_assertion_xml issuer_id, username, private_key_path, private_key_string, private_key_password, instant
107
+ saml_assertion_b64 = Base64.strict_encode64(saml_assertion_xml)
108
+ oauth_token_info = send_saml_assertion saml_assertion_b64, oauth_consumer_key, oauth_consumer_secret
109
+ oauth_token_info[:token_expiry] = instant + @token_timeout
110
+ oauth_token_info
111
+ end
112
+
113
+ def get_tokens username, issuer_id = IntuitIdsAggcat.config.issuer_id, oauth_consumer_key = IntuitIdsAggcat.config.oauth_consumer_key, oauth_consumer_secret = IntuitIdsAggcat.config.oauth_consumer_secret, certificate_path = IntuitIdsAggcat.config.certificate_path, certificate_string = IntuitIdsAggcat.config.certificate_string, certificate_password = IntuitIdsAggcat.config.certificate_password
114
+ #if !IntuitIdsAggcat.config.oauth_token_info.nil? && !IntuitIdsAggcat.config.oauth_token_info[:oauth_token].nil? && IntuitIdsAggcat.config.oauth_token_info[:token_expiry] > (Time.now + 2)
115
+ # IntuitIdsAggcat.config.oauth_token_info
116
+ #else
117
+ oauth_token_info = get_oauth_info issuer_id, username, oauth_consumer_key, oauth_consumer_secret, certificate_path, certificate_string, certificate_password
118
+ # IntuitIdsAggcat.config(:oauth_token_info => oauth_token_info)
119
+ # oauth_token_info
120
+ #end
121
+ end
122
+
123
+ end
124
+ end
125
+ end
126
+ end