jira-cli icon indicating copy to clipboard operation
jira-cli copied to clipboard

feat: Enable OAuth 3LO support

Open christianarty opened this issue 5 months ago • 13 comments

Summary

fixes #863

This PR allows for users to have another option (oauth) when generating their JIRA config.yml for the Cloud installation.

Details

This PR implements JIRA's 3LO OAuth solution for users to obtain a JIRA access token. Each consumer of jira-cli will need to create a JIRA App with the specific scopes in order to connect it properly with their JIRA cloud instance.

The oauth secret will be stored in the .config/.jira directory, where the tokens will be automatically regenerated when it expires and the newly generated tokens will be cached to the oauth secret file.

How to create a JIRA App properly:

See this discussion post here: https://github.com/ankitpokhrel/jira-cli/discussions/879#discussion-8604411

Known Limitations/Issues

[!NOTE]
This limitation has also been noted in the README under the Known Issues section.

Ideally, for OAuth, we would have one single distributed app that can be installed in multiple different JIRA cloud instances. However, The 3LO doesn't support Proof Key for Code Exchange (PKCE). Without this support, we would have to share the single distrubuted app's client secret with all the consumers. See these links for more info:

  • https://jira.atlassian.com/browse/ECO-283
  • https://community.developer.atlassian.com/t/oauth-2-0-with-proof-key-for-code-exchange-pkce/80173/3

As noted in the forum above, a workaround would be that each consumer has to create their own JIRA app and use that app's client ID and secret in the jira-cli client app.

  • This basically acts like a proxy to funnel requests into your JIRA cloud instance

Testing Done

  • make deps install => WORKS
  • ~/go/bin/jira issue create -tTask -s"TEST TICKET" -l"testing" --template ~/jira/task.tmpl -a$(~/go/bin/jira me) => WORKS (created a ticket, and proper link)
  • make test => WORKS
  • make lint => WORKS
  • make ci => WORKS

christianarty avatar Jul 17 '25 03:07 christianarty

cc: @ankitpokhrel for visibility. It'll be great if this can be reviewed/merged soon, so folks that can only authenticate through OAuth 3LO can start using this tool again.

shadyabhi avatar Jul 22 '25 03:07 shadyabhi

@ankitpokhrel Could you take a look at this PR when you get a chance? I think this is a nice feature add (and personally been using it for months now without hiccup)

christianarty avatar Sep 06 '25 22:09 christianarty

@christianarty Thanks for the PR! I'm currently away, I'll look into this in a few weeks.

ankitpokhrel avatar Sep 07 '25 07:09 ankitpokhrel

@ankitpokhrel Hey! Just wanted to see if you had a moment to take a peek at this PR! Would be appreciated thanks!

christianarty avatar Oct 08 '25 21:10 christianarty

Also added a new commit that expanded the default scopes since recently realized, with the oauth, for jira sprint list to work properly needed extra scopes: https://developer.atlassian.com/cloud/jira/software/rest/api-group-board/#api-rest-agile-1-0-board-boardid-sprint-sprintid-issue-get https://developer.atlassian.com/cloud/jira/software/rest/api-group-sprint/#api-rest-agile-1-0-sprint-sprintid-issue-post

christianarty avatar Oct 08 '25 22:10 christianarty

I have a suggestion here.

I played with the app and 3LO.

It works great except when the app you created doesn't have the expected scope

I feel like the CLI should display the scope it expect in the console. Either by default, or when the timeout happens.

The error message on the consent screen provided by Jira is unclear.

Also, I'm unsure if you can report the scope the app was created with without being authenticated, but it would be great to double check what us expected and what is currently on the created oauth app

ccoVeille avatar Nov 16 '25 17:11 ccoVeille

I have a suggestion here.

I played with the app and 3LO.

It works great except when the app you created doesn't have the expected scope

I feel like the CLI should display the scope it expect in the console. Either by default, or when the timeout happens.

The error message on the consent screen provided by Jira is unclear.

Also, I'm unsure if you can report the scope the app was created with without being authenticated, but it would be great to double check what us expected and what is currently on the created oauth app

@ccoVeille Great suggestion! I am not sure about the scope when unauthorized and I think that should be a separate PR (this PR is already big enough tbh), but I did just add for the CLI to print out the expected scopes when creating a new config. It looks like this: Screenshot 2025-11-16 at 12 51 05 PM

Do you think it should look like that or another format? EDIT: I removed the offline_access scope from printing to console since that is a special scope you don't have to click on JIRA ui.

@ankitpokhrel I was **just a bit off ** when I said a couple days I'll fix it 😅 but I refactored this to use the keyring storage as the primary and file system as secondary and it works as expected. Also wrote some tests to account for it but I think this would suffice. I also updated the README to account for some of the changes I did with the env vars.

christianarty avatar Nov 16 '25 17:11 christianarty

I have a suggestion here.

I played with the app and 3LO.

It works great except when the app you created doesn't have the expected scope

I feel like the CLI should display the scope it expect in the console. Either by default, or when the timeout happens.

The error message on the consent screen provided by Jira is unclear.

Also, I'm unsure if you can report the scope the app was created with without being authenticated, but it would be great to double check what us expected and what is currently on the created oauth app

@ccoVeille Great suggestion! I am not sure about the scope when unauthorized and I think that should be a separate PR (this PR is already big enough tbh), but I did just add for the CLI to print out the expected scopes when creating a new config. It looks like this: Screenshot 2025-11-16 at 12 51 05 PM

Do you think it should look like that or another format?

I think it's good, except they should be ordered alphabetically, or in the order they can be found in Jira developer console

ccoVeille avatar Nov 16 '25 19:11 ccoVeille

Also, I'm unsure if you can report the scope the app was created with without being authenticated, but it would be great to double check what us expected and what is currently on the created oauth app

Great suggestion! I am not sure about the scope when unauthorized and I think that should be a separate PR (this PR is already big enough tbh)

Yes, it does. And as we both said, we are not sure it can be done.

ccoVeille avatar Nov 16 '25 19:11 ccoVeille

Thanks @ccoVeille for the comments! Appreciate the extra look! I've addressed them all and tested it with the new revisions and things work as intended. @ankitpokhrel it now defaults to the keyring and fallsback to the filesystem storage. Please let me know if there is anything else we need to do in this PR otherwise i think its ready to 🚢

christianarty avatar Nov 19 '25 00:11 christianarty

Screenshot 2025-11-18 at 7 49 49 PM

Also, @ccoVeille these are what the new order of expected scopes, alphabetically sorted and grouped by scope type.

christianarty avatar Nov 19 '25 00:11 christianarty

Hoping to see this merged soon, looks great!

vibbix avatar Nov 21 '25 15:11 vibbix

@ankitpokhrel, whenever you get a chance could you drop a 🚢 . Would be greatly appreciated thanks!

christianarty avatar Nov 26 '25 20:11 christianarty