Live Paypal Application fails to create token information from auth code but not in sandbox - node.js

In my Meteor web application I have managed to successfully implement some functions that allow me to take an authorization code granted from Paypal's authorizeUrl function via the RESTful Paypal Node SDK in the Sandbox in order to assign a refresh token to an existing user. However, now that we need to deploy it to a Live environment, we are running into problems because the Paypal API is complaining with the following error:
Error: Response Status: 400
This means the request was bad, due perhaps to a 'bad syntax.' However, I am using the correct live API credentials and the authorization URL endpoint is the correct one at https://www.paypal.com/signin/authorize
Unfortunately this bug doesn't occur when I am reverting back to my sandbox mode configuration.
As a follow up, trying to pass an invalid authorization code to my sandbox configuration endpoint provides me the appropriate error message 400 with Invalid authorization code whereas the live environment gives me no such help...
The latest paypal-debug-id I have on hand is 83d570f17357e
EDIT:
It turns out Paypal thinks client id or secret is null even though I have clearly provided the configuration with client_id, client_secret, openid_client_id and openid_client_secret. This confuses me even more
EDIT 2:
Using the same Live API credentials I can successfully set up a basic payment flow using the Rest SDK, but I cannot use open ID connect with the same client ID and secret. Maybe that has something to do with it?

After some extensive testing and wrestling with the API it was discovered that there was actually a configuration conflict going on when binding the Meteor.wrapAsync API call to an instance of paypal created from the node SDK.
Assuming my Meteor.wrapAsync call is this:
var wrapGetUserInfo = Meteor.wrapAsync(openIdCxn.userinfo.get.bind(openIdCxn.userinfo), function (err, userinfo) {
if (err) {
console.log(err);
throw new Meteor.Error(500, "Internal Server Error", err);
}
});
Then instead of doing
var userInfo = wrapGetUserInfo(returnObject.access_token, paypal);
I will do
var userInfo = wrapGetUserInfo(returnObject.access_token);
And then it no longer complains

Related

msal-node error trying to resolve endpoints

I have been using MSAL in my React app for some time with success. One of the tokens that my app requests is for scope 'https://management.core.windows.net/user_impersonation'. I have a nodeJS server that I want to push that token acquisition to so I installed msal-node (1.12.1) and tried using the OBO flow:
const pca = new msal.ConfidentialClientApplication({
auth: {
clientId: settings.config.azure.clientId,
clientSecret: settings.config.azure.clientSecret,
authority: "https://login.microsoftonline.com/<tenantid>",
knownAuthorities: ["https://login.microsoftonline.com/<tenantid>"],
}
});
const request = {
scopes: ['https://management.core.windows.net//user_impersonation'],
oboAssertion: <token_extracted_from_auth_header>
}
const response = await pca.acquireTokenOnBehalfOf(request);
return response.accessToken;
However the above code results in the following error:
ClientAuthError: endpoints_resolution_error: Error: could not resolve endpoints. Please check network and try again. Detail: ClientAuthError: openid_config_error: Could not retrieve endpoints. Check your authority and verify the .well-known/openid-configuration endpoint returns the required endpoints. Attempted to retrieve endpoints from: https://login.microsoftonline.com/tenantid/v2.0/.well-known/openid-configuration
If I visit the URL it complains about I do get back some metadata so not really sure why it is failing.
Anybody have a suggestion?
Also in regards to OBO flow:
For my nodeJS app I have added that permission to the required API list
I presume the oboAssertion field is the token that is passed to my nodeJS app by the client? I simply extracted it from the Auth header
The actual error message there means that the URL that we are trying to contact is wrong. And it is wrong https://login.microsoftonline.com/tenantid/v2.0/.well-known/openid-configuration returns an error.
A coorrect one is: https://login.microsoftonline.com/19d5f71f-6c9a-4e7f-b629-2b0c38f2b167/v2.0/.well-known/openid-configuration
Notice how I used an actual teanant_id there. You can get yours from the Azure Portal - it's the "directory id"
If your web api is single tenant, i.e. it is only meant for the people in 1 organization, then the is the tenant id of that organization. It is also known as "directory id". You get it from the Azure Portal.
However, if your api is multi-tenant, i.e. it's a bit more complicated, and the "correct" answer is to use the tenant id of the incoming assertion. It's the tid claim in it.

The SSL connection could not be established, see inner exception. - DocuSign EnvelopesApi calls ONLY to PROD environment

