What is a client key and how to generate one? - java

I'm trying to send an https request to a server using Java. The URL to which I'm connecting needs the clientkey.
The URL is: "https://www.zipcodeapi.com/rest/"+clientKey+"/info.json/" + zipcode + "/radians";
How would I get the client key?

I think so you need to register on this website to generate a client key , basically these keys are like an access token to the web services you want to consume.
You can register but as the website says "free account allows up to 50 API requests per hour. Complete this form to get an API key to start using the API"
https://www.zipcodeapi.com/Register

Related

Cannot make requests to Walmart API

I'm trying to make a request to the Walmart API here.
https://walmart.io/docs/affiliate/product-lookup
Here are the steps I'm following.
I create my application here on Walmart and uploaded my public key. I created my keys following these instructions on Mac.
https://walmart.io/key-tutorial
I followed this code to generate my signature.
https://walmart.io/docs/affiliate/onboarding-guide
I plug in all these values into the API explorer, but I keep getting the same error.
Is there an extra step I'm missing?
The 401 Unauthorized is an HTTP status code error that represents the request sent by the client to the server lacks valid authentication
Seems like one of the mandatory header params is missing while consuming api.
Request to please kindly cross check whether all of the mandatory header params are there as part of request.
We should have these below mentioned mandatory header params as part of the request.
One or more header params might be missing in the req.
WM_CONSUMER.ID
WM_SEC.KEY_VERSION
WM_CONSUMER.INTIMESTAMP
WM_SEC.AUTH_SIGNATURE
we need all of the header params and we can generate using below mentioned links.
Generating Auth Signature (WM_CONSUMER.INTIMESTAMP, WM_SEC.AUTH_SIGNATURE)
We can generate Auth Signature by using below mentioned link.
We will have to run below mentioned sample code to generate Auth Signature as seen below. This is going to generate timestamp and valid Auth Signature to consume APIs.
Time Stamp will be valid for couple of mins only. If it expires, we will have to regenerate the same
https://www.walmart.io/docs/affiliate/onboarding-guide
Generating consumer ID (WM_CONSUMER_ID)
Request to please kindly follow below steps to generate consumer ID
Create an account on Walmart IO platform - https://walmart.io by clicking on the user icon just before the search box.
Login to the account and accept "Terms of Use"
Click on "Create Your Application" to create a new application and fill in appropriate details.
Use this tutorial to generate two sets of public/private keys - https://walmart.io/key-tutorial
One set will be used for production.
Other set will be used for stage.
Upload both public keys using - https://walmart.io/key-upload?app_name=<your app name>
Consumer ID will be generated for both sets for prod and stage which can be seen on the dashboard - https://walmart.io/dashboard.
Regards,
Firdos
IOSupport

How to protect partner credentials in the api call from the end user browser

Team,
I have an requirement like i have to support to my partner (third party) portal to call us directly by making api call with credentials from their browser.
e.g.) Partner portal browser makes AJAX Call with below:
URL ---> https://example.com/request
HEADER ---> user_id : foo
HEADER ---> password : mypasswd
payload ---> {
"request_time" : 2232876435,
"request_name" : "get_user_info",
...
...
}
And their browser/portal is accessible/used by untrusted users of theirs. So now problem is since the call is from the front end; end user easily can inspect the browser to see the network api calls along with credential we have given to our partner to authorise at our side.
So i am planning to give suggestion to partner by asking them to encrypt the payload and headers in their portal backend server and render the encrypted information in the portal like below.
Encrypt (payload) using mypasswd.
Encrypt (password) using request_time <NOW OPTIONAL TO PASS>
So now,
e.g.) URL ---> https://example.com/request
HEADER ---> user_name : foo
HEADER ---> password : ENCRYPTED<mypasswd> <-- OPTIONAL
payload ---> ENCRYPTED<
{
"request_time" : 2232876435,
"request_name" : "get_user_info",
...
...
}
>
So in our system we will decrypt payload with mypasswd retrieved for user_id foo. so if decryption is successful, then the request is from valid resource.
Now the end portal user cannot understand the request from browser inspection.
NOTES:
I can't suggest my partner to call from their backend.
From the request payload i can identify repeated same request through unique transaction id, so they can't resubmit the same request. Hence avoiding replay attack.
Questions:
Q1) Any flaw or suggestion on this solution?
Q2) Is it possible to identify the decryption using passphrase is success or not in java? I am new to encryption, so could you please share any code or link to achieve this?
yours thoughts much valuable to me.
TLDR:
References:
Basic encryption details
https://blog.storagecraft.com/5-common-encryption-algorithms/
https://www.veracode.com/blog/research/encryption-and-decryption-java-cryptography
https://gooroo.io/GoorooTHINK/Article/13023/The-difference-between-encryption-hashing-and-salting/2085#.W2L_KdgzZD0
Java Encryption
How to encrypt and decrypt String with my passphrase in Java (Pc not mobile platform)?
Java Security: Illegal key size or default parameters?
Identifying decryption is successful through this exception:
Given final block not properly padded
EDIT: I misunderstood the question. If the information is encrypted by the third party before it reaches the end-user then this approach is generally safe. Replay attacks are the main thing to look out for. If the request being made is idempotent then you don't really need to worry, but otherwise you might need to implement a short-lived database for used tokens along with an expiry time or something similar.
You are solving this problem the wrong way. Having the end user make this request to you on behalf of the third party is silly - if the request comes from their browser then by definition they control the information they are sending and the way it is sent. Encryption does nothing to solve this since the encryption logic is also client side.
The solution to this problem is to eliminate the end-user. The request should come directly from the third party to you. This might be from the end-user making a request to the third party API or it might not - it doesn't matter.

