Here is my issue:
We integrated docusign in our application, server side with nodejs using this tutorial https://github.com/docusign/docusign-node-client ("OAuth JSON Web Token (JWT) Grant" section)
We have done the "Go Live Process": our application is registered in our production account
We have replaced the test config to the production config.
When we try to create an envelope, we get the following error:
PARTNER_AUTHENTICATION_FAILED: The specified Integrator Key was not found or is disabled. Invalid account specified for user
What am I doing wrong ?
async function docusignInit() {
var options;
var env = [40077,50077].indexOf(config.main.port) != -1 ? 'test' :'prod';
if (env == "test") {
options = {
basePath: restApi.BasePath.DEMO,
oAuthBasePath: oAuth.BasePath.DEMO
}
} else {
options = {
oAuthBasePath: "account.docusign.com",
// We called https://account.docusign.com/oauth/userinfo to found the uri
basePath:"https://eu.docusign.net/restapi/"
}
}
// in production, We must do
// var apiClient = new docusign.ApiClient(options.basePath);
// Otherwise, we get "Error: getaddrinfo ENOTFOUND undefined undefined:443"
var apiClient = new docusign.ApiClient(options.basePath);
var privateKeyFile = fs.readFileSync(`./server/docusign/keys/${env}/private.PEM`);
var res = await apiClient.requestJWTUserToken(config.docusign.integratorKey, config.docusign.userName, [oAuth.Scope.IMPERSONATION, oAuth.Scope.SIGNATURE], privateKeyFile, 3600)
var token = res.body.access_token;
apiClient.addDefaultHeader('Authorization', 'Bearer ' + token);
docusign.Configuration.default.setDefaultApiClient(apiClient);
await sendDocusign({
userId: 1,
firstName: 'foor',
lastName: 'bar',
email:'foo#bar;'
})
}
async function sendDocusign(role) {
var envDef = new docusign.EnvelopeDefinition();
envDef.emailSubject = 'Please signe this';
envDef.templateId = config.docusign.templateId;
var role = new docusign.TemplateRole();
role.roleName = "roleName";
role.clientUserId = role.userId;
role.name = role.firstName + " " + role.lastName;
role.email = role.email;
envDef.allowReassign = false;
envDef.templateRoles = [role];
envDef.status = 'sent';
var envelopesApi = new docusign.EnvelopesApi();
return await envelopesApi.createEnvelope(config.docusign.userAccountId, {
'envelopeDefinition': envDef
})
}
As you are able to generate AccesToken properly in PROD with PROD RSA KeyPair, so please check the endpoint which you using to make API calls to create an envelope. In demo it is always demo.docusign.net but in PROD it will be a different value depending on where you PROD account exists in the DocuSign data center. For instance if your PROD account is in NA1, then hostname will be will be www.docusign.net; if it is NA2 then hostname will be na2.docusign.net etc.
So it is recommended to make a /userinfo API call with the Access token to know the baseURI to make calls related to envelope. To get the base URI, call the /oauth/userinfo endpoint, supplying your application’s access token as a header.
For the developer sandbox environment, the URI is
https://account-d.docusign.com/oauth/userinfo
For the production environment, the URI is
https://account.docusign.com/oauth/userinfo
Documentation related to /userinfo API call is available here. Once you know you BaseURI then append this baseURI with envelopes related endpoint like below:
{base_uri} + "/restapi/v2.1/accounts/" + {account_id}
considering your error seems that you're missing the integratorKey or you're writing it in the wrontg way. According to that LINK is possible that you miss the brackets inside the intregrator key?
The integrator key must be placed in front of the user ID that is in
the Username node of the UsernameToken. The integrator key must be
wrapped with brackets, “[ and ]”.
An example of the api in the above documentation:
<soap:Header>
<wsa:Action>http://www.docusign.net/API/3.0/GetRecipientEsignList</wsa:Action>
<wsa:MessageID>uuid:3f9d7626-c088-43b4-b579-2bd5e8026b17</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous</wsa:Address>
</wsa:ReplyTo>
<wsa:To>http://demo.docusign.net/api/3.0/api.asmx</wsa:To>
<wsse:Security soap:mustUnderstand="1">
<wsu:Timestamp wsu:Id="Timestamp-8838aa24-9759-4f85-8bf2-26539e14f750">
<wsu:Created>2006-04-14T14:29:23Z</wsu:Created>
<wsu:Expires>2006-04-14T14:34:23Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SecurityToken-7c7b695e-cef7-463b-b05a-9e133ea43c41">
<wsse:Username>[Integrator Key Here]2988541c-4ec7-4245-b520-f2d324062ca3</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>
<wsse:Nonce>SjlScsL5q3cC1CDWrcMx3A==</wsse:Nonce>
<wsu:Created>2006-04-14T14:29:23Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soap:Header>
Related
On this page I generate the access token and with it I can publish the image on my Instagram:
For publish:
function InstagramPost() {
const access_token = 'GENERATE ACESS TOKEN';
const instagram_business_account = 'YYYYYYYYYYYYYYYYYY';
const image = 'https://upload.wikimedia.org/wikipedia/en/9/95/Test_image.jpg';
const text = 'Hello World';
var formData = {
'image_url': image,
'caption': text,
'access_token': access_token
};
var options = {
'method' : 'post',
'payload' : formData
};
const container = 'https://graph.facebook.com/v14.0/' + instagram_business_account + '/media';
const response = UrlFetchApp.fetch(container, options);
const creation = response.getContentText();
var data = JSON.parse(creation);
var creationId = data.id
var formDataPublish = {
'creation_id': creationId,
'access_token': access_token
};
var optionsPublish = {
'method' : 'post',
'payload' : formDataPublish
};
const sendinstagram = 'https://graph.facebook.com/v14.0/' + instagram_business_account + '/media_publish';
UrlFetchApp.fetch(sendinstagram, optionsPublish);
}
Now I want to take this access token and generate a long-lived one with it!
It asks for Instagram App Secret, but that path indicated (App Dashboard > Products > Instagram > Basic Display > Instagram App Secret) doesn't exist in App Dashboard!
I tried using the App secret as a parameter:
"https://graph.instagram.com/access_token
?grant_type=ig_exchange_token
&client_secret={App Secret Key}
&access_token={short-lived-access-token}"
But this error occurs:
Sorry, this content isn't available right now
The Facebook API is 100% accessible, so that's not the problem.
In Javascript/NodeJS I couldn't get it working at all (also on PostMan), I was using the request library.
Changed my code to:
const respLong = await axios.get(`https://graph.instagram.com/access_token?grant_type=ig_exchange_token&client_secret=${CLIENT_SECRET}&access_token=${accessTokenShort.toString()}`);
And magically this works. I can't tell you why what seems to be the exact same request in Postman and the request library doesn't work.
See pic of the url to get app secret (add your app ID) is: https://developers.facebook.com/apps/YOUR_APP_ID(number)/instagram-basic-display/basic-display/
There is a difference in approach between Basic Display and Instagram Graph API for Business Account.
So the way to convert a short-lived token to a long-lived token for Instagram Business Account is:
"https://graph.facebook.com/{graph-api-version}/oauth/access_token?
grant_type=fb_exchange_token&
client_id={app-id}&
client_secret={app-secret}&
fb_exchange_token={your-short-lived-access-token}"
Note that Instagram App Secret is not used, instead, use App Id and App Secret.
I tried to receive a token with the code below. Unfortunatelly I get the error:
DocuSign.eSign.Client.ApiException
HResult=0x80131500
Nachricht = Error while requesting server, received a non successful HTTP code with response Body: {"error":"consent_required"}
I tried with set TLS 12 and without. We run it in dev mode with base path https://demo.docusign.net/restapi
and oAuthBasePath =account-d.docusign.com
I tried also to set the consens manually with the URL below. But I receive the error in (Login Window) invalid Authorization: RequestType is not supported.
https://account-d.docusign.com/oauth/auth?response_type=code&scope=signature%20impersonation&client_id=a5ed47d5-xxxx-xxxx-8a19-756da64391de&redirect_uri=https://www.docusign.com
Is the something wrong with my account setting?
byte[] privateKey=DSHelper.ReadFileContent(DSHelper.PrepareFullPrivateKeyFilePath(privateKeyFilename));
var scopes = new List<string>
{
"signature",
"impersonation",
};
var basePath = ApiClient.Production_REST_BasePath;
var oAuthBasePath = OAuth.Production_OAuth_BasePath;
if (!production)
{
basePath = ApiClient.Demo_REST_BasePath;
oAuthBasePath = OAuth.Demo_OAuth_BasePath;
}
var _apiClient = new ApiClient(basePath);
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var authToken = _apiClient.RequestJWTUserToken(
clientId,
ImpersonatedUserId,
oAuthBasePath,
privateKey,
1,
scopes);
I found the solution. instead of reponse_type= code I have to use token
What response_type is supported for an integration key depends on how the key is configured. In the Authentication section of the key's configuration panel, Auth Code Grant allows the response type of code, while Implicit Grant allows the response type of token.
DocuSign's authentication docs assume you have "Auth Code Grant" selected, but either is technically acceptable to allow JWT consent.
I am trying to update only one application setting using below request. My setting is getting updated properly, but my all other application settings are vanished. I see only one settings there with the correct updated value which I tried to update. I do not want to loose or change all other application settings.
What am I missing here or what is wrong I am doing?
I am following the below given article:
https://learn.microsoft.com/en-us/rest/api/appservice/webapps/updateapplicationsettings
PUT https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{name}/config/appsettings
I am using their online tool to send the request:
https://learn.microsoft.com/en-us/rest/api/appservice/webapps/updateapplicationsettings
Since I am using the online tool it is generating the authorization token. But I want to do programmatically. It would be great if I can get the sample code to generate the token and to update application settings.
Authorization: Bearer
eyJ0eXAiOixxxxxxxeyE_rd3Cw
Content-type: application/json
I reproduce your problem and if you want to update application setting, you need to write down all the application settings, otherwise it will be overridden by the one application setting.
Preparation:
1.Register an App registration in Azure Active Directory and get appid and appsecret. Please refer to this article.
2.Add the registered app into Role assignments under Access control.
Here is C# code sample you could refer to.
var appId = "xxxxxxxxxxxxxxxxxxxx";
var secretKey = "xxxxxxxxxxxxxxxxxxxx";
var tenantId = "xxxxxxxxxxxxxxxxxxx";
var context = new AuthenticationContext("https://login.windows.net/" + tenantId);
ClientCredential clientCredential = new ClientCredential(appId, secretKey);
var tokenResponse = context.AcquireTokenAsync("https://management.azure.com/", clientCredential).Result;
var accessToken = tokenResponse.AccessToken;
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
var baseUrl = new Uri($"https://management.azure.com/");
var requestURl = baseUrl +
#"subscriptions/xxxxxxxxxxxxxxxxxxx/resourceGroups/xxxxxx/providers/Microsoft.Web/sites/xxxxxx/config/appsettings?api-version=2016-08-01";
string body = "{\"kind\": \"webapp\",\"properties\": {\"WEBSITE_NODE_DEFAULT_VERSION\": \"6.9.1\",\"aaa\": \"bbb\"}}";
var stringContent = new StringContent(body, Encoding.UTF8, "application/json");
var response = client.PutAsync(requestURl, stringContent).Result;
}
The result is as below:
I've built out an integration using DocuSign's Node SDK. While testing using a DocuSign sandbox account, the authentication flow works just fine using the example in the docs.
I'm now trying to do the same within a live DocuSign production account using the Integrator Key that was promoted from the sandbox account. authApi.login() seems to work just fine, I get no error and the status code of the response is 200. However, the value of loginInfo comes back as exports {} with no account info included.
I've made sure to change the base path from https://demo.docusign.net/restapi to www.docusign.net/restapi and as far as I can tell from the docs, there doesn't seem to be anything else I need to make the switch to production. Here is the code I am using:
apiClient.setBasePath('www.docusign.net/restapi');
apiClient.addDefaultHeader('Authorization', 'Bearer ' + token);
docusign.Configuration.default.setDefaultApiClient(apiClient);
const authApi = new docusign.AuthenticationApi();
const loginOps = {
apiPassword: true,
includeAccountIdGuid: true
};
authApi.login(loginOps, function (err, loginInfo, response) {
if (err) {
console.log(err);
}
if (loginInfo) {
// loginInfo returns 'exports {}' so the variables below cannot be set.
const loginAccounts = loginInfo.loginAccounts;
const loginAccount = loginAccounts[0];
const baseUrl = loginAccount.baseUrl;
const accountDomain = baseUrl.split('/v2');
const accountId = loginAccount.accountId;
apiClient.setBasePath(accountDomain[0]);
docusign.Configuration.default.setDefaultApiClient(apiClient);
www.docusign.net endpoint will only work if your PROD account is in NA1, if your PROD Account is in NA2, then you need to use na2.docusign.net and if it is in NA3 then na3.docusign.net. This is the main reason you should use /oauth/userinfo call with OAUTH2 Access Token to know your base URL, and then call all APIs with this baseURL. You can find more details at https://docs.docusign.com/esign/guide/authentication/userinfo.html
What I am trying to do is to use the "Web API on-behalf-of flow" scenario Microsoft described in this article to create a web hook.
So I started with the Microsoft github example and made sure that I can successfully get the users profile via the Graph API.
Then I modified the code where it gets the users profile to create the web hook, so the code looks like this:
// Authentication and get the access token on behalf of a WPF desktop app.
// This part is unmodified from the sample project except for readability.
const string authority = "https://login.microsoftonline.com/mycompany.com";
const string resource = "https://graph.windows.net";
const string clientId = "my_client_id";
const string clientSecret = "my_client_secret";
const string assertionType = "urn:ietf:params:oauth:grant-type:jwt-bearer";
var user = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
var authenticationContext = new AuthenticationContext(authority,new DbTokenCache(user));
var assertion = ((BootstrapContext) ClaimsPrincipal.Current.Identities.First().BootstrapContext).Token;
var userName = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn) != null
? ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn).Value
: ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email).Value;
var result = await authenticationContext.AcquireTokenAsync(resource,new ClientCredential(clientId,clientSecret),new UserAssertion(assertion,assertionType,userName));
var accessToken = result.AccessToken;
// After getting the access token on behalf of the desktop WPF app,
// subscribes to get notifications when the user receives an email.
// This is the part that I put in.
var subscription = new Subscription
{
Resource = "me/mailFolders('Inbox')/messages",
ChangeType = "created",
NotificationUrl = "https://mycompany.com/subscription/listen",
ClientState = Guid.NewGuid().ToString(),
ExpirationDateTime = DateTime.UtcNow + new TimeSpan(0, 0, 4230, 0)
};
const string subscriptionsEndpoint = "https://graph.microsoft.com/v1.0/subscriptions/";
var request = new HttpRequestMessage(HttpMethod.Post, subscriptionsEndpoint);
var contentString = JsonConvert.SerializeObject(subscription, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
request.Content = new StringContent(contentString, System.Text.Encoding.UTF8, "application/json");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await new HttpClient().SendAsync(request);
if (response.IsSuccessStatusCode)
{
// Parse the JSON response.
var stringResult = await response.Content.ReadAsStringAsync();
subscription = JsonConvert.DeserializeObject<Subscription>(stringResult);
}
The error I get from the response is:
{
"error":
{
"code": "InvalidAuthenticationToken",
"message": "Access token validation failure.",
"innerError":
{
"request-id": "f64537e7-6663-49e1-8256-6e054b5a3fc2",
"date": "2017-03-27T02:36:04"
}
}
}
The webhook creation code was taken straight from the ASP.NET webhook github sample project, which, I have also made sure that I can run successfully.
The same access token code works with the original user profile reading code:
// Call the Graph API and retrieve the user's profile.
const string requestUrl = "https://graph.windows.net/mycompany.com/me?api-version=2013-11-08";
request = new HttpRequestMessage(HttpMethod.Get, requestUrl);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var response = await new HttpClient().SendAsync(request);
So I want to find out:
Is creating a webhook via the graph API using the on-behalf-of flow even supported? Not sure if this SO question is what I'm looking for here.
If it is supported, what am I missing here?
If it is not supported, is there an alternative to achieve it? E.g. is there anything from the existing Office 365 API that I can use?
"message": "Access token validation failure.",
The error means you got incorrect access token for the resource . According to your code ,you get the access token for resource :https://graph.windows.net( Azure AD Graph API) , But then you used that access token to access Microsoft Graph API(https://graph.microsoft.com) ,so access token validation failed .