Docusign - Auto Sending Email on form submit - docusignapi

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>

Related

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.

Using JSON Web Tokens (JWT) with Azure Functions (WITHOUT using Active Directory)

I am sure someone out there has already done this, but I have yet to find any documentation with regard to the Microsoft implementation of JWT. The official documentation from Microsoft for their JWT library is basically an empty page, see:
https://learn.microsoft.com/en-us/dotnet/framework/security/json-web-token-handler-api-reference
So, here is what I (and I am sure many others) would like to accomplish:
Definition: User ID = The username or email address used to log into a system.
AUTHENTICATION:
A user logs in. The user fills in web form and the system sends (via HTTPS POST) the users ID and password (hashed) to the server in order to authenticate / validate the user.
Server Authenticates user. The users ID and password are checked against the values saved in the database and if NOT valid, an invalid login response is returned to the caller.
Create a JWT Token - ???? No documentation available!
Return the JWT token to the caller - ???? - I assume in a header? via JSON, not sure -- again - no documentation.
Given the code below, can anyone provide a code example for steps 3 and 4?
[FunctionName( "authenticate" )]
public static async Task<HttpResponseMessage> Run( [HttpTrigger( AuthorizationLevel.Anonymous, "get", "post", Route = null )]HttpRequestMessage req, TraceWriter log )
{
// Step 1 - Get user ID and password from POST data
/*
* Step 2 - Verify user ID and password (compare against DB values)
* If user ID or password is not valid, return Invalid User response
*/
// Step 3 - Create JWT token - ????
// Step 4 - Return JWT token - ????
}
AUTHORIZATION:
Assuming the user was authenticated and now has a JWT token (I am assuming the JWT token is saved in the users session; if someone wants to provide more info, please do):
A POST request is made to an Azure Function to do something (like get a users birth date). The JWT token obtained above is loaded (from the POST data or a header - does it matter?) along with any other data required by the function.
The JWT token is validated - ???? No documentation available!
If the JWT token is NOT valid, a BadRequest response is returned by the function.
If the JWT token is valid, the function uses the data passed to it to process and issue a response.
Given the code below, can anyone provide a code example for steps 1 and 2?
[FunctionName( "do_something" )]
public static async Task<HttpResponseMessage> Run( [HttpTrigger( AuthorizationLevel.Anonymous, "get", "post", Route = null )]HttpRequestMessage req, TraceWriter log )
{
// Step 1 - Get JWT token (from POST data or headers?)
// Step 2 - Validate the JWT token - ???
// Step 3 - If JWT token is not valid, return BadRequest response
// Step 4 - Process the request and return data as JSON
}
Any and all information would really help those of us (me) understand how to use JWT with Azure (anonymous) functions in order to build a "secure" REST API.
Thanks in advance.
Any and all information would really help those of us (me) understand how to use JWT with Azure (anonymous) functions in order to build a "secure" REST API.
Per my understanding, you could use the related library in your azure function code to generate / validate the JWT token. Here are some tutorials, you could refer to them:
Create and Consume JWT Tokens in C#.
Jwt.Net, a JWT (JSON Web Token) implementation for .NET
JWT Authentication for Asp.Net Web Api
Moreover, you could leverage App Service Authentication / Authorization to configure the function app level Authentication / Authorization. You could go to your Function App Settings, click "NETWORKING > Authentication / Authorization" under the Platform features tab. Enable App Service Authentication and choose Allow Anonymous requests (no action) as follows:
You could create a HttpTrigger function with anonymous accessing for user logging and return the JWT token if the user exists. For the protected REST APIs, you could follow the code sample below:
if(System.Security.Claims.ClaimsPrincipal.Current.Identity.IsAuthenticated)
{
//TODO: retrieve the username claim
return req.CreateResponse(HttpStatusCode.OK,(System.Security.Claims.ClaimsPrincipal.Current.Identity as ClaimsIdentity).Claims.Select(c => new { key = c.Type, value = c.Value }),"application/json");
}
else
{
return req.CreateResponse(HttpStatusCode.Unauthorized,"Access Denied!");
}
For generating the JWT token used in App Service Authentication, you could follow How to: Use custom authentication for your application and the code under custom API controller CustomAuthController from adrian hall's book about Custom Authentication to create the JWT token.
UPDATE:
For the custom authentication approach under App Service Authentication, I just want op to leverage the authentication / Authorization provided by EasyAuth. I have did some test for this approach and found it could work on my side. Op could send the username and password to the HttpTrigger for authentication, then the HttpTrigger backend need to validate the user info, and use Microsoft.Azure.Mobile.Server.Login package for issuing App Service Authentication token to the client, then the client could retrieve the token from the AuthenticationToken property. The subsequent requests against the protected APIs could look like as follows:
https://<your-funapp-name>.azurewebsites.net/api/<httpTrigger-functionName>
Header: x-zumo-auth:<AuthenticationToken>
NOTE:
For this approach, the related HttpTrigger functions need to allow anonymous accessing and the App Service Authentication also needs to choose Allow Anonymous requests (no action). Otherwise, the App Service Authentication and function level authentication would both validate the request. For the protected APIs, op needs to manually add the System.Security.Claims.ClaimsPrincipal.Current.Identity.IsAuthenticated checking.
Try this: https://liftcodeplay.com/2017/11/25/validating-auth0-jwt-tokens-in-azure-functions-aka-how-to-use-auth0-with-azure-functions/
I successfully made it work using this guide. It took awhile due to nuget versions.
Follow that guide properly and use the following nuget versions
IdentityModel.Protocols (2.1.4)
IdentityModel.Protocols.OpenIdConenct (2.1.4)
IdentityModel.Tokens.Jwt (5.1.4)
Oh and, the guide tells you to write your AUDIENCE as your api link, don't. You'll get unauthorized error. Just write the name of your api, e.g. myapi
If you get error about System.http.formatting not being loaded when running the function, try to reinstall NET.Sdk.Functions and ignore the warning about AspNet.WebApi.Client being restored using .NETFramework. And restart visual studio.
What you're describing is something that you should be able to do yourself by doing a little bit of research. To address your specific questions:
Create a JWT Token - ???? No documentation available!
The link Bruce gave you gives a nice example for how to create a JWT: https://www.codeproject.com/Tips/1208535/Create-And-Consume-JWT-Tokens-in-csharp
Return the JWT token to the caller - ???? - I assume in a header? via JSON, not sure -- again - no documentation.
There's no documentation because you're basically inventing your own protocol. That means how you do it is entirely up to you and your application requirements. If it's a login action, it might make sense to return it as part of the HTTP response payload. Just make sure that you're using HTTPS so that the token stays protected over the wire.
A POST request is made to an Azure Function to do something (like get a users birth date). The JWT token obtained above is loaded (from the POST data or a header - does it matter?) along with any other data required by the function.
How you send the token is, again, entirely up to you. Most platforms use the HTTP Authorization request header, but you don't have to if you don't want to.
The JWT token is validated - ???? No documentation available!
Use the ValidateToken method of the JwtSecurityTokenHandler (see the previous link for how to get the JwtSecurityTokenHandler). Docs here: https://msdn.microsoft.com/en-us/library/dn451155(v=vs.114).aspx.
I created an Azure Functions input binding for JWT Token Validation. You can use this as an extra parameter with the [JwtBinding] attribute. See https://hexmaster.nl/posts/az-func-jwt-validator-binding/ for source and NuGet package information.
Basically Azure Functions built on top of ASP.NET Core. By making some dependency injection tricks you could add your own authentication and policy-based authorization. I created demo solution with JWT authentication just for fun, beware to use it on production.

