DocuSign API Can't download signed PDFs USER_LACKS_MEMBERSHIP Error - docusignapi

I am using the envelopes list status changes api and getting the error below. I am the only user on the account and a DS Admin. Also, we have used this code successfully with other DocuSign accounts.
Can you please help me resolve the issue?
Error:
ApiException: Error while requesting server, received a non successful HTTP code 400 with response
Body:
'{"errorCode":"USER_LACKS_MEMBERSHIP","message":"The UserID does not have a valid membership in this Account."}'
ApiClient apiClient = new ApiClient(basePath);
apiClient.setAccessToken(token, tokenExpirationSeconds);
EnvelopesApi envelopesApi = new EnvelopesApi(apiClient);
// prepare the request body
EnvelopesApi.ListStatusChangesOptions options = envelopesApi.new ListStatusChangesOptions();
LocalDate date = LocalDate.now().minusDays(30);
options.setFromDate(date.toString("yyyy/MM/dd"));
// call the API - ERROR HERE
EnvelopesInformation results = envelopesApi.listStatusChanges(accountId, options);

the userId you used for your JWT token must be an admin of the same exact account in DocuSign.
Any chance you use demo vs. production? two different accounts?
This error simply means your API calls is using a user that is not authorized to view this envelope because it lacks a membership to the account that this envelope is part of.

The most common cause of that error (after you've confirmed the account ID is correct) is hitting the wrong Base URL for the account. The first time you generate an authentication token for a particular user, you should make a UserInfo call and cache the BaseURL value.

Thanks! Ended up rebuilding credentials from scratch. I appreciate the insights.

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.

401 Error when sending data to Stripe `Customers` API

I want to create a new customer in Stripe upon form submit and add that customer's credit card to their account. As of now, I'm using the following code upon submit in my React App. The create customer call is then made separately from my server:
async submit(ev) {
let {token} = await this.props.stripe.createToken({name: "Name"});
let response = await fetch("https://api.stripe.com/v1/customers", {
method: "POST",
headers: {"Content-Type": "text/plain"},
body: token.id
});
When sending that data, I get a 401 error on the let response = ... line. I know that a 401 is an auth error, but my test API keys are definitely correct and don't have limits on how they can access my stripe account. Can anyone advise?
The issue here is that you are trying to create a Customer object client-side in raw Javascript. This API request requires your Secret API key. This means you can never do this client-side, otherwise anyone could find your API key and use it to make refunds or transfer for example.
Instead, you need to send the token to your own server. There, you will be able to create a Customer or a Charge using one of Stripe's official libraries instead of making the raw HTTP request yourself.
In my case, it's throwing the error due to a missing of stripe public key
var stripe = Stripe('{{ env("STRIPE_KEY") }}');
then I pass the public key as above, and it worked like a charm.

How to consume Graph API with a ADAL token?

in my Xamarin.forms project, I use ADAL (Microsoft.IdentityModel.Clients.ActiveDirectory) to authenticate on the Azure portal (Auth 1.0 endpoint). That part work great, but I need to get the security group of the user. So I use this code and passing the token received with ADAL:
HttpClient client = new HttpClient();
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Get, "https://graph.microsoft.com/v1.0/me/memberOf");
message.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", token);
HttpResponseMessage response = await client.SendAsync(message);
string responseString = await response.Content.ReadAsStringAsync();
I always got StatusCode: 401, ReasonPhrase: 'Unauthorized'.
In my azure AD app registration, I add the Graph API and these permissions:
I think I miss something. Any idea?
----- EDIT 1 ---
Here my payload. I changed it for a picture for lisibility. I don't know how to post json here
----- EDIT 2 ---
OH! I see. I think I need to understand more the Azure Login process. For now I follow an example of ADAL and Azure that let my log and use some function in my backend. So the login process use:
var authContext = new AuthenticationContext(authority); var authResult = await authContext.AcquireTokenAsync(resource, clientId, uri, platformParams);
Where authority = https://login.microsoftonline.com/mysite.com, ResourceID is my backend app ID and clientID is my native app ID. So Shawn is correct, I do not use the Graph.microsoft.com to get the token. Do we have another way to achieve all that? The need of using Graph is only to get the AD group the user has to adjust permission inside the app.
You are correct in your comment. If you add a new permission to your application, you must ask the user to re-consent to the app.
You can force re-consent through ADAL by setting the PromptBehavior to Always:
platformParams.PromptBehavior = PromptBehavior.Always
Or you can simply modify your Login URL to force it, by adding the query string:
&prompt=consent
In terms of building an app to help overcome this problem, if you think your app will be changing permissions after release, you can integrate logic which detects Unauthorized, and then sends the user to re-consent.
Another option is for your app to track changes which may require a new consent prompt, and detect when the user uses this new version of your application the first time, and asks them to consent.
In our new App Model V2, we support the concept of Incremental and Dynamic Consent, which should get rid of this problem all together for you.

Access the DocuSign API in your Force.com / Salesforce.com account in order to send an object with a single click of a button

DocuSignAPI for Salesforce.
Hello everybody, I'm following this manual to access the DocuSign API in Force.com / Salesforce.com account in order to send an object with a single click of a button to be isgned.
http://developer.force.com/cookbook/recipe/accessing-docusign-api-from-salesforcecom-to-send-contracts-for-esignatures
the problems is when i get the next error:
"The DocuSign EnvelopeId:Exception - System.CalloutException: Web service callout failed: WebService returned a SOAP Fault: The email address for the recipient is invalid. The recipient Id follows. faultcode=soap:Client faultactor=https://demo.docusign.net/api/3.0/dsapi.asmx"
Do anyone know the solution?
Thank you.
Re your specific error, I suggest that you download the API call logging information from DocuSign itself to see exactly what you sent to DocuSign via Salesforce.
In general for Salesforce/DocuSign integration, recommended first step is to use DocuSign for Salesforce, available from the Salesforce app store.
Additional developer information and source code is available from this blog post. It includes info on recipes (including source code) from DocuSign that document how to call the DocuSign API from Salesforce.
One issue to watch out for: you can't send PDFs from Salesforce to DocuSign due to callout limitations enforced by Salesforce.
Solutions:
you can make a call to a gateway (which you write). Your gateway would then pull the doc from Salesforce and then send it to DocuSign
Or use DocuSign for Salesforce which does the above for you.
thank you for your answer.
At the end the solution was that the email of the person that I wanted to send the document to sign didnt exist :P.
But now my problem is How can I update the Docusign status? becouse when I put this in an "execute anonymous windows" that creates me a Status:
dsfs__DocuSign_Status__c status = new dsfs__DocuSign_Status__c();
status.dsfs__Contract__c='0293900000xD';
status.dsfs__Envelope_Status__c='Sent';
upsert status;
but when i use this inside of a controller extension:
try {
DocuSignAPI.EnvelopeStatus es = dsApiSend.CreateAndSendEnvelope(envelope);
envelopeId = es.EnvelopeID;
// this.contract.DocuSign_Status__c=es.Status;
dsfs__DocuSign_Status__c status = new dsfs__DocuSign_Status__c();
status.dsfs__Contract__c=this.contract.Id;
status.dsfs__Envelope_Status__c=es.Status;
upsert status;
} catch ( CalloutException e) {
System.debug('Exception - ' + e );
envelopeId = 'Exception - ' + e;
}
Doesn't work, the Status is never created.
Thank you for your help.

Resources