cancel
Showing results forย 
Search instead forย 
Did you mean:ย 

Tutorial: Using the DocuSign eSignature REST API with the REST Snap Pack and JWT Authentication

robin
Former Employee

I previously wrote about integrating with the DocuSign eSignature API with the REST Snap Pack and OAuth 2.0 authentication, but for those that wish to control their access a bit more, DocuSign supports authenticating with JSON Web Tokens (JWTs) too.

I followed the instructions from the โ€œHow to get an access token with JWT Grant authenticationโ€ DocuSign Developer portal.

Setup

As before, DocuSign makes it very easy to get started with their free Developer Account signup.

Again, in the sidebar under โ€œINTEGRATIONSโ€, select โ€œApps and Keysโ€. One that page is up, choose the โ€œAdd App & Integration Keyโ€ button and provide an application name (I chose โ€œSnapLogic Community JWT Demoโ€ this time).

The โ€œIntegration Keyโ€ that is generated is also known as the Client ID and JWT will also refer to it as the "iss" value.

You can keep the User Application selected as Authorization Code Grant but instead of adding a Secret Key, this time weโ€™re going to be choosing a Service Integration:

image

I wanted DocuSign to generate the public/private key pair for me, so I selected the โ€œGenerate RSAโ€ button.

A new dialog will open this the generated keys - you must copy these values and store them somewhere as this will be your only chance to do so:

image

Finally, I set a throwaway Redirect URI, http://localhost (this isnโ€™t really used - the goal here is to first authorized the app you created but JWT will take over from that point). Click โ€œSaveโ€ to create the Integration App.

Grant Consent

The first thing you want to do is to get consent from a DocuSign user (it could be you) for this App to impersonate them (thatโ€™s what a Service account does). It follows this URI syntax:

https://account-d.docusign.com/oauth/auth?
    response_type=code
    &scope=YOUR_REQUESTED_SCOPES
    &client_id=YOUR_INTEGRATION_KEY
    &state=YOUR_CUSTOM_STATE
    &redirect_uri=YOUR_REDIRECT_URI

so I opened the following URL in my browser (substitute your client ID/integration key, state, scopes and redirect URI that you wish to use):

https://account-d.docusign.com/oauth/auth?response_type=code&scope=signature%20impersonation&client_...

Youโ€™ll be asked to consent to the application:

image

and then redirected to that throwaway localhost redirect URI (you donโ€™t need to save anything from this response).

Generating the JWT

Now that consent has been granted, itโ€™s time to move to JWT. This is where the JWT Snap Pack comes into play.

Itโ€™s outside the scope of this topic to fully describe JWT, but in short it is a token value that encodes header and payload/body data that is signed with keys. The DocuSign Developer docs take you through how its constructed.

The JWT Generate Snap will take care of generated the correct header ("kid" is the Key Alias ID - more on that later, "alg" has to be "RS256", and "typ":"JWT" is implied by the JWT spec).

The main action is to generate the JWT Payload/Body that matches what DocuSign wants:

{
  "iss": "5c2b8d7e-xxxx-xxxx-xxxx-cda8a50dd73f",
  "sub": "464f7988-xxxx-xxxx-xxxx-781ee556ab7a",
  "aud": "account-d.docusign.com",
  "iat": 1598383123,
  "exp": 1598390123,
  "scope": "signature impersonation"
}

and there are few ways to do that.

You could build the above JSON object manually than use it directly in the โ€œCustom Metadataโ€ section, but Iโ€™ll show how to leverage the various fields in the JWT Generate Snap and the JWT Account.

"aud" and "sub" stand for Audience and Subject respectively and can be set directly on the JWT Generate Snap:

"sub" is the most difficult value to get - in fact, you have to look it up by using the API to call the /userinfo endpoint and that means using the OAuth 2.0 flow. Luckily, my first post described exactly how to do this - follow the setup instructions and see the โ€œGET User Infoโ€ section.

image

Note: "aud" must be list of strings (hence the array). It will be disregarded silently if it is not and your auth will fail. We will investigate a usability enhancement here.

The "iat" value will be generated automatically (it defaults to โ€œnowโ€ in Unix Epoch timestamp format).

"iss" is the issuer, and this will be the Client ID/Integration Key created when you registered your App in the DocuSign Developer portal.

You configure the "iss" and "exp" values by creating a JWT Account and leveraging the โ€œJWT Issuerโ€ and โ€œToken TTLโ€ fields respectively (the latter is added to the generated "iat" value).

image

That leaves the "scopes" (which will always include impersonation and most DocuSign APIs want the signature scope too, so Iโ€™ve include them both, space-separated), and that can be directly configured on the โ€œCustom Metadataโ€ field in the JWT Generate Snap.

All this configuration between the Snap and Account settings will be combined to form the Payload (you may also see a "nbf" payload field automatically added, which is โ€œnot beforeโ€ and defaults to 120 seconds before "iat" and โ€œToken IDโ€ becomes "jti"; DocuSign will ignore these):

image

Finally, we need to configure the JWT Generate Snapโ€™s Account for signing. This is where the public/private keypair saved earlier will be used. Weโ€™ll want to create a protected keystore for use by the account. There are a variety of ways to do this, but Iโ€™ll demonstrate with openssl.

The first step is to combine the public and private keys together into one PEM file:

image

Then weโ€™ll use openssl to create a X.509 certificate:

image

And then weโ€™ll combine the certificate and the private key in the PEM file to create a PKCS 12 (.p12) file format:

image

Upload the .p12 file to the Accountโ€™s โ€œKey Storeโ€ field, also providing the password you used to protect it. You can use the suggest bubble on the โ€œKey Aliasโ€ field to refer to your entry by name (this will be the "kid" value in the JWT Header).

image

Decoding the Generated JWT

The output of the JWT Generate Snap will be the JWT token under the "access_token" field (donโ€™t confuse this with a DocuSign API access token, that comes later):

image

You can copy this value and use jwt.io to see the decoded values:

image

Exchanging the JWT for a DocuSign API Access Token

Alright, itโ€™s finally time to actually get an access token from DocuSign and start using their API!

We are going to use the REST POST Snap to send a form-encoded request to the DocuSign token endpoint:

image

The changes are minimal - the HTTP Entity is "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion="+$access_token (using the JWT you just created) and you need to set the appropriate Content-Type HTTP Header value of application/x-www-form-urlencoded.

The Service URL is https://account-d.docusign.com/oauth/token and note that this needs to match the Audience value you used earlier (it is also the Demo environment value - Production is different; see DocuSignโ€™s docs linked above).

If everything has been configured correctly, youโ€™ll get an API access token:

image

And like in the first post, you can use this token with the REST Snap Pack (e.g. GET), albeit this time setting it directly via the Authorization HTTP Header:

image

and it should return data successfully:

image

In the end, this pipeline looked simply like this:

image

Cheers!

1 REPLY 1

Majid
New Contributor III

Thank You Robin. This Post has been helpful and we were able to successfully integrate with DocuSign using the steps provided.