1
votes

I'm trying to get the access token using the Docusign JWT authentication, but I always get:

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

I double checked all the data (integration key, api username, etc) and they are fine. I followed all the steps in the Docusign guidelines.

The only part I'm not 100% sure is when I generate the signature of the JWT token. The documentation says:

The first two parts of the JWT are signed with your application's private key (using the RSA SHA-256 digital signature algorithm) as shown in the diagram.

This is how I'm generating the signature:

$header = [
            'typ' => 'JWT',
            'alg' => 'RS256'
        ];

$body = [
            'iss' => getenv('INTEGRATION_KEY'),
            'sub' => getenv('API_USERNAME'),
            'iat' => time(),
            'exp' => time() + 3600,
            'aud' => str_replace('https://', '', getenv('AUTH_URL')),
            'scope' => 'signature impersonation'
        ];
$signature = JWT::encode($body, file_get_contents(env('PRIVATE_KEY')), 'RS256');

$header = $this->base64url_encode(json_encode($header));
$body = $this->base64url_encode(json_encode($body));
$jwt = $header . '.' . $body . '.' . $signature;

Is that correct? If not, and since JWT::encode expects an array as first parameter, how should I do to make it work?

This is how I'm requesting the access token:

        return Http::withHeaders(
            [
                'Content-Type' => 'application/x-www-form-urlencoded'
            ]
        )->post(
            getenv('AUTH_URL') . '/oauth/token',
            [
                'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
                'assertion' => $jwt
            ]
        );

Thanks!

3
The whole JWT token is in the signature variable when you encode it, there is header, body ( base64) and signature.Al-Amin
Did you look at github.com/docusign/code-examples-php ? it is using the PHP SDK to get token using JWT flow and much more...Inbar Gazit

3 Answers

1
votes

Apparently Firebase JWT encode method doesn't encode a string in the right way.

I used this:

$header = $this->base64url_encode(json_encode($header));
$body = $this->base64url_encode(json_encode($body));

openssl_sign(
            $header.".".$body,
            $signature,
            file_get_contents(env('PRIVATE_KEY_PATH')),
            "sha256WithRSAEncryption"
        );

and it worked.

Make sure you're using the same scopes when requesting consent and requesting the jwt token.

Thanks everyone for the help.

0
votes

Creating a correct JWT token is hard. I suggest you either use the requestJWTUserToken from the PHP SDK or review its source to see how it makes the OAuth request.

0
votes

I was having the same problem in a application using Laravel 6 and I managed to solve it as follows:

// the Header will not be needed as it is automatically generated
$header = [
            'typ' => 'JWT',
            'alg' => 'RS256'
             ];
$body = [
            'iss' => getenv('INTEGRATION_KEY'),
            'sub' => getenv('API_USERNAME'),
            'iat' => time(),
            'exp' => time() + 3600,
            'aud' => str_replace('https://', ​​'', getenv('AUTH_URL')),
            'scope' =>'signature impersonation'
            ];
/**
* Note that when creating the JWT, only the $body is provided, 
* as the function already performs the necessary concatenations.
* in your code you put it like this: 
* $jwt = $header . '.' . $body . '.' . $signature;
* which generates a hash that cannot be validated,
*/

// create the JWT
$jwt = JWT::encode($body , $privateKey, 'RS256');

// make the request
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', getenv('AUTH_URL').'/oauth/token',['query' =>[
                                                                    'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
                                                                    'assertion'  => $jwt,
                                                                    ]
]);

echo '<pre>';
print_r($response);
echo '</pre>';