I am using DocuSign eSign SDK V3.1.1 to create user in DocuSign without sending any activation email to user. I want password and forgotten password information to be set from API itself so that after this call user can immediately start using their account. I am using below code for this purpose:
UserInformation userInformation = new UserInformation()
{
UserName = data["UserName"],
Email = data["UserEmail"],
SendActivationEmail = "false",
Password = "123456",
ForgottenPasswordInfo = new ForgottenPasswordInformation()
{
ForgottenPasswordQuestion1 = "What is the name of your first pet?",
ForgottenPasswordAnswer1 = "Pogo"
},
PermissionProfileId = "XXXXX"
};
List<UserInformation> usersInfo = new List<UserInformation>() { userInformation };
NewUsersDefinition newUsersDefinition = new NewUsersDefinition()
{
NewUsers = usersInfo
};
var result = usersApi.Create(accountId, newUsersDefinition);
However, the ctivation email is still sent to user and password and forgotten password is not set from the API. Am I missing something in above request? Or do I need to set any other parameter to achieve the requirement?
Silent Activation through the eSignature API is only available on some account types, and is no longer generally available. The supported way to do this is now through the Organization API, as documented here: https://developers.docusign.com/orgadmin-api/code-examples/add-user
If you don't currently have an Organization with a Claimed Domain, you'll want to reach out to your Account Manager or the Sales team to have the Organization module added to your account. DocuSign Support can enable that on a Demo/Sandbox account, open a Support case and provide your demo account ID.
Related
I need to send mails from a background application(worker service/azure function) using MSGraph API with Application permission. This is how I have initialized the GraphServiceClient to send emails.
var credentials = new ClientSecretCredential(
"TenantID",
"ClientId",
"ClientSecret",
new TokenCredentialOptions { AuthorityHost = AzureAuthorityHosts.AzurePublicCloud });
GraphServiceClient graphServiceClient = new GraphServiceClient(credentials);
var subject = $"Subject from demo code";
var body = $"Body from demo code";
// Define a simple e-mail message.
var email = new Microsoft.Graph.Message
{
Subject = subject,
Body = new ItemBody
{
ContentType = BodyType.Html,
Content = body
},
ToRecipients = new List<Recipient>()
{
new Recipient { EmailAddress = new EmailAddress { Address = "EmailId" }}
}
};
// Send mail as the given user.
graphServiceClient
.Users["UserID"]
.SendMail(email, true)
.Request()
.PostAsync().Wait();
How long the graphServiceClient will have a valid token and how to regenerate a token when the token is expired.
What are the best practices for this usage
The default lifetime of an access token is variable. When issued, an access token's default lifetime is assigned a random value ranging between 60-90 minutes (75 minutes on average). Please refer this DOC for more information.
The refresh tokens can be used to acquire access tokens if they expire, Refresh tokens are long-lived, and can be used to retain access to resources for extended periods of time.
For getting the access tokens with client secret please refer this method of getting the access tokens.
Hope this will help.
As of May 2022, there is no option to generate a refresh token while using client_credentials options.
For client_credentials option
It's possible to generate a refresh token while using on behalf of user
For on behalf of a user
Another company we partner with sends us new client information via DocuSign envelopes completed by those clients. I am attempting to extract the form data from the document, either via the PDF or via the DocuSign API. The PDF only appears to have the Envelope ID embedded in it. When I add my account as a CC recipient and try to view the form data in the DocuSign console, I receive an error message:
Additionally, I'm unable to view the form data via the DocuSign API.
{
errorCode: "USER_LACKS_PERMISSIONS",
message: "This user lacks sufficient permissions to access this resource."
}
I've tried accessing via the API at:
/v2/accounts/{accountId}/envelopes/{envelopeId}/recipients/{recipientId}/tabs
/v2/accounts/{accountId}/envelopes/{envelopeId}/documents/{documentId}/fields
Questions:
Is there a way for a user who is not in the sender's tenant to be able to view the envelope form data?
Is there a way for DocuSign to embed the tab data into the PDF for extraction?
Is there another approach I'm not considering?
If the user is cc to the envelope using the same userId and email combination that is on their account, then that user also can use the API to gain account information. (account is what you call "tenant.")
If the user is not on the envelope and you just receive the PDF some other way, then you cannot use the API to obtain information about the envelope because that is limited only to recipients of the envelope.
#Inbar-Gazit was kind enough to do some digging internally at DocuSign, and after a bit of back-and-forth, discovered that this is possible using the SOAP API with the RequestEnvelope and RequestEnvelopeV2 methods. I'm unsure if there's any advantage to using one method over the other. Both also have async methods.
https://developers.docusign.com/docs/esign-soap-api/reference/Status-and-Managing-Group/RequestEnvelope
Some quick-and-dirty C# validated that this will indeed work. I validated this both as the sending account (which also works via REST) and the CC recipient account (which did not work via REST).
var authString = $"<DocuSignCredentials><Username>{_userName}</Username><Password>{_password}</Password><IntegratorKey>{_apiKey}</IntegratorKey></DocuSignCredentials>";
var client = new DSAPIServiceSoapClient();
using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
{
HttpRequestMessageProperty httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers.Add("X-DocuSign-Authentication", authString);
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
EnvelopeStatus status = client.RequestStatusEx(_envelopeId);
Console.Out.WriteLine("Subject: " + status.Subject);
// RequestEnvelope Method
var envelope = client.RequestEnvelope(_envelopeId, false);
var testTab = envelope.Tabs.FirstOrDefault(t => t.TabLabel.Contains("Test"));
if (testTab != null)
{
Console.WriteLine($"Tab {testTab.TabLabel}: {testTab.Value}");
} else
{
Console.WriteLine("Tab not found.");
}
// RequestEnvelopeV2 Method
var requestOptions = new RequestEnvelopeV2Options() {
IncludeAC = false,
IncludeAnchorTabLocations = true,
IncludeDocumentBytes = false
};
var envelopeV2 = client.RequestEnvelopeV2(_envelopeId, requestOptions);
var testTabV2 = envelopeV2.Tabs.FirstOrDefault(t => t.TabLabel.Contains("Test"));
if (testTabV2 != null)
{
Console.WriteLine($"Tab(v2) {testTabV2.TabLabel}: {testTabV2.Value}");
} else
{
Console.WriteLine("Tab(v2) not found.");
}
Console.WriteLine("\r\nDone.");
Console.ReadKey();
}
Output:
Subject: Please DocuSign: Test Envelope
Tab txtDataLabelTest1: Some Data Here
Tab(v2) txtDataLabelTest1: Some Data Here
Done.
I want to send a mail via the gmail API. I have a function that works so far, but my problem is that I don't know how to change the from address. My mails are always send as the user I authorized the API access with.
So I want my mails sent from from.mail#example.com in the following code:
function sendSampleMail(auth, cb) {
let gmailClass = google.gmail('v1');
let emailLines = [];
emailLines.push('From: from.mail#example.vom');
emailLines.push('To: to.mail#example.com');
emailLines.push('Content-type: text/html;charset=iso-8859-1');
emailLines.push('MIME-Version: 1.0');
emailLines.push('Subject: this would be the subject');
emailLines.push('');
emailLines.push('And this would be the content.<br/>');
emailLines.push('The body is in HTML so <b>we could even use bold</b>');
const email = emailLines.join('\r\n').trim();
let base64EncodedEmail = new Buffer.from(email).toString('base64');
base64EncodedEmail = base64EncodedEmail.replace(/\+/g, '-').replace(/\//g, '_');
gmailClass.users.messages.send(
{
auth: auth,
userId: 'me',
resource: {
raw: email
}
},
cb
);
}
I don't know if it's even possible to send with different from-mails via the google API. I could not find any information about that and no solutions.
You can't send emails (or make any request) as a different user from the authenticated user because you don't have any permissions to impersonate it.
If you're a G Suite administrator, you can use a service account [1][2] with domain wide delegation [3], which will grant you access to impersonate any gmail account from your domain. You can create a service account on Cloud Platform after selecting a project, from where you'll be able to download the credentials JSON file. And use the JSON Web Tokens methods [4] to authorize your application using the service account JSON.
[1] https://cloud.google.com/iam/docs/service-accounts
[2] https://cloud.google.com/iam/docs/understanding-service-accounts
[3] https://developers.google.com/admin-sdk/directory/v1/guides/delegation
[4] https://github.com/googleapis/google-auth-library-nodejs#json-web-tokens
I'm new to Azure AD B2C and have set up a site that correctly authenticates using local accounts (email only). When the validation request comes back, I see the email address under the 'emails' claim, but the 'name' claim comes back as 'unknown'.
Looking in Azure portal, the account is created but the name is unset and is 'unknown' for all users that register. This isn't what I was expecting. I would prefer that the 'name' be set to the email address by default so that it is easier to find the account in the portal, since we aren't collecting a 'Display Name' at all for this account type (user already enters given and surname).
Do I have something configured incorrectly, and is there a way to default the username to the email address for local, email only accounts?
Azure AD B2C does not "auto-populate" any fields.
When you setup your sign-up policy or unified sign-up/sign-in policy you get to pick the Sign-up attributes. These are the attributes that are show to the user for him/her to provide and are then stored in Azure AD B2C.
Anything that the user is not prompted for is left empty or in a few select cases (like name as you have observed) set to 'unknown'.
Azure AD B2C can not make assumptions as to what to pre-populate a given attribute with. While you might find it acceptable to use the email as the default for the name, others might not. Another example, the display name, for some, can be prepopulated with "{Given name} {Surname}", but for others, it's the other way around "{Surname, Givenname}".
What you are effectively asking for is an easy way to configure defaults for some attributes which is not that's available today. You can request this feature in the Azure AD B2C UserVoice forum.
At this time, you have two options:
Force your users to explicitly provide this value by select it as a sign-up attribute in your policy.
Add some code that updates these attributes with whatever logic you want (for example in the controller that processes new sign-ups or via a headless client running periodically).
Here's a quick & dirty snippet of .Net code that you can use for this (assuming you want to do this in the auth pipeline (Startup.Auth.cs):
private async Task OnSecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
try
{
var userObjectId = notification.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")?.Value;
// You'll need to register a separate app for this.
// This app will need APPLICATION (not Delegated) Directory.Read permissions
// Check out this link for more info:
// https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-devquickstarts-graph-dotnet
var authContext = new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(string.Format(graphAuthority, tenant));
var t = await authContext.AcquireTokenAsync(graphResource, new ClientCredential(graphClientId, graphClientSecret));
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + t.AccessToken);
var url = graphResource + tenant + "/users/" + userObjectId + "/?api-version=1.6";
var name = "myDisplayName";
var content = new StringContent("{ \"displayName\":\"" + name + "\" }", Encoding.UTF8, "application/json");
var result = await client.PostAsync(url, content);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
You'll reference this method when you setup your OpenIdConnectAuthenticationOptions like so:
new OpenIdConnectAuthenticationOptions
{
// (...)
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = OnAuthenticationFailed,
SecurityTokenValidated = OnSecurityTokenValidated,
},
// (...)
};
I wrote this extension:
public static class ClaimsPrincipal
{
public static string Username(this System.Security.Claims.ClaimsPrincipal user)=> user.Claims.FirstOrDefault(c => c.Type == "preferred_username").Value;
}
Now you can use
User.Identity.Name for name if you have this in your OpenId config in the Startup.cs
options.TokenValidationParameters = new TokenValidationParameters() { NameClaimType = "name" };
and User.Username if you include the extension
I am trying to send an email using the Outlook/Office 365 REST API, and I am trying to send it as an address that I have as a "Connected Account". Attempting to send the message returns a `` error. However, the API will let me create a draft with this address.
Additionally, I can send the API-created draft just fine, and I can also create and send messages as this account from the web interface.
Is there a way to authorize the API to be able to send a message as an address for a connected account?
No, the API doesn't support this today. It has to do with the scope of the permissions that you consent to. "Allow this app to send mail as you" covers sending from your account, but not from another account, even if you have been granted access.
Another thing you can think about is to leverage App-only authentication. You can configure a Azure AD App to have App-only authentication. After that, all the request will behalf of that app id and you should be able to delegate that app id to send email to anyone on behalf of the user you want.
The following is the steps:
Create a Azure AD application.
Configure your Azure AD Application to allow App-only token by
following Build service and daemon apps in Office 365. You also
need a certificate for app-only token request.
Go to your Azure AD Application->Configuration, Click "Add
application" to add "Office 365 Exchange Online". Select "Send email
as any user" under "Application permission" dropdown box. It allows
your Azure AD App to have permission to send email on behalf of
someone.
Once you have Azure AD application configured, you can refer the
following code for sending email on behalf of a specific user.
string tenantId = "yourtenant.onmicrosoft.com";
string clientId = "your client id";
string resourceId = "https://outlook.office.com/";
string resourceUrl = "https://outlook.office.com/api/v2.0/users/service#contoso.com/sendmail"; //this is your on behalf user's UPN
string authority = String.Format("https://login.windows.net/{1}", AUTHORITYURL, tenantId);
string certificatPath = #"c:\test.pfx"; //this is your certficate location.
string certificatePassword = "xxxx"; // this is your certificate password
var itemPayload = new
{
Message = new
{
Subject = "Test email",
Body = new { ContentType = "Text", Content = "this is test email." },
ToRecipients = new[] { new { EmailAddress = new { Address = "test#cotoso.com" } } }
}
};
//if you need to load from certficate store, use different constructors.
X509Certificate2 certificate = new X509Certificate2(certficatePath, certificatePassword, X509KeyStorageFlags.MachineKeySet);
AuthenticationContext authenticationContext = new AuthenticationContext(authority, false);
ClientAssertionCertificate cac = new ClientAssertionCertificate(clientId, certificate);
//get the access token to Outlook using the ClientAssertionCertificate
var authenticationResult = await authenticationContext.AcquireTokenAsync(resourceId, cac);
string token = authenticationResult.AccessToken;
//initialize HttpClient for REST call
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
client.DefaultRequestHeaders.Add("Accept", "application/json");
//setup the client post
HttpContent content = new StringContent(JsonConvert.SerializeObject(itemPayload));
//Specify the content type.
content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json;odata=verbose");
HttpResponseMessage result = await client.PostAsync(url, content);
if(result.IsSuccessStatusCode)
{
//email send successfully.
}else
{
//email send failed. check the result for detail information from REST api.
}
For a complete explanation, please reference to my blog Send email on behalf of a service account using Office Graph API
I hope it helps and let me know if you have questions.