Authenticate against Jira REST APIs with OAuth 1.0a 1-Legged and .NET Core 2.x

OAuth specification 2.0 is out there since 2012 but 1.0a version is still widely used. Atlassian’s Jira is for example such case. You wouldn’t find anything about 1-Legged OAuth in the documentation but the fact is, by now, Jira is still supporting this flow but referring to this wrongly as 2-Legged OAuth. Sadly there aren’t lot of .Net Core libraries which implements OAuth’s 1-Legged, as described in the The OAuth Bible. I implemented this functionality into oauth-dotnetcore and will show you how this can be used to access Jira APIs.

Before the application can make a request against Jira you need to create RSA public / private key pair and register new application to allow 2-Legged OAuth and user impersonation through 2-Legged OAuth.

For the request self you will need to have Consumer Key and Consumer Secret which is actually a private key you generated before as a PEM format.

//Generate authorization header
OAuthRequest oauthRequest = OAuthRequest.ForProtectedResource("GET", "CONSUMER_KEY", "CONSUMER_SECRET", string.Empty, null, OAuthSignatureMethod.RsaSha1);
oauthRequest.RequestUrl = $"{baseUrl}{resource}?{queryLanguage}{searchOperator}{searchBy}{searchOperator}{searchValue}&user_id={userId}";
string authorizationHeader = oauthRequest.GetAuthorizationHeader();

//Make request
var httpClient = new HttpClient();
// authorizationHeader.Remove(0,6) => Remove "OAuth " from authorizationHeader to avoid to have invalid header
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("OAuth", authorizationHeader.Remove(0,6));
string result = await httpClient.GetStringAsync(oauthRequest.RequestUrl);
string formattedJson = JToken.Parse(result).ToString(Formatting.Indented);

What is really important here ist to set accessToken which is actually oauth_token in term of specification to string.Empty as required in the specification, otherwise the signature and the header will be wrong.

You can store the key pairs safe in Windows Certificate Store and use the private key to sign the request. Only thing you need is to convert the RSA private key to PEM format.

private static string GetCertificatePrivateKeyAsPem(string certificateThumbprint, StoreLocation storeLocation)
{
	var certificationStore = new X509Store(storeLocation);
	certificationStore.Open(OpenFlags.ReadOnly);
	X509Certificate2Collection certificates = certificationStore.Certificates.Find(X509FindType.FindByThumbprint, certificateThumbprint, false);

	if (certificates.Count > 0) 
	{ 
		var certificate = certificates[0];
		var rsaPrivateKey = certificate.GetRSAPrivateKey();
		var privateRsaKey = DotNetUtilities.GetRsaKeyPair(rsaPrivateKey).Private;
		var memoryStream = new MemoryStream();
		using (TextWriter textWriter = new StreamWriter(memoryStream))
		{
			var pemWriter = new PemWriter(textWriter);
			pemWriter.WriteObject(privateRsaKey);
			textWriter.Flush();
			return System.Text.Encoding.UTF8.GetString(memoryStream.ToArray(), 0, (int) memoryStream .Length);
		}
	 }
	return null;
}

GetRsaKeyPair and PemWriter in the code below are in the Portable.BouncyCastle NuGet package.

This is how request may looks like.

GET /jira/rest/api/2/search?jql=assignee=anton.kalcik&user_id=anton.kalcik HTTP/1.1

Authorization: OAuth oauth_consumer_key="CONSUMER_KEY",oauth_nonce="tqjfjtxsatwftw8p",oauth_signature="NTIzZGY4MzVmZWY5ZWVmYjdkMGMzNGRmZDQ5ODVmNDRmYTI4MGRiNGIwNjIwNTE0MzQxMmY3MTRiNTZmODE3NgpkMWRjOTkzMzc5NjdlNmExMDNiM2M5NWQ5ZmJmN2FiNTJjODBjNDRjZDAwOWQ2NTgwZTczZTZiN2UyNDQ5ODY1CjkwY2U1M2EwYTMwNjc2MDE3NTI1YjUyNDhiMDAwYmI0YWE5MjJhOWRmNjE1YTUyNzJkMTU2YzQyNWMzZDMyNjMKNzc5N2U3NDg4ZDQxMjIzZTA3NTBkNDkyNmVmYmQ3YjgyMjI0YWQ3ODY4OGE0OGI4ODE5MTI4YjNiZmY1YTg4Yg==",oauth_signature_method="RSA-SHA1",oauth_timestamp="1557962068",oauth_token="",oauth_version="1.0"

Host: example.com

About the Author Anton Kalcik

Most of the time, I assist people in the creation of valuable software. I’m a software engineer and entrepreneur specializing in .NET and Microsoft Azure. I offer Code Katas, Coding Dojos, workshops and talks about .NET, Microsoft Azure, DevOps, Agile Methodologies and Clean Code. I'm founder of CoderDojo Wien and president of digital.austria association.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.