【问题标题】:Exchange a jwt for an access token returns invalid_grant error用 jwt 交换访问令牌返回 invalid_grant 错误
【发布时间】:2018-11-03 02:44:37
【问题描述】:

我正在尝试为我的应用程序实施服务集成身份验证 - 管理员同意。以下是我创建 jwt 的方式:

class Program
{
    static void Main(string[] args)
    {
        #region Test

        string integratorKey = "integratorKey ";
        string userId = "userId ";
        string serverAddress = "serverAddress";
        string scope = "signature";
        string key = @"C:\Users\Tester\Desktop\privatekey.txt";

        // JWT Header
        // The header specfies the token type and the signature algorithm
        var jwtHeader = new JwtHeader
        {
            { "typ ", "JWT "},
            { "alg", "RS256"},
        };

        // JWT Body
        // The body specfies the account and user id granting consen
        var jwtPayload = new JwtPayload
        {
           { "iss ", integratorKey},
           { "sub", userId},
           { "iat", DateTimeOffset.UtcNow.ToUnixTimeSeconds()},
           { "exp", DateTimeOffset.UtcNow.AddHours(1).ToUnixTimeSeconds()},
           { "aud", serverAddress},
           { "scope", scope}
        };

        // JWT Signature
        // The body contains the result of signing the base64url-encoded header and body
        string pemKey = File.ReadAllText(key);
        var rsa = CreateRSAKeyFromPem(pemKey);
        RsaSecurityKey rsaKey = new RsaSecurityKey(rsa);

        var jwtSecurityToken = new JwtSecurityToken(jwtHeader, jwtPayload);
        jwtSecurityToken.SigningKey = rsaKey;

        // Token to String so you can use it in your client
        var jwtHandler = new JwtSecurityTokenHandler();
        var tokenString = jwtHandler.WriteToken(jwtSecurityToken);
        #endregion
    }

    public static RSA CreateRSAKeyFromPem(string key)
    {
        TextReader reader = new StringReader(key);
        PemReader pemReader = new PemReader(reader);

        object result = pemReader.ReadObject();

        if (result is AsymmetricCipherKeyPair)
        {
            AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)result;
            return DotNetUtilities.ToRSA((RsaPrivateCrtKeyParameters)keyPair.Private);
        }
        else if (result is RsaKeyParameters)
        {
            RsaKeyParameters keyParameters = (RsaKeyParameters)result;
            return DotNetUtilities.ToRSA(keyParameters);
        }

        throw new Exception("Unepxected PEM type");
    }
}

我已经在 jwt.io 上验证了此代码生成的令牌,一切看起来都不错。但是,当我尝试使用 Postman 将生成的 jwt 交换为访问代码时,我总是会得到“invalid_grant”,这是我在 postman 中提出请求的方式:

POST https://account-d.docusign.com/oauth/token
-Headers: Content-Type application/x-www-form-urlencoded

-Body: grant_type urn:ietf:params:oauth:grant-type:jwt-bearer assertion [Generated jwt]

我什至试过把

Headers: Authorization Basic b64encoded(integratorKey:secretKey) 

也一样,但仍然没有运气。

你能指出我在这里做错了什么吗?谢谢:)

【问题讨论】:

    标签: .net jwt docusignapi


    【解决方案1】:

    好的,我自己已经弄清楚出了什么问题,现在我可以在 Postman 中接收访问令牌。为了使这项工作,我改变了 3 件事:

    1. 当我从组织门户授权应用程序时,我已将应用程序分配给错误的集成商密钥,因此我需要将其更改为指向正确的密钥。

    2. 我在 C# SDK 中找到了生成 jwt 的代码,所以我用它来确保创​​建的 jwt 被 DocuSign 接受:

      static void Main(string[] args)
      {
          string integratorKey = "integratorKey ";
          string userId = "userId ";
          string serverAddress = "account-d.docusign.com";
          string scope = "signature impersonation";
          string privateKeyFilename = @"C:\Users\Tester\Desktop\privatekey.txt";
      
          JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
      
          SecurityTokenDescriptor descriptor = new SecurityTokenDescriptor()
          {
              IssuedAt = DateTime.UtcNow,
              Expires = DateTime.UtcNow.AddHours(1)
          };
      
          descriptor.Subject = new ClaimsIdentity();
          descriptor.Subject.AddClaim(new Claim("scope", scope));
          descriptor.Subject.AddClaim(new Claim("aud", serverAddress));
          descriptor.Subject.AddClaim(new Claim("iss", integratorKey));
      
          if (userId != null)
          {
              descriptor.Subject.AddClaim(new Claim("sub", userId));
          }
      
          if (privateKeyFilename != null)
          {
              string pemKey = File.ReadAllText(privateKeyFilename);
              var rsa = CreateRSAKeyFromPem(pemKey);
              RsaSecurityKey rsaKey = new RsaSecurityKey(rsa);
              descriptor.SigningCredentials = new SigningCredentials(rsaKey, SecurityAlgorithms.RsaSha256Signature, SecurityAlgorithms.HmacSha256Signature);
          }
      
          var token = handler.CreateToken(descriptor);
          string jwtToken = handler.WriteToken(token);
      }
      
      public static RSA CreateRSAKeyFromPem(string key)
      {
          TextReader reader = new StringReader(key);
          PemReader pemReader = new PemReader(reader);
      
          object result = pemReader.ReadObject();
      
          if (result is AsymmetricCipherKeyPair)
          {
              AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)result;
              return DotNetUtilities.ToRSA((RsaPrivateCrtKeyParameters)keyPair.Private);
          }
          else if (result is RsaKeyParameters)
          {
              RsaKeyParameters keyParameters = (RsaKeyParameters)result;
              return DotNetUtilities.ToRSA(keyParameters);
          }
      
          throw new Exception("Unepxected PEM type");
      }
      
    3. 更改 1 和 2 后,我仍然在 Postman 中出现错误:“consent_required”。原来我必须在我的积分器键中添加一个重定向 uri,然后导航到这个 url:

      SERVER/oauth/auth?response_type=code&scope=signature%20impersonation&client_id=CLIENT_ID&redirect_uri=https://docusign.com
      

    然后点击“授予”。

    希望这会有所帮助。

    【讨论】:

    • 如果您已经从组织管理面板正确授权了集成密钥,那么您应该不会收到许可要求错误。您是在演示中还是在生产中进行所有这些操作?您需要使用演示组织管理员在演示环境中授予同意。
    • @LarryK 我在我的演示环境中完成了所有这些工作,并且我使用了一个演示组织管理员来配置所有内容。您的意思是我的答案中的更改 3 根本没有必要吗?如果是这种情况,我该如何摆脱 Consent_required 错误?
    • @ixsl 非常感谢您。我花了一天半的时间试图使用 .Net Core 库,一旦我导入 Nuget Portable.BounyCastle v1.8.5.2 并按照您的示例代码,我就能够获得访问令牌。这是多么痛苦啊!!!
    猜你喜欢
    • 1970-01-01
    • 2017-03-06
    • 1970-01-01
    • 2019-11-09
    • 1970-01-01
    • 2016-11-06
    • 2017-12-17
    • 2021-03-30
    • 2020-03-26
    相关资源
    最近更新 更多