Запрос токена доступа DocuSign JWT - PullRequest
0 голосов
/ 12 июля 2020
  • Я пытаюсь получить токен доступа в среде песочницы.
  • У меня есть приложение VB. NET и ссылка на DocuSign.eSign.dll
  • Я изучил docusign C# примеров кода и не удалось запустить их в vb. net

Это первый подход, который я пробовал:

Dim ac As ApiClient = New ApiClient()
Dim privateKeyStream() As Byte = Convert.FromBase64String(PrivateKey)
Dim tokenInfo As OAuth.OAuthToken = ac.RequestJWTUserToken("INTEGRATION_ID", "ACCOUNT_ID", "https://account-d.docusign.com/oauth/token", privateKeyStream, 1)

Это привело к следующей ошибке:

System.Exception
  HResult=0x80131500
  Message=Unexpected PEM type
  Source=DocuSign.eSign
  StackTrace:
   at DocuSign.eSign.Client.ApiClient.CreateRSAKeyFromPem(String key) ...

Второй подход использовал следующие коды:

Dim privateKeyStream As Stream = New FileStream("D:\docusign.pem", FileMode.Open)
'Dim privateKeyStream As Stream = New MemoryStream(Encoding.UTF8.GetBytes(PK))
Using SR = New StreamReader(privateKeyStream)
    If Not SR Is Nothing And SR.Peek() > 0 Then
        Dim privateKeyBytes() As Byte = ReadAsBytes(privateKeyStream)
        'Dim privateKeyBytes() As Byte = StreamToByteArray(privateKeyStream)
        'Dim privateKeyBytes() As Byte = Convert.FromBase64String(PrivateKey)
        'Dim privateKeyBytes() As Byte = Encoding.UTF8.GetBytes(PrivateKey)

        Dim privateKeyS As String = Encoding.UTF8.GetString(privateKeyBytes)

        Dim handler As JwtSecurityTokenHandler = New JwtSecurityTokenHandler()
        handler.SetDefaultTimesOnTokenCreation = False

        Dim descriptor As SecurityTokenDescriptor = New SecurityTokenDescriptor()
        descriptor.Expires = DateTime.UtcNow.AddHours(1)
        descriptor.IssuedAt = DateTime.UtcNow

        Dim scopes As List(Of String) = New List(Of String)
        scopes.Add(OAuth.Scope_SIGNATURE)

        descriptor.Subject = New ClaimsIdentity()
        descriptor.Subject.AddClaim(New Claim("scope", String.Join(" ", scopes)))
        descriptor.Subject.AddClaim(New Claim("aud", "account-d.docusign.com"))
        descriptor.Subject.AddClaim(New Claim("iss", "INTEGRATION_ID"))
        descriptor.Subject.AddClaim(New Claim("sub", "ACCOUNT_ID"))

        Dim RSA = CreateRSAKeyFromPem(privateKeyS)
        Dim rsaKey As RsaSecurityKey = New RsaSecurityKey(RSA)
        descriptor.SigningCredentials = New SigningCredentials(rsaKey, SecurityAlgorithms.RsaSha256Signature)


        Dim Token = handler.CreateToken(descriptor)
        Dim jwtToken As String = handler.WriteToken(Token)

        Dim baseUri As String = String.Format("https://{0}/", basePath)
        Dim RestClient As RestClient = New RestClient(baseUri)
        RestClient.Timeout = 10000

        Dim contentType As String = "application/x-www-form-urlencoded"

        Dim formParams As New Dictionary(Of String, String)
        formParams.Add("grant_type", OAuth.Grant_Type_JWT)
        formParams.Add("assertion", jwtToken)

        Dim queryParams As New Dictionary(Of String, String)

        Dim headerParams As New Dictionary(Of String, String)
        headerParams.Add("Content-Type", "application/x-www-form-urlencoded")
        headerParams.Add("Cache-Control", "no-store")
        headerParams.Add("Pragma", "no-cache")

        Dim fileParams As New Dictionary(Of String, FileParameter)
        Dim pathParams As New Dictionary(Of String, String)

        Dim postBody As Object = Nothing

        Dim request As RestRequest = PrepareRequest(basePath, Method.POST, queryParams, postBody, headerParams, formParams, fileParams, pathParams, contentType)

        Dim response As IRestResponse = RestClient.Execute(request)

        If (response.StatusCode >= HttpStatusCode.OK And response.StatusCode < HttpStatusCode.BadRequest) Then
            Dim tokenInfo As OAuth.OAuthToken = JsonConvert.DeserializeObject(Of OAuth.OAuthToken)(response.Content)
            Return tokenInfo.access_token
        Else
            Throw New ApiException(response.StatusCode, "Error while requesting server, received a non successful HTTP code " & response.ResponseStatus & " with response Body: " + response.Content, response.Content)
        End If
    Else
        Throw New ApiException(400, "Private key stream not supplied or is invalid!")
    End If
