DocuSign Authorization Code Grant flow returns invalid_grant error
Asked Answered
G

7

8

The DocuSign documentation goes through an easy to follow authorization flow for code grant. I'm able to get the "code" from the initial GET request to /oath/auth but getting the tokens gives me an error of "invalid_grant" when I try in postman. I've followed the steps and have a request that looks like this using account-d.docusign.com for host:

POST /oauth/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic MjMwNTQ2YTctOWM1NS00MGFkLThmYmYtYWYyMDVkNTQ5NGFkOjMwODc1NTVlLTBhMWMtNGFhOC1iMzI2LTY4MmM3YmYyNzZlOQ==

grant_type=authorization_code&code=ey2dj3nd.AAAA39djasd3.dkn4449d21d

Two other members of my team have also tried with their developer accounts and all are getting invalid_grant errors. Is this no longer supported or are there common errors associated with this error that we might be able to investigate?

Grassquit answered 5/10, 2016 at 18:33 Comment(0)
H
10

Re-check all of your values.

I was also getting the same invalid_grant response and could not figure out why at first. It turns out that I had a typo in the Content-Type header. I was using application/x-www-form-urlencode instead of application/x-www-form-urlencoded.

You may not be, but if you are submitting the exact Authorization Header as you've posted it here in your question (MjMwNTQ2YTctOWM1NS00MGFkLThmYmYtYWYyMDVkNTQ5NGFkOjMwODc1NTVlLTBhMWMtNGFhOC1iMzI2LTY4MmM3YmYyNzZlOQ==) it will fail with that message.

That is the base64 value for the sample integration key and sample secret key provided in their documentation. If you decode that string with an online base64decoder it will result in 230546a7-9c55-40ad-8fbf-af205d5494ad:3087555e-0a1c-4aa8-b326-682c7bf276e9. This is the same sample integration key and secret in the documentation.

Check the Authorization header you are submitting by encoding your integration key and secret (integrationKey:secret) using this online base64encoder. This will make sure the issue isn't with your base64 encoding of your integration key and secret. Once you have that value make sure your Authorization uses the word Basic before the value you got from this website. (Basic base64stringFromOnlineEncoder)

Check that the code your are submitting in the body of the post is not the sample code from their documentation. ey2dj3nd.AAAA39djasd3.dkn4449d21d is the sample code from their documentation. You may just be using that in your question as a placeholder but if you are submitting any of those values it will return invalid_grant. Make sure that the body of your post does not have any leading or trailing spaces.

  1. Have the correct Content-Type set application/x-www-form-urlencoded
  2. Have the correct Authorization header set Basic base64EncodedIntegrationKey:Secret
  3. Have the correct body using the valid code received from the GET request to /oauth/auth with no leading or trailing spaces, making sure you're not using the values from your question.

If you are still having trouble and you are not doing a user application but are doing a service integration you can use Legacy Authentication to get your oAuth2 token.

Alternative Method using Legacy Authentication for Service Integrations

This method does not use a grant code. You pass in the integration key, username and password into the X-DocuSign-Authentication header in JSON format.

Demo Server: demo.docusign.net

Production Server: www.docusign.net API

Version: v2

POST https://{server}/restapi/{apiVersion}/oauth2/token
Content-Type: application/x-www-form-urlencoded
X-DocuSign-Authentication: {"IntegratorKey":"your_integrator_key","Password":"docusign_account_password","Username":"docusign_account_username"}

grant_type=password&client_id=your_integrator_key&username=docusign_account_username&password=docusign_account_password&scope=api

If you are building a user application that requires the user enter their docusign credentials to generate the token, this alternative will not work for you.

Herron answered 6/10, 2016 at 6:42 Comment(4)
Me and my 2 other teammates have double checked our values. We're not using the examples from the document - we're using our own generated integrator key and secret key from our developer accounts. Legacy Authentication is not an option for us.Grassquit
In that case, you haven't posted enough of your code to provide you with help. Yes it is supported, and I have provided you with common errors to check for, as you have asked for.Herron
integrationKey:secret - it'd be nice if the documentation said that!Bohannon
What if in my flow, I don't want to use the auth GET flow for the user to grant access? In that case my only option is the legacy Authentication API? For example in a customer portal where the customer is logging in, we want to the customer to sign the contract in place, there is no DocuSign user to login!Disused
J
4

