【问题标题】:Docusign - "Error":"Invalid_request" Response When Requesting JWT Access TokenDocusign - 请求 JWT 访问令牌时的“错误”:“无效请求”响应
【发布时间】:2021-04-06 14:58:52
【问题描述】:

我正在使用 REST API,并且正在 C# 中从 Docusign 的 Postman 集合中实现“02 JWT 访问令牌”。我生成了 RSA 密钥对,标头和正文已准备好 (Header.Body) 为 Base64 格式。

long d1 = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
long d2 = DateTimeOffset.UtcNow.ToUnixTimeSeconds() + 1800;

string header = "{  \"alg\": \"RS256\",  \"typ\": \"JWT\"}";
string body = "{  \"iss\": \"" + integrationKey + "\",  \"sub\": \"" + apiUsername + "\",  \"aud\": \"" + environment + "\",  \"iat\": " + d1.ToString() + ",  \"exp\": " + d2.ToString() + ",  \"scope\": \"signature impersonation\"}";
string base64 = Base64Encode(header) + "." + Base64Encode(body);

Base64 编码器:

public string Base64Encode(string plainText)
{
    var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
    return System.Convert.ToBase64String(plainTextBytes);
}

我已使用以下代码进行签名,它似乎可以工作:

private string Sign(string message, string privateKey)
{
    try
    {
        byte[] r = Encoding.UTF8.GetBytes(message);

        StringReader strReader = new StringReader(privateKey);
        PemReader pemReader = new PemReader(strReader);
        AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)pemReader.ReadObject();
        RsaKeyParameters privateRSAKey = (RsaKeyParameters)keyPair.Private;


        ISigner sig = SignerUtilities.GetSigner("SHA256withRSA");
        sig.Init(true, privateRSAKey);
        sig.BlockUpdate(r, 0, r.Length);
        byte[] signedBytes = sig.GenerateSignature();

        return Convert.ToBase64String(signedBytes);

    }
    catch (Exception ex)
    {
        throw ex;
    }
}

然后我提交。断言(下面代码中的标记)格式为“Header.Body.Signature”:

using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://" + environment + "/oauth/token"))
        {
            var contentList = new List<string>();
            contentList.Add($"assertion={token}");
            contentList.Add($"grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer");

            request.Content = new StringContent(string.Join("&", contentList));
            request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");
            request.Headers.Authorization = new AuthenticationHeaderValue("Basic", encodedKeys);

            HttpResponseMessage response = null;

            try
            {
                using (HttpClient client = new HttpClient())
                {
                    response = await client.SendAsync(request);
                }

                if (response != null)
                    return await response.Content.ReadAsStringAsync();
                else
                    throw new Exception();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error: " + ex.Message);
                throw ex;
            }
        }

我在提交时遇到错误,{"error":"Invalid_request"}。

更多信息: https://developers.docusign.com/platform/auth/jwt/jwt-get-token/

【问题讨论】:

    标签: c# docusignapi bouncycastle


    【解决方案1】:

    JWT 断言似乎是从头开始制作的,这可能会导致很多问题。DocuSign 建议使用库来制作 JWT 断言。 此链接使用我们的 SDK 显示此过程: https://github.com/docusign/code-examples-csharp/blob/06c46b235c094be1346e4ddca692aa9b72a82456/launcher-csharp/Common/JWTAuth.cs

    对于这种情况,您可能需要尝试一种方法:public static (string, string, string) AuthenticateWithJWT()。这将使用 .NET Core。 或者您可以使用我们 SDK 上的方法:RequestJWTUserToken。 其中之一可能会解决它,请考虑应安装并设置 DocuSign 代码示例启动器以使用此方法。

    【讨论】:

      【解决方案2】:

      DocuSign OAuth JWT 授权使用具有 RS256 算法的 JWT 令牌。

      RS256 是指带有 SHA-256 密钥的 RSA 签名算法。

      How to create an RS256 JWT 向您展示如何做到这一点。情况很复杂。我建议你使用库函数!

      对于大多数 DocuSign API 方法,使用我们 SDK 的 RequestJWTUserToken 方法之一。

      【讨论】:

        【解决方案3】:

        问题在于 Base64 编码。它应该是 Base64Url 编码,格式略有不同。值得庆幸的是,只需添加 '.Replace("=", "").Replace("/", "_").Replace("+", "-");'

        public string Base64Encode(string plainText)
            {
                var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
                return System.Convert.ToBase64String(plainTextBytes).Replace("=", "").Replace("/", "_").Replace("+", "-");
            }
        
        
            private string Sign(string message, string privateKey)
            {
                try
                {
                    byte[] r = Encoding.UTF8.GetBytes(message);
        
                    StringReader strReader = new StringReader(privateKey);
                    PemReader pemReader = new PemReader(strReader);
                    AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)pemReader.ReadObject();
                    RsaKeyParameters privateRSAKey = (RsaKeyParameters)keyPair.Private;
        
                    ISigner sig = SignerUtilities.GetSigner("SHA256withRSA");
                    sig.Init(true, privateRSAKey);
                    sig.BlockUpdate(r, 0, r.Length);
        
                    return Convert.ToBase64String(sig.GenerateSignature()).Replace("=", "").Replace("/", "_").Replace("+", "-"); 
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        

        【讨论】:

          猜你喜欢
          • 2020-11-01
          • 2021-01-11
          • 1970-01-01
          • 2021-01-17
          • 1970-01-01
          • 2020-01-11
          • 1970-01-01
          • 2021-02-12
          • 1970-01-01
          相关资源
          最近更新 更多