google wallet subscription JWT 400 MERCHANT_ERROR - android-pay

When I generate and execute a non-subscription JWT in the Google developer sandbox, everything executes successfully. However, whenever I attempt to execute a subscription JWT, I encounter a 400 / Bad Request / MERCHANT_ERROR message.
I have copied & pasted each of the resulting signed & encoded JWT into Google's JWT Decoder - which reports that each of the JWTs are valid, but only the non-subscription JWT executes successfully.
I've tried everything that I can think of. Any help would be most appreciated. Thanks.
The non-subscription JWT that succeeds
{
"iss":"ourSellerIdentifier",
"aud":"Google",
"typ":"google/payments/inapp/item/v1",
"iat":1395879238,
"exp":1395879298,
"request":{
"name":"Professional Edition",
"sellerData":"10955.373715.2.1",
"price":"39.95",
"currencyCode":"USD"
}
}
The subscription JWT that generates an error
{
"iss":"ourSellerIdentifier",
"aud":"Google",
"typ":"google/payments/inapp/item/v1",
"iat":1395880013,
"exp":1395880073,
"request":{
"name":"Professional Edition",
"sellerData":"10955.373715.2.1",
"recurrence":{
"price":"39.95",
"currencyCode":"USD",
"frequency":"monthly"
}
}
}

The typ field should be google/payments/inapp/subscription/v1 for subscriptions - re: "subscription" (vs "item")
Hth....

Related

Error when getting token using BotFramework's OAuthPrompt and Azure Oauth 2 Generic Provider

I'm trying to add authentication to a bot for Microsoft Teams using the Azure Oauth 2 Generic Provider. It works the first time I sign in, but if I need to get the token again, bot framework raises an error.
The connection works fine when I test in Azure Portal
Azure Portal connection test
And the token is returned the first time I call OAuthPrompt and sign in, I'm able to get the user profile as expected:
OAuthPrompt token response
If I call OAuthPrompt a second time to get the token, I get the error DialogContextError: Error retrieving token: 3498ec40d9ccd8469840bd31f8b1a78c.
The code for the dialog:
this.addDialog(
new OAuthPrompt(OAUTH_PROMPT, {
connectionName,
text: "Please sign in",
title: "Sign in",
timeout: 300000,
showSignInLink: true
})
);
How I get the token:
private async getTokenStep(stepContext: WaterfallStepContext) {
return await stepContext.beginDialog(OAUTH_PROMPT);
}
Any Idea what I doing wrong?
If you are using the OAuthPrompt class provided by MS, the most obvious reason I can think of that it's generating an error retrieving the token is because your request is getting throttled. If you can find the HTTP Request in your debug it's most likely returning 400 Bad Request.
Why are you calling the OAuthPrompt the second time to generate a new token, when you already requested a token the first time? What you should actually be doing is saving the token you generated from the first request into a user state, and reusing the token until it expires. You can check if the token expires before prompting for a new token again.
Check this article for how to save user state.
https://learn.microsoft.com/en-us/azure/bot-service/bot-builder-howto-v4-state?view=azure-bot-service-4.0&tabs=csharp

Changing Firebase target with Chrome Extension results in auth/invalid-credential

I've previously setup and followed these steps, and got it to work:
https://firebaseopensource.com/projects/firebase/quickstart-js/auth/chromextension/readme/#license
But cloning this extension, but with a different Extension ID, different firebase instance and OAuth/key setup, I've tried to follow the steps at least 3 separate times, but every time it fails at the last step, the login (the consent screen works though)
Upload a fresh dummy extension (without key field in manifest.json) (But it is the exact same code as the working one)
Get the Chrome Extension ID, and the Public Key, no problem
Create OAuth Client ID with the Extension ID, configured consent screen, no problem, the screen shows up and I can click through
Add OAuth & Public Key to manifest.json
Make another OAuth Client ID? (I think this is a duplicate step, because which Client ID should I use? and afaik the whitelisting is optional)
Use chrome.identity to get OAuth token:
export function startAuth(interactive) {
// Request an OAuth token from the Chrome Identity API.
chrome.identity
.getAuthToken({ interactive: !!interactive }, (token) => {
if (chrome.runtime && !interactive) {
console.error('It was not possible to get a token programmatically.');
}
else if (token) {
// Authorize Firebase with the OAuth Access Token.
const credential = firebase.auth.GoogleAuthProvider
.credential(null, token);
firebase.auth()
.signInWithCredential(credential)
.catch((error) => {
// The OAuth token might have been invalidated. Lets' remove it from cache.
if (error.code === 'auth/invalid-credential') {
chrome.identity
.removeCachedAuthToken({ token }, () => {
startAuth(interactive);
});
}
});
}
else {
console.error('The OAuth Token was null');
}
});
}
Note: This code is working with another extensionID/OAuth/key, so the code itself can't be the problem.
There isn't much to change between them, it's really the ExtensionID, the OAuth client ID url, and the public key.
I've followed the steps 3 times, to no avail, every time I get the error auth/invalid-credential. I do get a token though, but that token won't authenticate. How to find out why this is?
It's trying to post to this address, and returning error 400:
POST: https://identitytoolkit.googleapis.com/v1/accounts:signInWithIdp?key=xxxxx
Error: INVALID_IDP_RESPONSE : Invalid Idp Response: access_token audience is not for this project
My conclusion
There must be something changed with how to set this up, even though it works with different credentials
The problem was that I didn't create the OAuth in the same project in google cloud console, as the firebase project...