Accessing Google Sheets API via Service Account Key

I am working on Google Sheets <-> Salesforce integration and developing it in Salesforce programming language - Apex on Force.com platform.
Currently I am attempting to connect to Google Sheets API. I am using Service Account Key, so Salesforce can pull the data from Google Sheets without the requirement for manual authorisation every time it sends out a query.
I am at the point where I set up the Service Account Key and I am successfully sending a request to it to obtain the access_code.
Then I am attempting to query the API, using the following class:
/****** API CALLOUT *******/
public static HttpResponse googleSheetsCallout (){
//the below line provides a string containing access token to google
string accessCode = getAccessToken();
//I found this endpoint structure online, this may be why my script
//isn't working. However, I am struggling to find the alternative.
string endpoint = 'https://sheets.googleapis.com/v4/spreadsheets/params=[SPREADSHEET ID GOES HERE]/values/[RANGE GOES HERE]?access_token=';
httpRequest req = new httpRequest();
req.setEndpoint(endpoint+accessCode);
req.setMethod('GET');
req.setTimeout(120000);
httpResponse res = new http().send(req);
System.debug ('res is ' +res);
return res;
}
When I run the function this is what the log returns:
|CALLOUT_RESPONSE|[71]|System.HttpResponse[Status=Forbidden, StatusCode=403]
|USER_DEBUG|[72]|DEBUG|res is System.HttpResponse[Status=Forbidden, StatusCode=403]
I enabled Google Sheets access in the google developer console menu, and what's interesting is when loking at the console it appears that Google notices API requests being sent out (they are appearing on the activity chart).
I solved it, and the issue was not the code itself.
The problem was sharing my sheet. To allow read/edit access to your sheet from the service account it must be shared with the Service Account ID email address, the same way it's shared with any other user. If this isn't done the script will produce 403 error.

Android/ASP RESTful API authentication without SSL/HTTPS

A common SO question, but no specific solid answers.
My setup:
I have a website running on Classic ASP with backed DB. Unfortunately, no SSL Certs are available
I have an Android application that will send a Google Volley to request data from the site using a bespoke but simple API
Currently:
I am still in testing, privately, so currently I just access the site as such:
On the app, the user enters a UserId and Password once.
User navigates to a Fragment which is associated with a specific ASP Page which will return some data
A Volley is sent to /mysite.com/_api/apage.asp?m=md5hashhereabcdefghijk
The server searches user records for a matching hash (built on UserID+SALT+pass). On matching record, it uses the found userid as the User's ID
apage.asp does some sql queries and returns a JSON object
app receives this JSON response and parses.
The problem:
Anyone packet sniffing, or MITM, would be able to plainly see the URLs being accessed (and server responses) and be able to replicate the query via their browser. This is what I'm trying to stop. Any SALTs or secret keys in the app would be easily seen by decompiling the APK.
Issues:
I've read all sorts of different solutions, but none of which really fit my environment. I can't use ASP session variables (RESTful being stateless), I cant use HTTPS(SSL/TLS) as there are no Certs on the Server. I can't use an App-based password as this can be decompiled and easily seen.
I appreciate that you will never get something 100% secure, but can only make people disinterested in hacking a system, or not make it worth while.
Proposed solution:
I want some feedback/thoughts on the following proposed method:
Each request will have its own handshake to authenticate the app
This will go as such:
User opens app for the first time and enters UserID/Password. This will remain with the app until it is uninstalled (or logged out), but I intend to keep the user's app logged in
User navigates in the app to a Fragment that corresponds with a specific page on the server
Volley is sent with :
UserAgent HTTP header 'some value'
generate the same authentication hash for (userid+salt+pass)
encrypt this hash with a public key
one query string /apage.asp?q=abcdefghijk.... sent to server
server decrypts using its private key
server checks this hash as I do currently.
page returns plaintext JSON values (not encrypted)
The same problem happens here whereby a MITM or sniffer could replicate the URL and get the same information back
A Second Proposed Solution:
Would it be better with every request actually starting with a whole handshake?
App sends volley to server requesting a handshake (HELO)
Server gross error check with UserAgent HTTP Header
Server logs the timestamp and IP of the request and generates a unique random code
App receives this code and builds a new hash using that unique code as a Salt
App sends second volley to /apage.asp?m=MD5(UserID+UniqueCode+Password)
Server Gross error check with originating IP, timestamp+-tolerance (30 seconds between the two requests?), UserAgent Request Header.
APage.asp uses this hash to authenticate the request, providing previous steps have successfully passed.
APage.asp returns a JSON object, as requested.
Server flags the log of originating IP/timestamp as EXPIRED, or, just remove the record.
This initial step would make it a lot harder for a sniffer or MITM to replicate the URL calls, as A) Each request would have a randomly returned code B) each code/hash combo can only be used once.
The only thing I can think of is someone decompiles the App, and sees the method of handshake, so could try to replicate this. However, the username/password hash would never match as that is the only thing they cannot get from the hash (as it is salted with the random code)
Thoughts? Could it be improved with some RSA public/private key cryptography? Could I generate my querystring apage.asp?m=abcdeghi..., Generate an MD5 Hash of that, append onto the end, then encrypt before sending?
Many thanks in advance

Magento customer authentication via API

I am using Magento with a 3rd party Java Web Application.
My application is "connected" to Magento via Magento SOAP API V2.
How can I perform a Customer Authentication from my Java aplication (outside of Magento) via api?
Any help would be appreciated.
I came up to a solution on how to login a customer via SOAP API and I will post it here so it can be helpful for others.Here is what I did to make it work:
I created a custom module in Magento with a custom method that login a customer and retuns the sessionID that is set on server side.
Mage::app()->setCurrentStore($website);
// Init a Magento session. This is super ultra important
Mage::getSingleton('core/session');
// $customer Mage_Customer_Model_Customer
// We get an instance of the customer model for the actual website
$customer = Mage::getModel('customer/customer')
->setWebsiteId(Mage::app()->getStore()->getWebsiteId());
// Load the client with the appropriate email
$customer->loadByEmail($email);
// Get a customer session
$session = Mage::getSingleton('customer/session');
$session->loginById($customer->getId());
if ($session->isLoggedIn()) {
return $session->getSessionId();
} else {
return null;
}
I created a Magento Custom Api so I can call my login method via SOAP.
Call the login method from my JAVA app, get the sessionId, then set the cookies on the browser, based on received sessionId.
http://yourmagentohost/setCookies.php?sessionId=your_session_id
And inside setCookies.php you have: setcookie("frontend", $_GET["sessionId"] , time()+3600);
That's it, now you have a logged in customer.
How can I perform a Customer Authentication from my Java aplication
(outside of Magento) via api? SOAP API V2
Clarification:
API Users (at least Soap) and Customer's are two user types. If you have a pre-existing userlist, and are looking to find out if they exist as user's inside of Magento, you may retrieve email account's and their related attributes and corresponding password hash's (CE: md5:salt , or CE/EE: sha:salt) all via SOAP. If you are looking to do comparative operations, you will need to implement the same Hashing against your password's to do 1:1 comparisons. If you are looking to have your Application use SOAP to directly perform operations, I would make sure that there is a layer of abstraction, as your app could be used nefariously targeting other user id's all depending on the SOAP Role and ACL set in Magento's Admin.
Moving on...
V2: You'll have to swap to Java, ex: PHP.
$username 'yourUsername';
$password = 'yourApiKeyPlainText';
$proxy = new SoapClient('https://www.yourdomain.com/magento/api/v2_soap?wsdl=1');
$sessionId = $proxy->login($username, $password);
//Get a Full customer List from Magento
$customerList = $proxy->customerCustomerList($sessionId);
//get back a list
//Target a user from your List, Compare Details against your App
$customerInfo = $proxy->customerCustomerInfo($sessionId, '2'); //Customer Id
Remote operations, like Checkout, can be rather involved. The question remains, what do you wish to do next to, or on behalf of the user with your app?
References:
http://www.magentocommerce.com/api/soap/customer/customer.list.html
http://www.magentocommerce.com/api/soap/customer/customer.info.html
Cheers,
Your code example does not use SOAP. Magento SOAP accesses actually look like the following:
$client = new SoapClient('http://magentohost/soap/api/?wsdl');
// If somestuff requires api authentification,
// then get a session token
$session = $client->login('apiUser', 'apiKey');
Have a look at the API documentation: http://www.magentocommerce.com/api/soap/introduction.html

Categories