well-formed JWT but still getting merchant_error - android-pay

I'm trying to set up In-App Payments for a Chrome Packaged App. When I switch the SellerSecret and SellerIdentifier from the sandbox to my own I get an merchant_error when I call buy().
As far as I can tell, this error seems to indicate that the JWT is not well-formed (but the only difference is switching out the sample secret and identifier with my own).
I've used the JWT Decoder ( https://developers.google.com/wallet/digital/docs/jwtdecoder ) and it looks fine.
Here's the JWT
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIwMDQwNDkxNDU3OTM0MTYxMzI0MiIsImF1ZCI6Ikdvb2dsZSIsInR5cCI6Imdvb2dsZVwvcGF5bWVudHNcL2luYXBwXC9pdGVtXC92MSIsImV4cCI6MTM5MjkxNTg3NCwiaWF0IjoxMzkwMzIzODc0LCJyZXF1ZXN0Ijp7Im5hbWUiOiJEYW4ncyBQaWVjZSBvZiBDYWtlIiwiZGVzY3JpcHRpb24iOiJUZXN0IFB1cmNoYXNlIDEiLCJwcmljZSI6IjEwLjUwIiwiY3VycmVuY3lDb2RlIjoiVVNEIiwic2VsbGVyRGF0YSI6InVzZXJfaWQ6MTIyNDI0NSxvZmZlcl9jb2RlOjMwOTg1NzY5ODcsYWZmaWxpYXRlOmFrc2RmYm92dTlqIn19.SHwbbWiJMnyXxui-WbaDs3Z1_7mdn5lFWCJatmug1Rg
Can anyone help out?
Thanks!
-Daniel
UPDATE: I just generated a JWT using the ruby sample code here https://developers.google.com/wallet/digital/docs/tutorial and when using my sandbox secret and ID it's fine but when I use my own secret and seller id it fails. Here's generated JWT from Ruby:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIwMDQwNDkxNDU3OTM0MTYxMzI0MiIsImF1ZCI6Ikdvb2dsZSIsInR5cCI6Imdvb2dsZS9wYXltZW50cy9pbmFwcC9pdGVtL3YxIiwiZXhwIjoxMzkwMzUzOTU0LCJpYXQiOjEzOTAzNTAzNTQsInJlcXVlc3QiOnsibmFtZSI6IlBpZWNlIG9mIENha2UiLCJkZXNjcmlwdGlvbiI6IlZpcnR1YWwgY2hvY29sYXRlIGNha2UgdG8gZmlsbCB5b3VyIHZpcnR1YWwgdHVtbXkiLCJwcmljZSI6IjEwLjUwIiwiY3VycmVuY3lDb2RlIjoiVVNEIiwic2VsbGVyRGF0YSI6InVzZXJfaWQ6MTIyNDI0NSxvZmZlcl9jb2RlOjMwOTg1NzY5ODcsYWZmaWxpYXRlOmFrc2RmYm92dTlqIn19.6enjLDpM-fxg69-XtcllsyVXBqRNbdhhBzXSr7jmyCM
I still get a merchant_error when I call buy() with the above jwt.

When you switch to your "own" (assuming you meant production id/secret) are you also switching your calls to production buy()
<script src="https://wallet.google.com/inapp/lib/buy.js"></script>
Update:
Useful info referencing #Danprime's comment:
Chrome Apps -> Wallet for Digital Goods
For Apps, you must call buy() with an extra parameter called parameters. This parameter currently has one field, env, which specifies the environment in which to process a payment. You can set this field to either prod (production server that accepts real credit cards), or sandbox (test server that accepts test credit cards to simulate transactions). The default setting is sandbox.

Your type is doubly escaped google/payments/inapp/item/v1 also in the jwt, the issuer looks like it starts with 00.
Are you using PHP to generate it? There should be an option to convert the object to JSON without escaping strings.
Can you double check that it actually begins with 00?

Related

Curl Command throwing' invalid grant error' on Windows command line