End Using

Это привело к тому же результату, что и первое решение:

System.Exception
  HResult=0x80131500
  Message=Unexpected PEM type
  Source=PropertyServer
  StackTrace:
   at PropertyServer.classDocusign.CreateRSAKeyFromPem(String key) in...

И мой третий подход был примерно так:

Dim ar1 As JObject = New JObject()
ar1.Add("typ", "JWT")
ar1.Add("alg", "RS256")

Dim header As String = Base64UrlEncoder.Encode(ar1.ToString)

Dim ar2 As JObject = New JObject()
ar2.Add("iss", "INTEGRATION_ID")
ar2.Add("sub", "ACCOUNT_ID")
ar2.Add("iat", DateDiff(DateInterval.Second, New Date(1970, 1, 1), Now))
ar2.Add("exp:", DateDiff(DateInterval.Second, New Date(1970, 1, 1), DateAdd(DateInterval.Hour, 1, Now)))
ar2.Add("aud:", "account-d.docusign.com")
ar2.Add("scope", "signature impersonation")

Dim body As String = Base64UrlEncoder.Encode(ar2.ToString)

Dim stringToSign As String = header & "." & body

Dim bytesToSign() As Byte = Encoding.UTF8.GetBytes(stringToSign)

'Dim data() As Byte = Encoding.UTF8.GetBytes(PrivateKey)
'Dim b64 As String = System.Text.Encoding.UTF8.GetString(data)

Dim keyBytes() As Byte = Convert.FromBase64String(PrivateKey)

Dim privKeyObj = Asn1Object.FromByteArray(keyBytes)
Dim privStruct = RsaPrivateKeyStructure.GetInstance(privKeyObj)

Dim sig As ISigner = SignerUtilities.GetSigner("SHA256withRSA")

sig.Init(True, New RsaKeyParameters(True, privStruct.Modulus, privStruct.PrivateExponent))

sig.BlockUpdate(bytesToSign, 0, bytesToSign.Length)
Dim signature() As Byte = sig.GenerateSignature()

Dim sign As String = Base64UrlEncoder.Encode(signature)

Return header & "." & body & "." & sign

При моей попытке 3rt я смог получить результат, однако, когда я пытаюсь опубликовать это как часть утверждения запроса в Postman, он возвращает следующее:

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

Я потратил часы на решение проблемы, но безуспешно, заранее спасибо.

Примечание: они импортированы

Imports System.IO
Imports System.Net
Imports System.Text
Imports DocuSign.eSign.Api
Imports DocuSign.eSign.Client
Imports DocuSign.eSign.Client.Auth
Imports DocuSign.eSign.Model
Imports Microsoft.Azure.KeyVault.Cryptography.Algorithms
Imports Newtonsoft.Json.Linq
Imports System.Security.Cryptography
Imports System
Imports System.Collections.Generic
Imports Org.BouncyCastle.Crypto
Imports Org.BouncyCastle.Crypto.Parameters
Imports Org.BouncyCastle.Security
Imports Newtonsoft.Json
Imports Org.BouncyCastle.Asn1
Imports Org.BouncyCastle.Asn1.Pkcs
Imports RestSharp
Imports System.IdentityModel.Tokens.Jwt
Imports Microsoft.IdentityModel.Tokens
Imports System.Security.Claims
Imports Org.BouncyCastle.OpenSsl
Imports System.Security.Cryptography.X509Certificates

