1

I'm trying to use the Jira REST API to update issues programmatically via a MacOS program, written in Swift. I have a Jira API Token and have succeeded using CURL. Here is the command:

curl --request PUT \
  --url 'https://xxxx.atlassian.net/rest/api/2/issue/SAN-2' \
  --user '[email protected]:zzz' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{
"update": {
"timetracking": [
{
"edit": {
"originalEstimate": "1w 1d"
}
}
]
}
}'

Where zzz is the API Token. This works and the field is updated correctly.

The Swift version mirrors this as closely as I can, but fails with the error

Response: {"errorMessages":["Issue does not exist or you do not have permission to see it."],"errors":{}}

Here is the Swift code:

        let tokenString = "[email protected]:zzz"

        guard let encodedTokenString = tokenString.data(using: .utf8)?.base64EncodedData() else { fatalError("Can't encode token") }

        let authString = String("Token token=\(encodedTokenString)")

        guard let url = URL(string: "https://xxxx.atlassian.net/rest/api/2/issue/SAN-2")

        else {
            fatalError("Couldn't create a static URL")
        }

        let request = NSMutableURLRequest(url: url)

        request.addValue(authString, forHTTPHeaderField: "Authorization")

        request.addValue("application/json", forHTTPHeaderField: "Content-Type")

        request.httpMethod = "PUT"

        let dataString = "{\"update\": {\"timetracking\": [{\"edit\": {\"originalEstimate\": \"1w 1d\"}}]}}".utf8

        let body = Data(dataString)    

        request.httpBody = body

        let session = URLSession.shared

        session.dataTask(with: request as URLRequest) { (data, response, error) -> Void in

            guard let data = data, let responseString = NSString(data: data, encoding: String.Encoding.utf8.rawValue) as String?, !responseString.isEmpty else {
                print("No valid response!")
                return
            }
            print("Response: " + responseString)

        }.resume()

I clearly have permission to edit the issue and it exists. I have an API token, and it works. What am I missing?

2
  • I believe it should be let authString = String("Bearer \(encodedTokenString)") The Authorization header should have a format Authorization: type credentials, and I have not heard of Authorization type Token. Usually with token the type is Bearer Commented Sep 17, 2020 at 21:13
  • Thanks Kiril. I tried changing "Token" to "Bearer" with the same results. Were there other changes you suggested? I'm not sure what "The Authorization header should have a format Authorization: type credentials" is implying, sorry. Commented Sep 17, 2020 at 22:01

1 Answer 1

3

I see two issues:

1) You're setting the encodedTokenString to be Data instead of a string.

guard let encodedTokenString = tokenString.data(using: .utf8)?.base64EncodedData() else { fatalError("Can't encode token") }

change the above to:

guard let encodedTokenString = tokenString.data(using: .utf8)?.base64EncodedString() else { fatalError("Can't encode token") }

2) Your authString should be:

`let authString = String("Basic \(encodedTokenString)")`
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.