Docusign - Auto Sending Email on form submit

Im working a Laravel Project where we need to get the form details and send them to users to get sign through docusign. I refereed the PHP SDK but not sure where to get the JWT TOKEN, since the normal authentication is asking for docusign credentials each time when submit, we planned to use JWT authentication, please correct me if their are any options apart for this. Reviewed the Rest API, they mentioning the JWT will expire in 1hr, so should we manually generate JWT every 1hr. Please let me know wat is the best approach for handling this.
with JWT, you only need consent once in a lifetime and then you can generate tokens whenever you need.
You can get started by cloning this repo and following instructions to see how DocuSign APIs work with JWT.
The relevant code for getting a JWT token using PHP is this:
public function login() {
self::$access_token = $this->configureJwtAuthorizationFlowByKey();
self::$expiresInTimestamp = time() + self::$expires_in;
if(is_null(self::$account)) {
self::$account = self::$apiClient->getUserInfo(self::$access_token->getAccessToken());
}
$redirectUrl = false;
if (isset($_SESSION['eg'])) {
$redirectUrl = $_SESSION['eg'];
}
self::authCallback($redirectUrl);
}
To gain consent, open a browser (only once needed) with this URL - https://account-d.docusign.com/oauth/auth?response_type=code&scope=signature%20impersonation&client_id=<YOUR_INT_KEY>&redirect_uri=<YOUR_REDIRECT_URI>

Docusign PARTNER_AUTHENTICATION_FAILED The specified Integrator Key was not found or is disabled