Ответы [ 2 ]

1 голос
/ 13 июля 2020

Наконец-то он заработал с помощью Ларри К. Я не уверен, что я снова пропустил после вчерашнего ответа Ларри, но теперь я могу получить токен доступа со следующими кодами: (Кстати, установка iat и exp на UT C или местное время не имеет значения)

... Дополнительно объявление PriveKey выглядит следующим образом:

Dim PrivateKey As String = "MIIEowIBAAKCAQEAjtTe7UUP/CBI9s...BLABLABLA...JfwZ2hHqFPXA9ecbhc0".Replace(vbLf, "").Replace(vbCr, "")

Dim ar1 As JObject = New JObject()
ar1.Add("typ", "JWT")
ar1.Add("alg", "RS256")

Dim header As String = Base64UrlEncoder.Encode(ar1.ToString)

Dim ar2 As JObject = New JObject()
ar2.Add("iss", "INTEGRATION_ID")
ar2.Add("sub", "GUID_VERSION_OF_USER_ID")
ar2.Add("iat", DateDiff(DateInterval.Second, New Date(1970, 1, 1), Now().ToUniversalTime))
ar2.Add("exp", DateDiff(DateInterval.Second, New Date(1970, 1, 1), DateAdd(DateInterval.Hour, 1, Now().ToUniversalTime)))
ar2.Add("aud", "account-d.docusign.com")
ar2.Add("scope", "signature")

Dim body As String = Base64UrlEncoder.Encode(ar2.ToString)

Dim stringToSign As String = header & "." & body

Dim bytesToSign() As Byte = Encoding.UTF8.GetBytes(stringToSign)

Dim keyBytes() As Byte = Convert.FromBase64String(PrivateKey)

Dim privKeyObj = Asn1Object.FromByteArray(keyBytes)
Dim privStruct = RsaPrivateKeyStructure.GetInstance(privKeyObj)

Dim sig As ISigner = SignerUtilities.GetSigner("SHA256withRSA")

sig.Init(True, New RsaKeyParameters(True, privStruct.Modulus, privStruct.PrivateExponent))

sig.BlockUpdate(bytesToSign, 0, bytesToSign.Length)
Dim signature() As Byte = sig.GenerateSignature()

Dim sign As String = Base64UrlEncoder.Encode(signature)

Return header & "." & body & "." & sign

Большое спасибо, Ларри К!

0 голосов
/ 12 июля 2020

Похоже, ваш третий подход был лучшим. Тем более, что ваши претензии не соответствовали действительности. Они должны быть:

ar2.Add("iss", "INTEGRATION_ID")
# sub is NOT the account id
ar2.Add("sub", "GUID_VERSION_OF_USER_ID")
# Check that your date is correct
ar2.Add("iat", DateDiff(DateInterval.Second, New Date(1970, 1, 1), Now))
# should be exp, not exp:
ar2.Add("exp", DateDiff(DateInterval.Second, New Date(1970, 1, 1), 
DateAdd(DateInterval.Hour, 1, Now)))
# should be "aud", not "aud:"
ar2.Add("aud", "account-d.docusign.com")
# only need signature. impersonation is automatically implied.
ar2.Add("scope", "signature")

Мне не удалось найти ничего очень полезного для создания RS256 JWT через VB.

Эта компания предлагает что-то за плату, но я у меня нет опыта с этим.

Microsoft, по-видимому, теперь позволяет создавать RS256 JWT, но у меня нет полезного примера, который я мог бы найти. Документы .

Пожалуйста, отправьте ответ на свой вопрос, как только вы его разберетесь. Спасибо !!

Добавлено

Я предлагаю распечатать JWT, созданный вашим программным обеспечением, а затем использовать инструмент или процедуру проверки, чтобы убедиться, что JWT, создаваемый вашим программным обеспечением, является тем, что вы ожидается.

К сожалению, многие онлайн-верификаторы просто декодируют утверждения. Вам необходимо дополнительно проверить правильность подписи. (Используйте ключ publi c из пары RSA, которую вам предоставляет DocuSign.)

...