We have a .NET service that needs to connect with Jira to create, update and read issues. It would be easy if we could use a username & password for authentication, but for this integration we need to implement a Private Key. All requests have to be signed with OAuth.

There are some resources online showing how to do this with C#, but none of them worked for us. After some fiddling around we came up with some code that works.

Packages

We use the following packages (make sure you have them installed):

Install-Package Atlassian.SDK»
Install-Package OpenSSL.PrivateKeyDecoder»

Getting the consumer secret

Jira uses OAuth version 1. There are 4 elements involved:

  • Access Token
  • Access Token Secret
  • Consumer Key
  • Consumer Secret

Three of these you already have, but the Consumer Secret needs to be generated out of the Private Key. Your key looks like this:

----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC0PIZ3R2ZPJuH0
lYJZShidrd7kwQtKUPR70ZwRzdchcII1lM98B7i9cSFUNzb511K9Bp9fMfAVwZ+U
HOiKTaZv8wi4XXLzjjJageUKHmFKOztRjeJB33bUspj+zlFRg1EkZSDTVraDz6iv
imj5tz1/1VL2/R81CCREFqKa0k2eEohQLecEeIMz7WITzLmbqTwULiLJZs028Hyb
eIoQVnbYE4YhIGGT50VWlEa4kXbh7Sof8gk6JnS1rP29raeNgr61tOXaO0/g141/
U7RleapyohfooLhNEiTEO3rd48wszrWGF4vWuRmTCOFW8cM6qLKb6EP3fCD0jLcJ
EKbgojghAgMBAAECggEAD4V41P577owRgGUnDQvG/pPnHTm3VbE5ZLetN5FLmgXH
iNgQXYTdYXRueNiqbi30t5zsOPVNe39+/8Z/i3gwFvWjMMayFrcOWgypTfZGIu+N
O7LleGPHUX4x6RuZFX/NYJN+61mignZtzJ7gTG+ofFZBfKNZaSaS157qu5Ip0gIZ
d9w4I2Q3eJBKoqHq/1NE7KTHv7KxKBYvsMqQLlkVrZItTj5EC/ffJ28EbSYR6hIY
GRJ1bM5ycvc2t0TIJh0d1VPMpazwFmF3M6eIdnBEluBjtq7C3AqcZwfOtnvQi4f7
igiObRExtgqEF+jZyUlSL43gcT29EEpAOT6YeMskmwKBgQD6MTR2mqHnzIkNya0o
tPDElt2IH0ZaYY0Whcg16c61MKbxAVvfyt4UaRwm/1Xh+97qyI/QmJR6+Zf8ijQj
1rlDW6krEZM33GTQeD/iQw8uxXAahN0LBzaxkMv8bmdKLV+zgk4ubdtTtHPIeQtl
yAQ/fwp+3chZzR9NG6aN7BuK5wKBgQC4a5mtosVPCVPetOtSR4M90bYpK04UOWW8
wIuoMplTDbVQaJDh76+IdQR+k8vhs1noE+bUPyV+r8RmkI1LfQheBaBR8dLmqN2Q
L0FLtL/g0EQ4WntjLhFRD8nr70MYyVV7iA6u5kOXgGvjxQXZv6Rzb5lFIvpCi4Nv
YNbYEPYLtwKBgQCF2Q8dKIrXjKgB1VQrA+oO8jsgGMM1lRy64OWEWko4ywd0xepV
5p06xCTIhC95D5tpddTins5IoAD8nR9Z0QUaEQ6GuQdOijzw/nQG4yNbPUtFFLGA
teI/ypwmtxXRLEcXrO2QjzsYI+ERbhh34jLLmXaO+q21xTQqt1E6egceHwKBgGtw
3I5pRvQ95evYkURVP2OzmqGvhgSIT/pAXty15deaI+jdkpLelfA05FJt/pjWaWmo
tpEu3MRK2Gw8iOTSyh4kvvsenJUfCj3nGe5mNmdeTnBaXoowm4wTW7sloHx/R1r5
sDw7EGPiQHjpHvh2CvPpr2y07QH5z7ACxggJEZ9PAoGBALdbNqiHJycRVizc1Qrn
A6sFLovEXsn9371w2l+SLrUeFlL73v0DKXWcRLz3RLcDGdq8gKMjIMCkdmX9lFPr
pK/+p6NMlLef8aSOxsDv4rxKNcSwcsfJ90tc4ex0JRN41zaAOcO7bOKUasNURgRS
Ki5GFciH4qixEtN7TxMi8lRF
-----END PRIVATE KEY-----

Note: the breaks are just for formatting and can be excluded, but the headers (begin and end) should be included with your key value!

Let’s use the PrivateKeyDecoder of the OpenSSL package to decode the key and convert it into a consumerSecret

var privateKey = ""; // <- get your private key in here
var decoder = new OpenSSL.PrivateKeyDecoder.OpenSSLPrivateKeyDecoder();
var keyInfo = decoder.Decode(privateKey);
var consumerSecret = OpenSSL.PrivateKeyDecoder.RSAExtensions.ToXmlString(keyInfo, true);

Make the HTTP Client behave

The Jira client uses a RestSharp HTTP client to connect to the API. We need to modify that HTTP client to include an OAuth authenticator that uses the consumerSecret:

var client = Atlassian.Jira.Jira.CreateRestClient(jiraUrl);
client.RestClient.RestSharpClient.Authenticator = 
    RestSharp.Authenticators.OAuth1Authenticator.ForProtectedResource(
        consumerKey,        // <- fill it
        consumerSecret,     // <- generated
        accessToken,        // <- fill it
        accessTokenSecret,  // <- fill it
        RestSharp.Authenticators.OAuth.OAuthSignatureMethod.RsaSha1
    );

This client will now sign all of our requests. This solution should work with both .NET Framework and .NET Core.