【问题标题】:Docusign PHP getting "invalid_grant: unsupported_grant_type" when trying to get token (JWT auth)Docusign PHP 在尝试获取令牌时获取“invalid_grant:unsupported_grant_type”(JWT auth)
【发布时间】:2021-01-29 22:34:30
【问题描述】:

我正在尝试使用 Docusign JWT 身份验证获取访问令牌,但我总是得到:

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

我仔细检查了所有数据(集成密钥、api 用户名等),它们都很好。 我遵循了 Docusign 指南中的所有步骤。

我不能 100% 确定的唯一部分是当我生成 JWT 令牌的签名时。 文档说:

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.

这就是我生成签名的方式:

$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;

正确吗? 如果不是,并且由于 JWT::encode 需要一个数组作为第一个参数,我应该如何使其工作?

这就是我请求访问令牌的方式:

        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
            ]
        );

谢谢!

【问题讨论】:

  • 整个 JWT 令牌在编码时都在签名变量中,有标头、正文(base64)和签名。
  • 你看github.com/docusign/code-examples-php了吗?它正在使用 PHP SDK 使用 JWT 流获取令牌等等......

标签: php jwt docusignapi


【解决方案1】:

我在使用 Laravel 6 的应用程序中遇到了同样的问题,我设法解决了如下问题:

// 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>';

【讨论】:

    【解决方案2】:

    显然 Firebase JWT 编码方法没有以正确的方式编码字符串。

    我用过这个:

    $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"
            );
    

    它成功了。

    确保在请求同意和请求 jwt 令牌时使用相同的范围。

    感谢大家的帮助。

    【讨论】:

      【解决方案3】:

      创建正确的 JWT 令牌很困难。我建议您使用 PHP SDK 中的 requestJWTUserToken 或查看其 source 以了解它是如何发出 OAuth 请求的。

      【讨论】:

        猜你喜欢
        • 2021-01-07
        • 2021-07-15
        • 2018-12-04
        • 2016-07-18
        • 1970-01-01
        • 2021-01-17
        • 2018-03-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多