Skip to content

Vendor atlassian-jwt and unlock jwt 3.x#482

Open
byroot wants to merge 1 commit into
sumoheavy:masterfrom
byroot:jwt-3.0
Open

Vendor atlassian-jwt and unlock jwt 3.x#482
byroot wants to merge 1 commit into
sumoheavy:masterfrom
byroot:jwt-3.0

Conversation

@byroot
Copy link
Copy Markdown

@byroot byroot commented Apr 9, 2026

Currently jira-ruby depends on atlassian-jwt which itself has a dependency on jwt ~> 2.1.

jwt being a popular dependency, this not allowing jwt 3.x, prevent updating a lot of other gems.

Given the state of atlassian-jwt, I don't expect them to ever release a new version, but it's not a whole lot of code so I think it makes more sense to just vendor it. Licensing wise there is compatibility.

Ref: https://bitbucket.org/atlassian/atlassian-jwt-ruby/src/master/
Ref: https://rubygems.org/gems/atlassian-jwt

@bobbrodie bobbrodie added this to the v3.1.1 milestone May 8, 2026
@bobbrodie
Copy link
Copy Markdown
Member

bobbrodie commented May 8, 2026

@byroot I'd like to propose a different approach. Since tests are failing after vendoring, what if we just switch to jwt and then re-implement compatible changes from Atlassian::Jwt.build_claims? I think something like this will work with both jwt 2.x and 3.x. All tests are passing but it needs further testing:

diff --git a/jira-ruby.gemspec b/jira-ruby.gemspec
index e825102..a31c832 100644
--- a/jira-ruby.gemspec
+++ b/jira-ruby.gemspec
@@ -23,8 +23,8 @@ Gem::Specification.new do |s|
   s.require_paths = ['lib']
 
   s.add_dependency 'activesupport'
-  s.add_dependency 'atlassian-jwt'
   s.add_dependency 'cgi'
+  s.add_dependency 'jwt'
   s.add_dependency 'multipart-post'
   s.add_dependency 'oauth', '~> 1.0'
 end
diff --git a/lib/jira/jwt_client.rb b/lib/jira/jwt_client.rb
index 1fa441e..ab0fb7d 100644
--- a/lib/jira/jwt_client.rb
+++ b/lib/jira/jwt_client.rb
@@ -1,6 +1,9 @@
 # frozen_string_literal: true
 
-require 'atlassian/jwt'
+require 'cgi'
+require 'digest'
+require 'jwt'
+require 'uri'
 
 module JIRA
   class JwtClient < HttpClient
@@ -29,15 +32,32 @@ module JIRA
     end
 
     def build_jwt(url)
-      claim = Atlassian::Jwt.build_claims \
-        @options[:issuer],
-        url,
-        http_method.to_s,
-        @options[:site],
-        (Time.now - 60).to_i,
-        (Time.now + 86_400).to_i
+      now = Time.now.to_i
+      claim = {
+        iss: @options[:issuer],
+        iat: now - 60,
+        exp: now + 86_400,
+        qsh: query_string_hash(url, http_method.to_s)
+      }
 
       JWT.encode claim, @options[:shared_secret]
     end
+
+    def query_string_hash(url, http_method)
+      uri = URI.parse(url)
+      base_uri = URI.parse(@options[:site])
+
+      path = uri.path.delete_prefix(base_uri.path)
+      path = '/' if path.empty?
+
+      params = CGI.parse(uri.query || '')
+      params.delete('jwt')
+      sorted_params = params.sort.map do |key, values|
+        "#{CGI.escape(key)}=#{values.sort.map { |v| CGI.escape(v) }.join(',')}"
+      end.join('&')
+
+      canonical = "#{http_method.upcase}&#{path}&#{sorted_params}"
+      Digest::SHA256.hexdigest(canonical)
+    end
   end
 end

@byroot
Copy link
Copy Markdown
Author

byroot commented May 9, 2026

My bad on the failing CI, it's unclear to me how these specs ever passed. But regardless, that code isn't actually needed, so I trimed it, it should pass now.

But otherwise, yes your proposal seem fine, I just went the simpler route because I only have limited context on this code, I'm not attached to a particular solution, as long as jira-ruby no longer block upgrading JWT I'm happy.

Currently `jira-ruby` depends on `atlassian-jwt` which itself
has a dependency on `jwt ~> 2.1`.

`jwt` being a popular dependency, this not allowing `jwt 3.x`, prevent
updating a lot of other gems.

Given the state of `atlassian-jwt`, I don't expect them to ever release
a new version, but it's not a whole lot of code so I think it makes
more sense to just vendor it. Licensing wise there is compatibility.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants