Cannot make requests to Walmart API - java

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

Related

SAML implementation using OneLogin in ColdFusion throwing error

As part of learning how to integrate OneLogin SSO in my ColdFusion app I pulled this git repo -
https://github.com/GiancarloGomez/ColdFusion-OneLogin and set up locally. But, while sending the auth request to OneLogin we are getting an error message saying "We're sorry, but something went wrong.
We've been notified about this issue and we'll take a look at it shortly."
I could not find the root cause of this issue. Appreciate your timely help on this.
Configuration on OneLogin looks like below. Note that consumer URL I modified to http://127.0.0.1:8500/coldfusion-onelogin/consume.cfm instead of actual format mentioned (http://127.0.0.1:8500/coldfusion-onelogin/consume/) in the YouTube video provided in the readme file of this git repo. I had tried changing the consumer URL format as this http://127.0.0.1:8500/coldfusion-onelogin/consume/ but we are still getting the error message.
Access Tab in OneLogin looks like below,
Below is the code which sends auth request to OneLogin.
<cfscript>
try{
// used to encode string - chose to use Java version just in case CF did not encode correctly
// encodeForURL appears to work but to keep the same as the samples from OneLogin I will use the Java reference
urlEncoder = createObject("java","java.net.URLEncoder");
// the appSettings object contain application specific settings used by the SAML library
appSettings = createObject("java","com.onelogin.AppSettings");
// set the URL of the consume file for this app. The SAML Response will be posted to this URL
appSettings.setAssertionConsumerServiceUrl(request.company.getConsumeUrl());
// set the issuer of the authentication request. This would usually be the URL of the issuing web application
appSettings.setIssuer(request.company.getIssuerUrl());
// the accSettings object contains settings specific to the users account.
accSettings = createObject("java","com.onelogin.AccountSettings");
// The URL at the Identity Provider where to the authentication request should be sent
accSettings.setIdpSsoTargetUrl("https://app.onelogin.com/saml/signon/" & request.company.getIssuerID());
// Generate an AuthRequest and send it to the identity provider
authReq = createObject("java","com.onelogin.saml.AuthRequest").init(appSettings, accSettings);
// now send to one login
location ( accSettings.getIdp_sso_target_url() & "?SAMLRequest=" & authReq.getRidOfCRLF(urlEncoder.encode(authReq.getRequest(authReq.base64),"UTF-8")), false);
}
catch(Any e){
writeDump(e);
}
</cfscript>
Below is the format of auth request URL ,
https://app.onelogin.com/saml/signon/[issuerId]?SAMLRequest=[SamlRequest].
I am not providing the actual URL here since I am not sure whether someone can tamper it or not. But please do let us know if it is really required to solve this issue.
Below is the screenshot of the SAML Login Page , from here I am clicking on the button and send auth request to OneLogin.
Also, In the index.cfm , form action attribute is "/post/". Since it was throwing an error I had to replace it with "/coldfusion-onelogin/post.cfm". Here coldfusion-onelogin is a folder under wwwroot. Any settings in ColdFusion to be modified so that it will not throw any error if we keep the form action attribute as "/post/" ?.
Hmmm. The consumer URL validator is supposed to be a regex expression, and I'm not sure how it's going to handle a literal HTTP value (since it'll try to evaluate it as regex)
So try changing URL validator to be something dumb like *. (match everything)
That should hopefully clear the error until you can sort out what you want the validation to be in production.
You need to first logout from the OneLogin Admin Panel
https://app.onelogin.com/logout
To successfully test the demo app.

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.

"Parameter client_assertion_type is missing" in keycloak

I am trying out get the access token from the super user so that I can the same to create new users in key cloak, I have deployed keycloak in wildfly and when I try to do the get call, I am getting Invalid user credentials as response,
How to know the actual credentials?
And when I try to update the password from the console, I getting the error message like below.
Since I am new to this and din't find enough information from internet also, any kind of help will be appreciated .
Updated:
Now i am getting new error description as Parameter client_assertion_type is missing like below. What should be client_assertion_type here ?
This keycloak help page describes the most likely reason for the second error:
Q: When logging in, I get an error: *Parameter client_assertion_type is missing [invalid_client].
A: This error means your client is configured with Signed JWT token credentials, which means you have to use the --keystore parameter when logging in.
Alternatively you can disable using JWT tokens for the client in Keycloak.
For your information, the client_assertion_type would probably be urn:ietf:params:oauth:client-assertion-type:jwt-bearer. But then you'd get another error because the client_assertion is missing.
If ccp-portal is a confidential client using client authentication with signed JWT then the Keycloak doc states that
During authentication, the client generates a JWT token and signs it
with its private key and sends it to Keycloak in the particular
backchannel request (for example, code-to-token request) in the
client_assertion parameter.
I guess it's not possible to generate a JWT with PostMan.
This is meant for backchannel client-keycloak communication, not for
user authentication.
Solutions
You can use the admin-cli as client_id instead of your ccp-portal client. The admin-cli should be in the list of clients configured for your ccp realm. You can see that from the Keycloak interface.
Another option is allow direct access grants in ccp-portal client config.
Finally you could use ccp-portal client in your application configured with one of the Keycloak client adapters, instead of POSTMan.
As subrob sugrobych mentionned, parameters should be passed as form-data.
first of all, when you are posting data to keycloak over a rest client, you need to input parameters as form paramaters, and not as query parameters. This is why you are getting this strange error of not providing parameter grant_type, when you obviously are providing it. Same is valid for accessing keycloak api via code.
Next thing you need to think about are roles for your superuser. You can assign realm roles and client roles. There is a client named 'realm-management' which contains roles which would normally count as "system roles". You will need to use them. When you are getting HTTP code 403, it means, that probably your user is missing a role from this client.

Google Calendar V3 API Push notification via java client

I need subscribe for Google Calendar API v3 Push Notifications. I have checked documentation - it provides useful API details. I have checked java client library. It contains useful classes...
Trying:
com.google.api.services.calendar.Calendar calendar = initObject();
...
calendar.calendarList().get("myMail#ukr.net").execute();
As result I have CalendarListEntry map with my calendar info.
Trying use same calendarClient object:
calendar.calendarList().watch(channel).execute();
in result:
17:46:26,540 ERROR # c.n.c.c.g.GoogleCalendarClient.watchCalendarList com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized
It seems I have an authorization issue. I think I should not have one because of I can try one more time same client object and it returns correct result. Also I have considered case to use optional token field - no changes.
If someone needs my channel object:
17:58:38,022 INFO # {"address":"https://myPersonalVerifiedByGoogleAddr/google/calendars/","id":"4ac3e9e3-8428-405e-a8ed-6cf0e4fa25ff","payload":false,"type":"web_hook"}
address - my inet address verified by google
id - generated
payload - false (because of no content in my request)
type - web_hook (following google doc)
I have no ideas how to fix unauthorized in watch request, because of client is authorized (I would not be able to load calendar info).
You may want to try testing it by sending http request to validate if it is just an OAuth token issue. Next is to validate if you have done all the required steps to make a watch request. This would narrow down the possible reasons you encounter the issue.
Also check that in the docs it stated that "the Google Calendar API will be able to send notifications to this HTTPS address only if there is a valid SSL certificate installed on your web server."

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

Categories