I have migrating our Apis to use Docusign OAuth authentication flow. While testing I found that the code works perfectly fine when I point to Docusign Demo environment. However when I point to docusign Prod environment I get the following error.
The SSL connection could not be established, see inner exception.
There inner exception is actually null.
The docusign Auth call is fine and we get the accountId as expected. However the EnvelopesApi calls are failing. I do have a ticket open with Docusign but wanted to see if any one can help.
Our Api is deployed as a Windows Service and is in dotnet core 5.0. However I have tested this by deploying the Api to an IIS website with ssl binding and I can repro the same exception.
Auth Flow - OAuth JwtFlow
API BasePath as - "https : //docusign.net/restapi" (space added on purpose)
OAuth Base Path as - "account.docusign.com"
Below code get the accountId and sets the AccessToken. This is successful.
var privateKeyBytes = Encoding.UTF8.GetBytes(docuSignKey);
try
{
_tokenInfo = apiClient.RequestJWTUserToken(docusignConfig.IntegratorKey, docusignConfig.UserIdGuid,
docusignConfig.OAuthBasePath, privateKeyBytes, docusignConfig.TokenExpiryInHours);
var userInfo = apiClient.GetUserInfo(_tokenInfo?.access_token);
var account = userInfo?.Accounts
.FirstOrDefault(la => la.IsDefault.ToLowerInvariant() == true.ToString().ToLowerInvariant())
?? userInfo?.Accounts.First();
SetApiClientConfiguration(docusignConfig);
return account?.AccountId;
}
catch (Exception ex)
{
ESignLogger.Error($"{GetType().Name}.{nameof(AuthorizeAndGetAccountId)}. Error in getting account details. " + ex.Message);
return null;
}
Below code is the envelopesApi call which fails.
var recipientResponse = await _envelopesApi.ListRecipientsAsync(accountId, envelopeId);
The URLs for eSignature REST API calls for the DocuSign production environments can be different for different customers based on where their account is provisioned.
The default URL (https://www.docusign.net/restapi) can be used in some cases.
However, the best practice is to call the User Info endpoint for the particular user (it's by account, but a user can be a member of more than one account) and for each account that user is a member of, you'll get back a baseURI that can be different than the default I just posted above.
If this wasn't your issue, it may also be that you need to download one of the certificates to your server. You can find all of DocuSign SSL certificates in this page.
Steps to check:
OAuth step to obtain an access_token. You're using the JWT grant flow. If it returns an access token from account.docusign.com then you've succeeded. Note that your client ID (integration key) needs to pass go-live before it can be used with account.docusign.com
Next use the access token with the right base url for the eSig API. You can determine the right base url by using the /oauth/userinfo API. Or if your application is just for your own company, you can just look up your DocuSign account's base URL from the API & Keys page of the eSignature Settings (admin) tool.

Given the new Spotify web api authentication credentials, is it possible to run the api without a server?

I'm trying to run the spotify web api using node-spotify-api npm package. In order to require the package I have to use something called browserify, which allows me to specifically use the "require()" function in the browser. I'm strictly trying to run the api on the client side. When I do, this is the error I get -
// I have my client ID and client secret ID delcared in variables
// Code below is suppose to execute the search function once the user enters a track
var query = $("#query").val().trim();
console.log(query)
spotify.search({ type: 'track', query: query }, function(err, data)
{
if (err) {
return console.log('Error occurred: ' + err);
}
console.log(data);
});
// Once executed, I get the error below
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'null' is therefore not allowed access. If an opaque
response serves your needs, set the request's mode to 'no-cors' to
fetch the resource with CORS disabled.
bundle.js:120 Error occurred: RequestError: TypeError: Failed to fetch
I looked up the error and everything I'm looking at redirects me in the direction of running the api on the server side which I do not want to do if possible. Any thoughts on how to strictly run this client-side?
I think you are describing the auth flow called Client Credentials, and no, this is not possible because Spotify refuses to allow CORS on their auth token endpoint. See this issue on GitHub.
You will need to use the Implicit Grant flow to utilize the API entirely within the browser.

Nodejs - ADAL package issue

I am using adal-node package in my Nodejs app for authenticating against Azure AD.
URL: https://www.npmjs.org/package/adal-node
I am using acquireTokenWithAuthorizationCode method to get the token and it works fine.
When my auth code expires, I want to refresh my token using the below.
authenticationContext.acquireTokenWithRefreshToken(_tokenData.refreshToken, authdata.clientId, authdata.resource, callback).
But when I run this code, its giving me the below error.
"Get Token request returned http error: 400 and server response: {"error":"invalid_request","error_description":"AADSTS90014: The request body must contain the following parameter: 'client_secret or client_assertion'
The method will not accept client secret as its argument, but still it complains that it needs a client secret.
Can you please help?
Thanks
Anil
Unfortunately, the library does not support your scenario right now. The function acquireTokenWithRefreshToken that you are using was intended for OAuth public clients that don't require a client secret, but your app is an OAuth confidential client which does.
I have filed the following issue in the GitHub repo to track the need to add a new method that would support your scenario.
https://github.com/AzureAD/azure-activedirectory-library-for-nodejs/issues/22

Azure Error: Client side authentication flow with Google is not supported

I suddenly started to receive the following error in my app. I'm sure it has been running fine before - atleast on my machine :-)
Error: Client side authentication flow with Google is not supported.
I get this error when I try to login using a accesstoken I've received from a gapi authorize call:
// login with google using gapi
gapi.auth.authorize({ client_id: clientId, scope: scopes, immediate: noPopup },
function (authResult) {
// Pass the accesstoken into azure
client.login("google", {"access_token": authResult.access_token}).then(
function(user) {
// logged into azure...
Then I receive the error about not supported flow.
(if I change from "google" to "facebook", the error is: Error: The Facebook Graph API access token authorization request failed with HTTP status code 400 - which makes sence since it's a google accesstoken I'm passing in)
If I paste in the url directly in a browser https://kjokken.azure-mobile.net/login/google, then everything seems to be ok.
Any ideas why this is happening?
Thanks for any help
Larsi
Thank you for using Mobile Services and taking the time to report this. We actively working on adding support for this particular scenario over the next couple of weeks, which explains what you are seeing. I will update this post when we have more information.
In the interim, did you consider using MobileServiceClient.login(MobileServiceAuthenticationProvider provider, UserAuthenticationCallback callback)?
Thanks,
-Yavor

Resources