I have a web application that I am trying to integrate with Docusign. I am using the java docusign client. I started down the path to use OAuth2, but then found out the refresh token expires and from what I am reading the user would have to authenticate again (user interaction each time). Normally refresh does not expire but access token does. Am I reading that correctly?
I want the user to authenticate once and for the app to be able to use that token without having to ask the user for access again. So I started looking at JWT and am not finding the documentation I need.
Using the JWT I can get the user info for the account. But can't make the call for templates.
apiClient.configureJWTAuthorizationFlow(folder + "509.cert", folder
+ "509.ppk", "account-d.docusign.com", IntegratorKey, account, 3600 );
com.docusign.esign.client.auth.OAuth.UserInfo userInfo =
apiClient.getUserInfo(apiClient.getAccessToken());
// **** This prints fine *****
System.out.println("UserInfoxxx: " + userInfo);
// **** Verified the url is demo *****
apiClient.setBasePath(userInfo.getAccounts().get(0).getBaseUri() +
"/restapi");
com.docusign.esign.api.TemplatesApi api = new
com.docusign.esign.api.TemplatesApi(apiClient);
try {
com.docusign.esign.model.EnvelopeTemplateResults resp =
api.listTemplates(account);
for ( com.docusign.esign.model.EnvelopeTemplateResult template :
resp.getEnvelopeTemplates() )
{
out.println("X " + template.getDescription() + " " +
template.getName() );
}
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
https://demo.docusign.net/restapi
com.docusign.esign.client.ApiException: Error while requesting server,
received a non successful HTTP code 400 with response Body: '{
"errorCode": "PARTNER_AUTHENTICATION_FAILED",
"message": "The specified Integrator Key was not found or is disabled.
Invalid account specified for user."}'
at com.docusign.esign.client.ApiClient.invokeAPI(ApiClient.java:929)
at
com.docusign.esign.api.TemplatesApi.listTemplates(TemplatesApi.java:2471)
at
com.docusign.esign.api.TemplatesApi.listTemplates(TemplatesApi.java:2409)
I am using my integrator key (client id)
Any suggestions or advise?
[Update]
Yes I am here is my flow.
Send the user to
https://account-d.docusign.com/oauth/auth?response_type=code&scope=signature%20impersonation&client_id=" + IntegratorKey + "&redirect_uri=" + redirectUri + "&state=" + state;
On redirect
String code = request.getParameter("code");
com.docusign.esign.client.auth.OAuth.OAuthToken oAuthToken = apiClient.generateAccessToken(IntegratorKey, ClientSecret, code);
System.out.println("OAuthToken: " + oAuthToken.getAccessToken() );
com.docusign.esign.client.auth.OAuth.UserInfo userInfo = apiClient.getUserInfo(oAuthToken.getAccessToken());
String folder = com.n.util.Settings.getInstance().getRealPath("/") + "META-INF/cert/";
apiClient.configureJWTAuthorizationFlow(folder + "509.cert", folder + "509.ppk", "account-d.docusign.com", IntegratorKey, userInfo.getSub(), oAuthToken.getExpiresIn() );
I then store userInfo.getSub() and use that in the other requests.
I have tried the account id as well.
Re: I started down the path to use OAuth2, but then found out the refresh token expires and from what I am reading the user would have to authenticate again (user interaction each time).
Normally refresh does not expire but access token does.
Am I reading that correctly?
Not completely. Please use Authorization Code Grant as you originally planned.
Here's the scoop: if you ask for the extended scope (in addition to the signature scope) then the returned refresh token will be good for another 30 days every time your app uses the refresh operation.
Example:
Day 1: Human logs into DocuSign using Authorization Code Grant flow via your app. The scope request is signature%20extended Your app receives back from DocuSign an Access Token good for 8 hours and a Refresh Token is good for 30 days. Your app stores the refresh token in non-volatile storage.
Day 23: Human again wants to use your app with DocuSign. Your app uses the Refresh Token it stored to make a refresh token request to DocuSign. (No human interaction is needed.) Your app receives back an Access Token, good for 8 hours, and a new Refresh Token good for 30 days from now (until day 53). Your app stores (replaces) the Refresh Token in non-volatile storage.
Result As long as your app uses/refreshes the refresh token at least once every 30 days, it will forever have a DocuSign refresh token can be used to obtain an Access Token, with no human interaction needed.
Caveat A security issue initiated by the DocuSign customer or by DocuSign itself may cause the Refresh and/or Access token to be no longer valid, and thus require that the user manually authenticate to DocuSign. But this would be an unexpected event and would also affect Access Tokens obtained via the JWT Authentication flow.
Please reserve the JWT flow for the cases where it is required. The JWT flow enables your app to impersonate the user. This is a higher level of access and thus should not be used if there is a good alternative. If the user is present then Authorization Code Grant is the recommended authentication flow.
Re your problem with the JWT flow: Try out our new Java JWT example to see if it helps.

Azure delegated mail reading across office365 domain (nodejs)

Trying to read/write/update the emails of each user within the domain on office365. I'm using Azure Active Directory and an Azure app. I'm the account admin. I've turned on a whole load of permissions at this stage as not sure which ones are necessary.
I'm programming in Nodejs. So...
Authenticate my app, using OAuth, against Azure so that I can access my own application. <- WORKS.
Request admin rights against the account at this URL: https://login.microsoftonline.com/common/adminconsent?client_id='+clientID+'&redirect_uri'+uri where clientID and uri are replaced. This redirects me to authentication against Microsoft platform. You can see all the permissions I have requested (while debugging) here:
Once I accept the permissions it returns me to my app, where it requests a token from: https://login.windows.net/[my-app-tenant-id]/oauth2/token. That returns the access token. So far so good
After that, I then try and use this token to read a user of my organisations emails (for instance me, but there are a few users I have tried it with). It goes to: https://graph.microsoft.com/v1.0/[userEmailAddress#domain.com/messages. I pass the token as a bearer.
This is the problem, I get
{
"error": {
"code": "InvalidAuthenticationToken",
"message": "Access token validation failure.",
"innerError": {
"request-id": "[request-id]",
"date": "2017-03-21T17:31:24"
}
}
}
I have tried this with a couple of URLs, for instance the outlook API, with this url https://outlook.office.com/api/v2.0. I think however that is for simple OAuth and wouldn't work this way anyway.
If anyone can explain how to get the access token to be valid, would be great.
FYI, I am also, simultaneously testing out the npm library azure-graphapi and using:
var clientID = '[client id]'
var clientSecret = '[client secret]'
var tenant = '[tenant id]'
var graph = new GraphAPI(tenant, clientID, clientSecret);
graph.get('users/', function(err, user) {
resp.json({users: user});
})
I can get the list of users. So perhaps I am being stupid and somehow I can use this to read a users email?
Thanks
Maybe you have made a mistake in the request header to get access token.
As you can see, I got a token by sending a POST request to the https://login.microsoftonline.com/common/oauth2/v2.0/token endpoint and passed the value mail.read to the scope parameter in this request.
Now, I am able to get emails of the user with that token.

Resources