For anyone who is facing this error, I'd like to point out this note in the documentation:

Note: The obtained authorization code is only viable for 2 minutes. If more then two minutes pass between obtaining the authorization code and attempting to exchange it for an access token, the operation will fail.

I was struggling with the same error until I spotted the note and sped up my typing to meet the 2 minutes.

Hope it helps someone else.

Jezabella answered 16/5, 2019 at 21:31 Comment(2)
Hi @Jezabella You are correct. But if the authorization code expires for every 2 minutes do i need to generate authorization code for every two minutes manually by constructing url with redirect url. Do you have any idea on how to generate authorization code programatically.Crigger
No @rameshm, I only did it once and never tried it in code.Jezabella
M
1

In my case the problem was related to having set a wrong value for Content-Type header, namely "application/x-www-form-URIencoded" instead of the correct "application/x-www-form-urlencoded". Note though that in my case the problem was not a "typo" but an excessive trust in DocuSign documentation.

Indeed the wrong Content-Type is, at the time of writing, suggested directly into the documentation page where they describe the Authorization Code Grant workflow, see the image below for the relevant part.

enter image description here

Hopefully they will fix the documentation soon but for the time being be careful not to blindly copy & paste the code from their examples without thinking, as I initially did.

Malnutrition answered 3/1, 2019 at 12:39 Comment(0)
P
1

anyone have an idea what is wrong here I am getting a BadRequest with the following

{"error":"invalid_grant","error_description":"unauthorized_client"}
var client = new RestClient(ESIGNURL);
            var request = new RestRequest("/oauth/token");
            request.Method = Method.POST;
            request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
            request.AddHeader("Authorization", "Basic " + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(integrationkey+ ":" + secret)));

            string body = "grant_type=authorization_code&code=" + code;
            request.Parameters.Clear();
            request.AddParameter("application/x-www-form-urlencoded", body, ParameterType.RequestBody);

            var response = client.Execute(request);
Potherb answered 20/6, 2020 at 17:24 Comment(0)
N
0

I was getting this error as well. What I realized is I was appending the state at the end of the code before passing it to the oauth token endpoint.

This snippet is from Docusign explaining what are some other reasons for getting that error.

Invalid-error explanation

Northern answered 17/3, 2021 at 19:48 Comment(0)
R
0

I just spent a day doing this (in NodeJS). I'll add a couple of things to the answers from before. First, I had to put:

"Content-Type": "application/x-www-form-urlencoded"

in the header. Otherwise it gave me the message:

{
     "error": "invalid_grant",
     "error_description": "unsupported_grant_type"
}

Second, the base64 encoding:

I used this in NodeJS and it worked

const integration_key = process.env.INTEGRATION_KEY;
const secret_key = process.env.SECRET_KEY;
const authinfo =
     integration_key.toString("utf8") + ":" + secret_key.toString("utf8");
const buff2 = Buffer(authinfo, "utf8").toString("base64");

If you use "base64url" it dosen't work because it strips the == off of the end of the string. The = symbol is used as padding and apparently it's needed. You see a similar difference on this site https://www.base64encode.org/ when you toggle the url safe encoding option. If you don't have the padding on the end of your base64 encoded string (or if it's generally incorrect) you get this message:

{
     "error": "invalid_grant",
     "error_description": "unauthorized_client"
}

Finally, if you're using Postman (I'm using DocuSign's Postman Collection) remember to reset and save the codeFromUrl variable after you update it. Otherwise it doesn't update and you get the message:

{
    "error": "invalid_grant",
    "error_description": "expired_client_token"
}

This means the old URL code has expired and your new one didn't save.

Runabout answered 19/1, 2023 at 21:19 Comment(0)
C
0

For folks trying the DocuSign - 01 Authorize Code Grant Access Token from Postman, If you have configured the codeFromUrl in your postman using URL - https://www.example.com/callback as the Redirect URIs, then while using it consecuievely it gives invalid_grant error. You can use another site such as webhook.site which dynamically generates a unique URL. But you have to always register the webhook URL in docusign under allowed Redirect URIs everytime you generate a different webhook.site url.

Cotillion answered 26/8, 2023 at 10:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.