chrome.identity.LaunchWebAuthFlow: How to implement logout in a web app using oauth2

I am working on some client side web app like a chrome extension that needs access to outlook mail and calendar. I followed the instruction on https://dev.outlook.com/RestGettingStarted and successfully got access and refresh tokens to retrieve data.
However, I cannot find any way of implementing "logout". The basic idea is to let user sign out and login with a different outlook account. In order to do that, I removed cached tokens, requested access tokens in interactive mode. The login window did pop out, but it took any valid email address, didn't let me input password and finally returned tokens for previous account. So I was not able to really use a different account until the old token expired.
Can anyone please tell me if it is possible to send a request to revoke the tokens so people can use a different account? Thanks!
=========================================================
Update:
Actually it is the fault of chrome.identity api. I used chrome.identity.LaunchWebAuthFlow to init the auth flow. It caches user's identity but no way to remove it. So we cannot really "logout" if using this api.
I used two logouts via launchWebAuthFlow - first I called the logout link to my app, then secondly, I called the logout link to Google.
var options = {
'interactive': false,
'url': 'https://localhost:44344/Account/Logout'
}
chrome.identity.launchWebAuthFlow(options, function(redirectUri) {});
options = {
'interactive': false,
'url': 'https://accounts.google.com/logout'
}
chrome.identity.launchWebAuthFlow(options, function(redirectUri) {});

.NET Gmail OAuth2 for multiple users

