JIRA Cookie-based auth API calls in F# with RestSharp

Today I was trying to create a quick integration with a bug tracking tool, as a little spike, unfortunately as is often the case, out of date documentation, vague errors, etc held up the task. None-the-less I got something working with cookie based authentication (I’ll be switching to OAuth based soon I’m sure that’ll go just as smooth). I’ll also submit a report about the problems with the documentation I discovered.

The rest of the documentation seems ok, but only time will tell as I get further with it, but from my experience it’s usually the initial steps that result in the most frustrations, as you get reminded not to trust the documentation…

Following along with this guide – JIRA REST API Example – Cookie-based Authentication.

What’s not clear in the documentation:

  • Even though you sign in with your email address, you really need to use your username (which is different), at least is for the `admin` account.
  • Error 1: there is a leading `/jira/` element in the auth API route, this may be old or may be specific to self hosting, it’s not part of the URI for on-demand, it should be `http://jira.example.com:8090/rest/auth/1/session`
  • Error 2: (the big one) what is returned is a different `session` object and it not only contains the required `JSESSIONID` but also another key,value pair you need to have in your cookie when you make a subsequent request: `studio.crowd.tokenkey`.

The core objective was to get specific events from 1 system to be reflected in new or existing locations in a second system. In this case the second system is JIRA the bug tracker.

Complete Solution

The break down will follow below.

Sorry this code is a bit awkward because RestSharp is written for fluent C# style usage, I’ll be looking for an F# focused rest client, and I only chose ReshSharp because I had used it ages ago.

Walk Through

Some types to send along, notice the casing, that’s because I don’t have any JSON serialization code wired up yet to do the case change from .NET uppercase convention to lowercase JSON style.

type PostData = {
    body: string
}

type Login = {
    username : string
    password : string
}

Using these records, against your on-demand account make the auth request, and inspect what you get back (see Error 2) and you’ll discover more cookie details come back than documented. As an extra note as to why it was even more frustrating if you capture and review the calls from the web UI those calls supply even more cookie details such as: `ondemand.autologin`, `xsrf.token` and others.

let uname = "admin"
let pw = "your-password"

let restClient = 
    RestSharp.RestClient("https://your-account.atlassian.net")

let authReq = 
    RestSharp
        .RestRequest("/rest/auth/1/session")
        .AddJsonBody({ username = uname; password = pw })

Issue that auth request and now you’ll have the session cookie values you’ll need.

let authResponse = restClient.Post authReq
let cookiesToAdd = 
    authResponse.Cookies 
    |> Seq.map (fun x -> (x.Name, x.Value))

In this case I’m updating an existing comment to which I know the identifier.

let addCommentReq = 
    RestSharp
        .RestRequest("/rest/api/2/issue/Issue-Id/comment")
        .AddJsonBody({ body = "a new comment" })

for (name, value) in cookiesToAdd do
    addCommentReq.AddCookie(name, value) |> ignore

Finally issue that add comment request, and the status code should be ‘Created’, I saw ‘Unauthorized’ responses for far to long.


let commentResp = restClient.Post addCommentReq

Lastly another fun hiccup was discovering that curl on Windows doesn’t support https “Protocol https not supported or disabled in libcurl”, but that was the least of my problems.