I have generated the JWT Token for DocuSign through the https://jwt.io .The signature is verified.
Now to obtain the Access token I am using following Command in Curl,on Windows Command line tool.Rrefering the Document https://developers.docusign.com/esign-rest-api/guides/authentication/oauth2-jsonwebtoken.I am getting "invalid Grant".What is the problem with my request?I know my token is correct because the token verifies the signature.
curl --data "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=YOUR_JSON_WEB_TOKEN" --request POST https://account-d.docusign.com/oauth/token
invalid_grant is the the publicly facing version of several errors rolled together. If you've hit your limit of troubleshooting, I'd recommend opening a case with DocuSign Support, and provide your Demo Account ID, UserID, Integrator Key and the value of an x-DocuSign-TraceToken of a failing assertion. The plaintext version of your assertion would be helpful as well.
Here's a few things to check:
aud value - must be exactly account-d.docusign.com (for demo) or account.docusign.com for prod. Including https:// or any other value will fail.
sub value - must be an active userID (in GUID format) in the appropriate environment.
iss value - must be a valid client ID
Private Key used for signing - must be associated with the Client ID in the correct environment. If you're using a key generated in Production but the assertion is directed to account-d.docusign.com it will fail. In some cases it can take a few minutes for a newly generated keypair to be valid in the Account Server, so if you've just generated that key, wait a bit and try again.
Timestamps used - Your exp value must not have passed, and if you are using an nbf value, it must be in the past. Confirm your computer's clock is correctly configured - if it's dramatically off, your application could be generating invalid assertions because of that.
The pro-tip is to use a library to generate the JWT and convert it to an Access Token.
See the JWT examples for code examples in many languages. The examples use either a JWT method from a DocuSign SDK or a lower level JWT library.
C# .NET Core https://github.com/docusign/eg-01-csharp-jwt-core
C# .NET Framework https://github.com/docusign/eg-01-csharp-jwt-framework
PHP https://github.com/docusign/eg-01-php-jwt
Java https://github.com/docusign/eg-01-java-jwt
Node.js https://github.com/docusign/eg-01-node-jwt
Python. https://github.com/docusign/eg-01-python-jwt
Ruby https://github.com/docusign/eg-01-ruby-jwt
See the repositories’ Readme files for installation and configuration instructions.

Decode a JWT token automatically in Charles Proxy

I've been using Charles to debug the communication between a mobile app and an API.
We are now changing both the client (app) and the server to use JSON Web Tokens (JWT).
Is there a way to configure Charles so that the JWT is decoded when browsing the requests ?
Basically, the request (from mobile app to server) will consist of a single header (Authorization) containing the JWT, and when I click on that request in Charles, I'd like to see:
- the original token
- the decoded header
- the decoded payload
Looking at Charles' documentation, I found the following:
- Rewrite tool: could replace the token with the decoded data, but it doesn't seem like functions (base64decode) are supported, only plain text or and regexp replacement.
- Map Remote tool: seems like it could do the job, by calling a script on a server which takes in the original request as an argument, and returns the new request with the decoded data. The documentation describes a use for replacing specific sources (when browsing a website), so I'm having a hard time seeing how it could be applied to this case (client to API communication). Doesn't seem like it can pass the original request as an argument (just replaces it).
I know that I could always copy paste the token in a tool that decodes JWT, but that's a small step that I will be repeating a hundred/thousands of times, so I'd like to avoid it.
Or is there another way to debug HTTP requests between mobile and server that are encoded in JWT format ?
Since Charles Proxy doesn't support JWT Decode feature, you can try out Proxyman, which automatically decode JWT and display in a nice place.
If you need to manipulate it, you can take a look at JWT Decode Addon . The Scripting feature allows you to write JS code to achieve the same result.
Disclaimer: I'm a creator of Proxyman. Hope this answer could help you.

Error: The received token is of incorrect token type -- What should the token look like?

I recently registered to Microsoft Azure and set up a Cognitive Services Account. Using the instructions from the Text Translation API Documentation I was able to retrieve an authentication token from the /issueToken service using the interactive online example. However, if I want to use that token (for example for the interactive /translate example) I end up with the response
<html><body><h1>Argument Exception</h1><p>Method: Translate()</p><p>Parameter: </p><p>Message: The received token is of incorrect token type.</p><code></code><p>message id=0344.V2_Rest.Translate.3D8A6FF1</p></body></html>
What am I doing wrong? What should the token look like and in what format should I supply it? In the online example I specified the token by setting the appid field to "Bearer [token]" where [token] is the response from /issueToken.
In my case the token is a 687 characters long string which can be separated into three parts (using '.' as delimiter). The first two parts are base64-encoded and just contain some JSON-encoded information that stays constant (except the expiration date field). The third and last part changes everytime and can not be decoded using base64. Instead of supplying the full token I also tried to just use various substrings of the full token but without any success so far.
I also tried authenticating via curl using the Authentication-header instead of the appid-field, which also did not work for me.
The token actually has to look like it is described in the question text (at least as of now). The problem in my case was that I used the wrong subscription key. Note here: You get a different key for the translation API and the speech API each; even though both run under Cognitive Services and even if you connect both through the same resources.
I post this as an answer to my question because I want to confirm that all the steps listed above are correct and because I hope that it may help people who do the same mistake as I did.