We are building a solution that will need to access our customers Gmail accounts to read/send mail. On account signup, we'd have a pop-up for our customer to do Gmail auth page and then a backend process to periodically read their emails.
The documentation doesn't seem to cover this use case. For example https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth says that client tokens should be stored in client_secrets.json - what if we have 1000s of clients, what then?
Service accounts are for non-user info, but rather application data. Also, if I use the GoogleWebAuthorizationBroker and the user has deleted access or the tokens have expired, I don't want my backend server app to pop open a web brower, as this seems to do.
I would imagine I could use IMAP/SMTP accomplish this, but I don't think it's a good idea to store those credentials in my db, nor do I think Google wants this either.
Is there a reference on how this can be accomplished?
I have this same situation. We are planning a feature where the user is approving access to send email on their behalf, but the actual sending of the messages is executed by a non-interactive process (scheduled task running on an application server).
I think the ultimate answer is a customized IAuthorizationCodeFlow that only supports access with an existing token, and will not execute the authorization process. I would probably have the flow simulate the response that occurs when a user clicks the Deny button on an interactive flow. That is, any need to get an authorization token will simply return a "denied" AuthorizationResult.
My project is still in the R&D phase, and I am not even doing a proof of concept yet. I am offering this answer in the hope that it helps somebody else develop a concrete solution.
While #hurcane's answer more than likely is correct (haven't tried it out), this is what I got working over the past few days. I really didn't want to have to de/serialize data from the file to get this working, so I kinda mashed up this solution
Web app to get customer approval
Using AuthorizationCodeMvcApp from Google.Apis.Auth.OAuth2.Mvc and documentation
Store resulting access & refresh tokens in DB
Use AE.Net.Mail to do initial IMAP access with access token
Backend also uses AE.Net.Mail to access
If token has expired, then use refresh token to get new access token.
I've not done the sending part, but I presume SMTP will work similarly.
The code is based on SO & blog posts:
t = EF object containing token info
ic = new ImapClient("imap.gmail.com", t.EmailAddress, t.AccessToken, AuthMethods.SaslOAuth, 993, true);
To get an updated Access token (needs error handling) (uses the same API as step #1 above)
using (var wb = new WebClient())
{
var data = new NameValueCollection();
data["refresh_token"] = refresh;
data["client_id"] = "(Web app OAuth id)";
data["client_secret"] = "(Web app OAuth secret)";
data["grant_type"] = "refresh_token";
var response = wb.UploadValues(#"https://accounts.google.com/o/oauth2/token", "POST", data);
string Tokens = System.Text.Encoding.UTF8.GetString(response);
var token = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(Tokens);
at = token.access_token;
return at;
}

C# MS-CRM 2013 online Plugin To Publish Event On Facebook Page

My solution may not be technically possible. Yet I would like your viewpoint
We have to create a workflow/plugin MS-CRM 2013 which will publish events from CRM to a particular facebook page.
A separate application is not possible.
The problem is, to publish I need Page Access Token.
To get Page Access Token I need User Access Token.
To get User Access Token I need to follow the redirect_uri path where I will get the code in URL string but MS-CRM 2013 as you might be aware does not allow "code" as url string, it will refuse to redirect itself to my callback page, that is my problem.
I am open to suggestions I have used Facebook SDK and simple webrequest.this gives me the App Access Token
dynamic result = obj.Get("oauth/access_token", new
{
client_id = this.fbAppID,
client_secret = this.fbAppSecret,
grant_type = "client_credentials",
scope = "publish_actions,manage_pages,create_event,read_stream,publish_stream,email,read_friendlists,read_insights,read_requests,manage_friendlists,user_about_me,user_activities,user_birthday,user_groups,friends_groups"
});
Now How do I get the user access token from inside MS-CRM 2013 online.
If somebody has done it please do let me know, if you need more clarification I will be happy to provide more code etc.
You need to separate your logic:
Create an HTML/JavaScript WebResource combo that allows a user to link their CRM SystemUser record to Facebook. Build code similar to that below - it'll need additional supporting code to check if the user is already connected to Facebook, etc.
FB.login(function (response) {
if (response.authResponse) {
// user sucessfully logged in
var accessToken = response.authResponse.accessToken;
//TODO: Add logic to save accessToken to CRM SystemUser record.
}
}, { scope: 'email,publish_stream,email,rsvp_event,read_stream,user_likes,user_birthday' });
In your plugin retrieve the FB Access Token, saved in step 1, from the CRM SystemUser record, and use that to instantiate your Facebook connection object:
var obj = new FacebookClient(accessToken);
This is a bunch of work to do to get the access token. And none of the guides are going to clearly explain mixing pure HTML/JS for token retrieval but making the calls from C#, since this is a fairly unusual requirement.

Resources