Accessing Jira with OAuth Authenticated request

Based on Jira OAuth authentication using DotNetAuth, we can successfully get the access token, and are able to make an authenticated request. Now we plan to use Atlassian.SDK to access Jira with oAuth authentication, but currently Atlassian.SDK only supports basic authentication. So we will need to inject little bit extra code to make this happen.

Used packages

  • Atlassian.SDK 8.5.0
  • RestSharp 105.2.3
  • DotNetAuth Current DotNetAuth 1.0.5 nuget package uses old RestSharp version, and it doesn’t work with RestSharp 105.2.3, so small changes is required to align with this new RestSharp. The original DotNetAuth code can be downloaded from here.

Integrate DotNetAuth in RestSharp RestClient

A customized Authenticator is required to let RestClient know how to do the authenticate with DotNetAuth. This will be used when creating the RestClient.

public class OAuth1aAuthenticator : IAuthenticator
    {
        private OAuth1aProviderDefinition definition;
        private ApplicationCredentials credentials;
        private string access_token;
        private string access_token_secret;
        private string method;

        public OAuth1aAuthenticator(OAuth1aProviderDefinition oAuthDefinition, string consumerKey, string privateKey, 
                  string accessToken, string accessTokenSecret )
        {

            var consumerSecret = privateKey.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "").Replace("\r\n", "").Replace("\n", "");

            var keyInfo = opensslkey.DecodePrivateKeyInfo(Convert.FromBase64String(consumerSecret));

            var applicationCredentials = new ApplicationCredentials
            {
                ConsumerKey = consumerKey,
                ConsumerSecret = keyInfo.ToXmlString(true)
            };

            this.definition = oAuthDefinition;
            this.credentials = applicationCredentials;
            this.access_token = accessToken;
            this.access_token_secret = accessTokenSecret;
        }

        public void Authenticate(IRestClient client, IRestRequest request)
        {
            method = request.Method.ToString();

            string url = client.BuildUri(request)
                   .ToString();
            int queryStringStart = url.IndexOf('?');

            string leftPart = url;
            if (queryStringStart != -1)
            {
                leftPart = url.Substring(0, queryStringStart);
            }

            var contentType = request.Parameters.Where(x => x.ContentType == "application/x-www-form-urlencoded");

            ParameterSet parameterSet = ParameterSet.FromResponseBody(request.Resource);
            ParameterSet parameterSet2 = (contentType.Any()) ? ParameterSet.FromResponseBody(contentType.FirstOrDefault().Value.ToString()) : new ParameterSet();
            ParameterSet authorizationParameters = definition.GetAuthorizationParameters(credentials, access_token);

            string signature = definition.GetSignature(credentials.ConsumerSecret, access_token_secret, leftPart, method, new ParameterSet[]
            {
                authorizationParameters,
                parameterSet,
                parameterSet2
            });
            authorizationParameters.Add("oauth_signature", signature, null);
            string authorizationHeader = definition.GetAuthorizationHeader(authorizationParameters);

            request.AddHeader("Authorization", authorizationHeader);
            request.AddHeader("Accept", "application/json");
        }
    }

Once we have OAuth1aAuthenticator, we can create Rest Client with code below,

RestClient client = new RestClient(url)
            {
                Authenticator = new OAuth1aAuthenticator(new JIRAOAuth1aProvider(url), consumerKey, 
                                privateKey, accessToken, accessTokenSecret )
            };

Integrate oAuth in Atlassian.SDK

Create a new class (JiraOAuth) which inheritants from Jira.Jira. In it, a static method called CreateRestClient is created which accepts oAuth authentication details and will return Jira instance.

public class JiraOAuth : Jira.Jira
    {
        public JiraOAuth(ServiceLocator services, JiraCredentials credentials = null, JiraCache cache = null) : base(services, credentials, cache)
        {

        }

        public static Jira.Jira CreateRestClient(string jiraUrl, string jiraConsumerKey, string jiraPrivateKey, string access_token, string access_token_secret)
        {
            RestClient client = new RestClient(jiraUrl)
            {
                Authenticator = new JiraAuthenticator(jiraUrl, jiraConsumerKey, jiraPrivateKey, access_token, access_token_secret)
            };

            var jiraRestClient = new JiraRestClientEx(new ServiceLocator(), client);

            return CreateRestClient(jiraRestClient);
        }
    }

Then we can call below to create Jira instance.

Jira jira = JiraOAuth.CreateRestClient(jiraURL, jiraConsumerKey, jiraPrivateKey, jiraAccessToken, jiraAccessTokenSecret);

Now we have oAuth authentication support in Atlassian.SDK, the only difference is to use the new CreateRestClient to create the Jira instance, all the rest will remain the same as using basic authentication.