What pattern for constructing and verifying an access token for a web application?

We have a web application which consists of two parts (among others): a 'shell' written in Java running in Jetty using Windows authentication through Waffle, which shows a 'component' written in ASP.NET running in IIS using Windows authentication. Both parts are served from the same host, but (of course) from different ports.
As it stands, a user first must sign in to the shell, and then when the component is loaded the user must sign in again. We want to get rid of that second sign-in step.
From what I've seen and read, e.g. about claims-based authentication and OAuth, the standard pattern for that is the following:
After signing in to the shell, the shell constructs a 'token' with the user's Windows account name, which it sends back to the browser.
The component does not use Windows authentication, but instead the browser sends it the token.
The component verifies that it trusts the token, and uses the identity from that token.
(In our case the simplest technique is to put the token in a cookie, since both shell and component run on the same server, and HTTP cookies are not port-specific, so the browser will automatically send the shell's token to the component.)
Now I see several ways to construct and verify the token, like:
(a) The token contains the Windows account name, encrypted with a symmetric key that is hardcoded into both shell and component, or generated and agreed at installation time or start-up time.
(b) The token contains the Windows account name, signed using a private key, and verified using the corresponding public key. This key pair is generated at installation time.
(c) The token contains a GUID, and the component's server side makes a call to the shell's server side to verify its validity and get the Windows account name.
I think I prefer (b), since (a) seems too 'hardcoded', and (c) is more likely to give scaling issues. Also, we already have a private/public key pair in place in the form of an SSL server certificate in the shell which is trusted by the component.
My main concern with (b) is that the token will contain an (X.509?) signature, which means the token could become fairly large. (Would it?) Also I'm not (yet) familiar with techniques to create a signature in Java, and verify it in .NET.
My question: What is the standard/recommended pattern to use here? What alternatives have I overlooked? Is there a standard protocol that we could use here?
You are on the right track.
Yes, the idea is to have the shell generate a token that cannot be forged (generated by anything/anyone but the shell) that can be verified by the component.
You are right that the token can become quite large. It will not become so large as to be unworkable (i.e. larger than a browser can handle), but it can become a performance issue.
In general, any component that accepts HTTP traffic with any kind of cached authentication is going to have a preferred format for that cached authentication. In your current implementation, after the user signs into the component (the second sign in step) the component will issue some kind of cookie containing identification credentials it will accept for subsequent requests. So the best thing would be for the shell to create exactly those credentials.
Failing that, it's quite reasonable for you to use your option (b) of creating a signed certification form the shell that the component can verify and then replace with its preferred form of authentication credential.

How to prevent a "replay" with Javascript SDK authResponse

I'm using the Javascript SDK to make a web page that is entirely static HTML and Javascript (i.e., it's not dynamically produced web markup via some web app). This web page occasionally uses Javascript to POST data to a server--data which should be tied to a particular Facebook user. I use FB.getLoginStatus to determine who the user is. This gives me authRepsonse JSON data which looks like this:
authResponse:
accessToken:"AAAC91..."
expiresIn: 3786
signedRequest:"Ws93YNGWQeOi..."
userID: "670..."
I can send the signedRequest to the server and decode it and validate it there (using my app's secret key), and then I know that the user is, in this case, "670...", so I can presumably safetly perform whatever operation is supposed to happen on the server. Here's the data I extract from the signed request:
{"algorithm"=>"HMAC-SHA256",
"code"=>
"2.AQAKT...|5hVFYWcu5a...",
"issued_at"=>1323403518,
"user_id"=>"670..."}
My question is, what prevents an adversary (who somehow got ahold of the encoded authResponse above) from just "replaying" the signedRequest data to my server at a much later time?
The "issued_at" param at first looked promising, but I don't have anything to compare that issued_at time to to see if I should accept this signedRequest or not. The "expiresIn" is another time related parameter, but it's not signed, so I can't trust it. Maybe "code" provides me with extra info, but I don't see how to decode that.
I expect I'm just thinking about this wrong, or using the API in a way I'm not supposed to. Any insights? Thanks.
First of all using an Message Authentication Code (MAC) is a fundamentally insecure approach to the problem of authentication. You should be storing this information as a server side state, so that this is never a threat. By using a cryptographic hash function as an HMAC you introduce the possibility of someone brute forcing your secret key. Cryptography should only be used when there is no other solution, instead you are using it to introduce a weakness. This is a gross misuse of cryptography.
That being said, you have an issued_at timestamp. Just take the current timestamp and subtract. make sure that value is greater than your session timeout.

Resources