lib/nubank_sdk/auth.rb in nubank_sdk-0.5.0 vs lib/nubank_sdk/auth.rb in nubank_sdk-0.5.1
- old
+ new
@@ -1,23 +1,38 @@
-# frozen_string_literal: true
-
module NubankSdk
class Auth
attr_reader :refresh_token, :refresh_before, :access_token
+ #
+ # Auth method to connect with the nubank api
+ #
+ # @param [String] cpf the cpf to authenticate
+ # @param [String] device_id the device id to authenticate
+ # @param [NubankSdk::ApiRoutes] api_routes the api routes to connect
+ # @param [[Symbol, Faraday::Adapter::Test::Stubs]] adapter the adapter to connect
def initialize(cpf:, device_id: nil, api_routes: nil, connection_adapter: nil)
@cpf = cpf
@device_id = device_id || generate_device_id
@api_routes = api_routes || NubankSdk::ApiRoutes.new
@connection_adapter = connection_adapter
end
+ #
+ # Return the instance of user certificate
+ #
+ # @return [NubankSdk::Certificate] the certificate instance
def certificate
@certificate ||= NubankSdk::Certificate.new(@cpf)
end
+ #
+ # Authenticate with the nubank api to get a new access token
+ #
+ # @param [String] password the password to authenticate
+ #
+ # @return [NubankSdk::ApiRoutes] the api routes with the new links
def authenticate_with_certificate(password)
token_url = @api_routes.entrypoint(path: :app, entrypoint: :token)
response = ssl_connection.post(token_url, token_payload(password))
response_hash = Client.get_body(response)
@@ -27,19 +42,29 @@
@access_token = response_hash[:access_token]
update_api_routes(response_hash[:_links])
end
+ #
+ # Request to nubank api to generate a new certificate
+ #
+ # @param [String] password the password to authenticate
+ #
+ # @return [String] email was has been received the code
def request_email_code(password)
response = default_connection.post(@gen_certificate_path, payload(password))
response_parsed = parse_authenticate_headers(response.headers['WWW-Authenticate'])
@encrypted_code = response_parsed[:device_authorization_encrypted_code]
response_parsed[:sent_to]
end
+ #
+ # Verify communication with the nubank api
+ #
+ # @return [File] the certificate file
def exchange_certs(email_code, password)
response = default_connection.post(@gen_certificate_path, payload(password).merge({
code: email_code,
'encrypted-code': @encrypted_code
})
@@ -49,10 +74,16 @@
certificate.process_decoded(key, response_data[:certificate])
end
private
+ # @!visibility private
+ # parse the headers of the authenticate response
+ #
+ # @param [String] header_content the headers to parse
+ #
+ # @return [Hash] the parsed header
def parse_authenticate_headers(header_content)
chunks = header_content.split(',')
parsed = {}
chunks.each do |chunk|
@@ -63,34 +94,56 @@
end
parsed
end
+ # @!visibility private
+ # Create a payload to generate a new certificate
+ #
+ # @param [String] password the password to authenticate
+ #
+ # @return [Hash] the payload to generate a new certificate
def payload(password)
{
login: @cpf,
password: password,
public_key: key.public_key.to_pem,
device_id: @device_id,
model: "NubankSdk Client (#@device_id)",
}
end
+ # @!visibility private
+ # Create a payload to authenticate with the nubank api
+ #
+ # @param [String] password the password to authenticate
+ #
+ # @return [Hash] the payload to authenticate
def token_payload(password)
{
'grant_type': 'password',
'client_id': 'legacy_client_id',
'client_secret': 'legacy_client_secret',
'login': @cpf,
'password': password
}
end
+ # @!visibility private
+ # Generates a new key for the certificate communication
+ #
+ # @return [OpenSSL::PKey::RSA] a new key
def generate_key
OpenSSL::PKey::RSA.new 2048
end
+ # @!visibility private
+ # Add the new links to the api routes
+ #
+ # @param [Hash] links the new links to add
+ #
+ # @return [NubankSdk::ApiRoutes] the api routes with the new links
def update_api_routes(links)
feed_url_keys = ['events', 'magnitude']
bills_url_keys = ['bills_summary']
customer_url_keys = ['customer']
account_url_keys = ['account']
@@ -98,42 +151,70 @@
@api_routes.add_entrypoint(path: :ssl, entrypoint: :query, url: links[:ghostflame][:href])
@api_routes.add_entrypoint(path: :ssl, entrypoint: :feed, url: find_url(feed_url_keys, links))
@api_routes.add_entrypoint(path: :ssl, entrypoint: :bills, url: find_url(bills_url_keys, links))
@api_routes.add_entrypoint(path: :ssl, entrypoint: :customer, url: find_url(customer_url_keys, links))
@api_routes.add_entrypoint(path: :ssl, entrypoint: :account, url: find_url(account_url_keys, links))
+ @api_routes
end
+ # @!visibility private
+ # Return the url of the first key found in the links
+ #
+ # @param [Array] keys the keys to search in the links
+ # @param [Hash] list of the links to search in
+ #
+ # @return [String] the url of the first key found
def find_url(keys, list)
links_keys = list.keys
keys.each do |url_key|
return list[url_key]['href'] if links_keys.include?(url_key)
end
''
end
+ # @!visibility private
+ # Generates a new connection with certificate
+ #
+ # @return [Client::HTTPS] a new connection with certificate
def prepare_default_connection
uri, @gen_certificate_path = @api_routes.entrypoint(
path: :app,
entrypoint: :gen_certificate,
type: :splitted
)
Client::HTTP.new(uri, @connection_adapter)
end
+ # @!visibility private
+ # Create a new default connection to the nubank api
+ #
+ # @return [Client::HTTP] a new default connection
def default_connection
@default_connection ||= prepare_default_connection
end
+ # @!visibility private
+ # Create a new ssl connection to the nubank api
+ #
+ # @return [Client::HTTPS] a new ssl connection
def ssl_connection
@ssl_connection ||= Client::HTTPS.new(certificate.encoded, @connection_adapter)
end
+ # @!visibility private
+ # return the key of the certificate communication
+ #
+ # @return [OpenSSL::PKey::RSA] the key of the certificate
def key
@key ||= generate_key
end
+ # @!visibility private
+ # Generates a random device id
+ #
+ # @return [String] a random device id
def generate_device_id
SecureRandom.uuid.split('-').last
end
end
end