jwtear 1.0.4 → 1.1.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9f4306c408c344ff505486b1de0bcf06eab68487544aca06e23db8690526753e
4
- data.tar.gz: ca5d778092da238f609b1c75548f3b6900e8c34af2f30e9e6ccb2c02edc7aee5
3
+ metadata.gz: ec80cbd22ceeba8225079c072f491c14489d9621921257c57ff7663ee4626ae8
4
+ data.tar.gz: aca681e7e119897223b99ac347c6eeadf8c90525d16a80b46e76d871f4ce9d04
5
5
  SHA512:
6
- metadata.gz: 5204340947b54c8cdf508d65b6d4b05721fc2cefeccc391f5426df5c42a3fdeb434783ece146f170083395bafffbdc59c9c2297642aa16e8d3ae66a00297259f
7
- data.tar.gz: d82526cef2d9b787c49d4985b97f1cfcc6ec70646b1c913aeb1bc231e7ab4f7b1a6e5217294385f12c5a7f98d7784008ce42a3c90f7f4cae32361a10886d82d3
6
+ metadata.gz: 59045d652e34c71a8cd451f723bf11e86faf506644c394d3012898a1836dbee7ee51896719499aa3e4191aca34e6d1383e3fb518a5758521527adb41d7a8312d
7
+ data.tar.gz: d1b6f5ca3bee6d04ad0e3623c88e54444f17357aececc0b2a5bb6ef3ee9bf8026df5288dbdeaea885afaad5bda186ebb7a9b7fb4cff2123cc776c4a13dff4447
@@ -0,0 +1,30 @@
1
+ name: Push2RubyGems
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ branches: [ master ]
8
+
9
+ jobs:
10
+ build:
11
+ name: Build + Publish
12
+ runs-on: ubuntu-latest
13
+
14
+ steps:
15
+ - uses: actions/checkout@v2
16
+ - name: Set up Ruby 2.6
17
+ uses: actions/setup-ruby@v1
18
+ with:
19
+ ruby-version: 2.6.x
20
+
21
+ - name: Publish to RubyGems
22
+ run: |
23
+ mkdir -p $HOME/.gem
24
+ touch $HOME/.gem/credentials
25
+ chmod 0600 $HOME/.gem/credentials
26
+ printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
27
+ gem build *.gemspec
28
+ gem push *.gem
29
+ env:
30
+ GEM_HOST_API_KEY: "${{secrets.GEM_HOST_API_KEY}}"
data/Gemfile.lock CHANGED
@@ -1,73 +1,70 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- jwtear (1.0.3)
4
+ jwtear (1.0.7)
5
5
  colorize (~> 0.8.1)
6
- gli (~> 2.19, >= 2.19.0)
7
- json-jwt (~> 1.10, >= 1.10.2)
6
+ gli (~> 2.20, >= 2.20.0)
7
+ json-jwt (~> 1.13.0)
8
8
  jwe (~> 0.4.0)
9
- tty-markdown (~> 0.6.0)
10
- tty-pager (~> 0.12.1)
9
+ tty-markdown (~> 0.7.0)
10
+ tty-pager (~> 0.14.0)
11
11
 
12
12
  GEM
13
13
  remote: https://rubygems.org/
14
14
  specs:
15
- activesupport (6.0.0)
15
+ activesupport (6.1.4.1)
16
16
  concurrent-ruby (~> 1.0, >= 1.0.2)
17
- i18n (>= 0.7, < 2)
18
- minitest (~> 5.1)
19
- tzinfo (~> 1.1)
20
- zeitwerk (~> 2.1, >= 2.1.8)
21
- aes_key_wrap (1.0.1)
22
- bindata (2.4.4)
17
+ i18n (>= 1.6, < 2)
18
+ minitest (>= 5.1)
19
+ tzinfo (~> 2.0)
20
+ zeitwerk (~> 2.3)
21
+ aes_key_wrap (1.1.0)
22
+ bindata (2.4.10)
23
23
  colorize (0.8.1)
24
- concurrent-ruby (1.1.5)
25
- equatable (0.6.1)
26
- gli (2.19.0)
27
- i18n (1.7.0)
24
+ concurrent-ruby (1.1.9)
25
+ gli (2.20.1)
26
+ i18n (1.8.10)
28
27
  concurrent-ruby (~> 1.0)
29
- json-jwt (1.10.2)
28
+ json-jwt (1.13.0)
30
29
  activesupport (>= 4.2)
31
30
  aes_key_wrap
32
31
  bindata
33
32
  jwe (0.4.0)
34
- kramdown (1.16.2)
35
- minitest (5.12.2)
36
- pastel (0.7.3)
37
- equatable (~> 0.6)
33
+ kramdown (2.3.1)
34
+ rexml
35
+ minitest (5.14.4)
36
+ pastel (0.8.0)
38
37
  tty-color (~> 0.5)
39
- rouge (3.11.1)
40
- strings (0.1.6)
41
- strings-ansi (~> 0.1)
42
- unicode-display_width (~> 1.5)
38
+ rexml (3.2.5)
39
+ rouge (3.26.0)
40
+ strings (0.2.1)
41
+ strings-ansi (~> 0.2)
42
+ unicode-display_width (>= 1.5, < 3.0)
43
43
  unicode_utils (~> 1.4)
44
- strings-ansi (0.1.0)
45
- thread_safe (0.3.6)
46
- tty-color (0.5.0)
47
- tty-markdown (0.6.0)
48
- kramdown (~> 1.16.2)
49
- pastel (~> 0.7.2)
50
- rouge (~> 3.3)
51
- strings (~> 0.1.4)
52
- tty-color (~> 0.4)
53
- tty-screen (~> 0.6)
54
- tty-pager (0.12.1)
55
- strings (~> 0.1.4)
56
- tty-screen (~> 0.6)
57
- tty-which (~> 0.4)
58
- tty-screen (0.7.0)
59
- tty-which (0.4.1)
60
- tzinfo (1.2.5)
61
- thread_safe (~> 0.1)
62
- unicode-display_width (1.6.0)
44
+ strings-ansi (0.2.0)
45
+ tty-color (0.6.0)
46
+ tty-markdown (0.7.0)
47
+ kramdown (>= 1.16.2, < 3.0)
48
+ pastel (~> 0.8)
49
+ rouge (~> 3.14)
50
+ strings (~> 0.2.0)
51
+ tty-color (~> 0.5)
52
+ tty-screen (~> 0.8)
53
+ tty-pager (0.14.0)
54
+ strings (~> 0.2.0)
55
+ tty-screen (~> 0.8)
56
+ tty-screen (0.8.1)
57
+ tzinfo (2.0.4)
58
+ concurrent-ruby (~> 1.0)
59
+ unicode-display_width (2.0.0)
63
60
  unicode_utils (1.4.0)
64
- zeitwerk (2.1.10)
61
+ zeitwerk (2.4.2)
65
62
 
66
63
  PLATFORMS
67
- ruby
64
+ x86_64-linux
68
65
 
69
66
  DEPENDENCIES
70
67
  jwtear!
71
68
 
72
69
  BUNDLED WITH
73
- 2.0.2
70
+ 2.2.25
data/bin/jwtear CHANGED
@@ -58,6 +58,8 @@ module JWTear
58
58
  print_error "Option #{exception.message}"
59
59
  when GLI::UnknownCommandArgument
60
60
  print_error "#{exception.message}"
61
+ when GLI::UnknownCommand
62
+ print_error "#{exception.message}"
61
63
  else
62
64
  print_error "Unknown Exception:"
63
65
  print_warning 'Please report the issue to: https://github.com/KINGSABRI/jwtear/issues'.underline
data/jwtear.gemspec CHANGED
@@ -18,11 +18,11 @@ Gem::Specification.new do |spec|
18
18
  spec.executables = ['jwtear']
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency 'gli', '~> 2.19', '>= 2.19.0'
22
- spec.add_dependency 'json-jwt', '~> 1.10', '>= 1.10.2'
21
+ spec.add_dependency 'gli', '~> 2.20', '>= 2.20.0'
22
+ spec.add_dependency 'json-jwt', '~> 1.13.0'
23
23
  spec.add_dependency 'jwe', "~> 0.4.0"
24
- spec.add_dependency 'tty-markdown', "~> 0.6.0"
25
- spec.add_dependency 'tty-pager', "~> 0.12.1"
24
+ spec.add_dependency 'tty-markdown', "~> 0.7.0"
25
+ spec.add_dependency 'tty-pager', "~> 0.14.0"
26
26
  spec.add_dependency 'colorize', "~> 0.8.1"
27
27
 
28
28
  # spec.add_development_dependency('rake', '~> 0.9.2.2')
@@ -19,32 +19,34 @@ module JWTear
19
19
 
20
20
  # read key as a string or from file(eg. pub_key.pem)
21
21
  def read_key(key)
22
- if key
23
- File.file?(key)? File.read(key) : key
22
+ if File.file?(File.absolute_path(key))
23
+ File.read(File.absolute_path(key))
24
+ else
25
+ key
24
26
  end
25
27
  end
26
28
 
27
29
  # check_dependencies
28
30
  # check dependencies for plugins and throw a gentle error if not installed
29
31
  # @param deps [Hash]
30
- # The key is the library to be require, the key is the gem to be required
32
+ # The key is the key is the gem name to be installed, the value is library to be require
31
33
  # @example
32
34
  # deps = {'async-io' => 'async/ip'}
33
35
  # check_dependencies(deps)
34
36
  #
35
37
  def check_dependencies(deps={})
36
- return if deps.empty?
38
+ return if deps.empty? or deps.nil?
37
39
  missing = []
38
40
 
39
- deps.each do |gem, req|
41
+ deps.each do |gem, lib|
40
42
  begin
41
- require req
43
+ require lib
42
44
  rescue LoadError
43
45
  missing << gem
44
46
  end
45
47
  end
46
48
  ensure
47
- unless missing.empty?
49
+ unless missing.nil? or missing.empty?
48
50
  print_error "Missing dependencies!"
49
51
  print_warning "Please install as follows:"
50
52
  puts "gem install #{missing.join(' ')}"
data/lib/jwtear/jwe.rb CHANGED
@@ -58,10 +58,10 @@ module JWTear
58
58
  cipher_text = Base64.urlsafe_encode64(@cipher_text, padding: false)
59
59
  authentication_tag = Base64.urlsafe_encode64(@authentication_tag, padding: false)
60
60
 
61
- "#{header.to_json}" + "" +
62
- "#{encrypted_key}" + "" +
63
- "#{iv}" + "" +
64
- "#{cipher_text}" + "" +
61
+ "#{header.to_json}" + ".".bold +
62
+ "#{encrypted_key}" + ".".bold +
63
+ "#{iv}" + ".".bold +
64
+ "#{cipher_text}" + ".".bold +
65
65
  "#{authentication_tag}"
66
66
  end
67
67
 
@@ -78,7 +78,7 @@ module JWTear
78
78
  key = OpenSSL::PKey::RSA.new(key)
79
79
  jwt = JSON::JWT.new(JSON.parse(payload, symbolize_names: true))
80
80
  jwt.header = JSON.parse(header, symbolize_names: true)
81
- ::JWE.encrypt(payload, key, enc: jwt.header[:enc]) # I had to use this gem as json-jwt does not support A192GCM AFAIK
81
+ ::JWE.encrypt(payload, key, enc: jwt.header[:enc]) # I had to use this gem as jwe does not support A192GCM AFAIK
82
82
  rescue TypeError => e
83
83
  print_bad "Invalid data type."
84
84
  print_warning "Make sure your public/private key file exists."
data/lib/jwtear/jws.rb CHANGED
@@ -39,7 +39,7 @@ module JWTear
39
39
  end
40
40
 
41
41
  def to_json_presentation
42
- "#{@header.to_json}" + "" + "#{@payload.to_json}" + "" + "#{Base64.urlsafe_encode64(@signature, padding: false)}"
42
+ "#{@header.to_json}" + ".".bold + "#{@payload.to_json}" + ".".bold + "#{Base64.urlsafe_encode64(@signature, padding: false)}"
43
43
  end
44
44
 
45
45
  # generate_jws
@@ -59,6 +59,8 @@ module JWTear
59
59
  puts "Unexpected algorithm '#{jwt.header[:alg]}'."
60
60
  puts e.message
61
61
  exit!
62
+ rescue Exception => e
63
+ print_error e.message
62
64
  end
63
65
 
64
66
  private
@@ -73,6 +75,24 @@ module JWTear
73
75
  jwt.to_s
74
76
  else
75
77
  raise JSON::JWS::UnexpectedAlgorithm.new("Encryption algorithm '#{jwt.alg}' requires key.") if key.nil?
78
+ alg = jwt.alg.upcase
79
+ case
80
+ when alg.start_with?("HS")
81
+ key
82
+ when alg.start_with?("RS")
83
+ key = OpenSSL::PKey::RSA.new(key)
84
+ when alg.start_with?("PS")
85
+ key = OpenSSL::PKey::RSA.new(key)
86
+ when alg.start_with?("ES")
87
+ # key = OpenSSL::PKey::RSA.new(key)
88
+ print_error("Signing for ECDSA-SHA is not yet implemented")
89
+ print_warning 'Please report the issue to: https://github.com/KINGSABRI/jwtear/issues'.underline
90
+ else
91
+ print_warning("Undefined algorithm. This might generate a wrong token")
92
+ print_warning 'Please report the issue to: https://github.com/KINGSABRI/jwtear/issues'.underline
93
+ key
94
+ end
95
+ jwt.alg = alg.to_sym
76
96
  jwt.sign(key).to_s
77
97
  end
78
98
  end
data/lib/jwtear/token.rb CHANGED
@@ -23,10 +23,9 @@ module JWTear
23
23
  @jwe.parse(token)
24
24
  end
25
25
  rescue Exception => e
26
- print_error "Unknown Exception: #{method(__method__).owner}"
26
+ print_error "#{method(__method__).owner}##{__method__} : Unknown Exception"
27
27
  print_warning 'Please report the issue to: https://github.com/KINGSABRI/jwtear/issues'.underline
28
- puts e
29
- puts e.backtrace
28
+ puts e.full_message
30
29
  exit!
31
30
  end
32
31
 
@@ -1,3 +1,3 @@
1
1
  module JWTear
2
- VERSION = "1.0.4"
2
+ VERSION = "1.1.7"
3
3
  end
@@ -33,7 +33,7 @@ module JWTear
33
33
  include JWTear::Helpers::Utils
34
34
 
35
35
  def initialize(token, list)
36
- deps = {'async-io' => 'async/io'}
36
+ deps = {}
37
37
  check_dependencies(deps)
38
38
  @token = Token.new
39
39
  @jws = @token.parse(token)
@@ -48,7 +48,7 @@ module JWTear
48
48
  key.valid_encoding? ? key.strip! : next
49
49
  print_status "Trying password: #{key}" if verbose
50
50
 
51
- gen_token = @token.generate(:jws, header: @jws.header.to_json, payload:@jws.payload.to_json , key: key)
51
+ gen_token = @token.generate(:jws, header: @jws.header.to_json, payload: @jws.payload.to_json , key: key)
52
52
  sig = gen_token.split('.').last
53
53
  if sig == Base64.urlsafe_encode64(@jws.signature, padding: false)
54
54
  print_good "Password found: #{key}"
@@ -59,7 +59,7 @@ module JWTear
59
59
  end
60
60
  end
61
61
  when keys.kind_of?(String)
62
- gen_token = @token.generate(:jws, header: @jws.header.to_json, payload:@jws.payload.to_json , key: keys)
62
+ gen_token = @token.generate(:jws, header: @jws.header.to_json, payload: @jws.payload.to_json , key: keys)
63
63
  sig = gen_token.split('.').last
64
64
  if sig == Base64.urlsafe_encode64(@jws.signature, padding: false)
65
65
  print_good "Password found: #{keys}"
data/plugins/generate.rb CHANGED
@@ -20,7 +20,7 @@ module JWTear
20
20
  jws_cmd.desc "Key as a password string or a file public key. eg. P@ssw0rd | eg. public_key.pem"
21
21
  jws_cmd.arg_name 'PASSWORD|PUB_KEY_FILE'
22
22
  jws_cmd.flag [:k, :key]
23
- jws_cmd.action do |global, options, args|
23
+ jws_cmd.action do |_, options, _|
24
24
  gen = Generate.new
25
25
  puts gen.jws_token(options[:header], options[:payload], read_key(options[:key]))
26
26
  end
data/plugins/parse.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'time'
2
+
1
3
  module JWTear
2
4
  module CLI
3
5
  extend GLI::App
@@ -83,10 +85,28 @@ module JWTear
83
85
  def print_jws_payload(payload)
84
86
  print_h2 "Payload"
85
87
  payload.each do |k, v|
86
- print_h3 "#{k}" , "#{v}"
88
+ if k == "iat" || k == "nbf"
89
+ print_h3 "#{k}" , "#{v}", "\tTIMESTAMP = #{Time.at(v)}".green
90
+ elsif k == "exp"
91
+ compare_time_with_now(k,v)
92
+ else
93
+ print_h3 "#{k}" , "#{v}"
94
+ end
87
95
  end
88
96
  end
89
97
 
98
+ def compare_time_with_now(k, timestamp)
99
+ if timestamp.nil?
100
+ return
101
+ end
102
+ readable_time = Time.at(timestamp)
103
+ if readable_time < Time.now
104
+ print_h3 "#{k}", "#{timestamp}", "\tTIMESTAMP = #{readable_time}\t(EXPIRED)".red
105
+ else
106
+ print_h3 "#{k}", "#{timestamp}", "\tTIMESTAMP = #{readable_time}".green
107
+ end
108
+ end
109
+
90
110
  def print_jws_sig(signature)
91
111
  print_h2 "Signature - B64 encoded"
92
112
  puts Base64.urlsafe_encode64(@token.signature, padding: false)
@@ -198,6 +198,7 @@ _source(JWT, JWS and JWE for Not So Dummies! (Part I))_
198
198
  * [Pentesterlab(PRO) - JWT X](https://pentesterlab.com/exercises/jwt_x/)
199
199
  * [Pentesterlab(PRO) - JWT XI](https://pentesterlab.com/exercises/jwt_xi)
200
200
  * [Pentesterlab(PRO) - JWT XII](https://pentesterlab.com/exercises/jwt_xii)
201
+ * [Pentesterlab(PRO) - JWT XIII](https://pentesterlab.com/exercises/jwt_iii)
201
202
  * [Pentesterlab(PRO) - JSON Web Encryption](https://pentesterlab.com/exercises/jwe)
202
203
  * [Vulnerable JWT implementations](https://github.com/Sjord/jwtdemo)
203
204
 
@@ -212,3 +213,4 @@ _source(JWT, JWS and JWE for Not So Dummies! (Part I))_
212
213
  * [Damn Vulnerable Service](https://github.com/snoopysecurity/dvws)
213
214
  * [CSRF JWT redirect leak](https://gist.github.com/stefanocoding/8cdc8acf5253725992432dedb1c9c781)
214
215
  * [Critical vulnerabilities in JSON Web Token libraries](https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/)
216
+ * [JWT Attack Playbook](https://github.com/ticarpi/jwt_tool/wiki)
data/plugins/wiki.rb CHANGED
@@ -34,7 +34,7 @@ module JWTear
34
34
  require 'open-uri'
35
35
  print_status 'Updating wiki'
36
36
  current_wiki = File.expand_path(File.join(__dir__ , 'wiki', 'README.md'))
37
- updated_wiki = open('https://raw.githubusercontent.com/KINGSABRI/jwtear/master/plugins/wiki/README.md').read
37
+ updated_wiki = URI.open('https://raw.githubusercontent.com/KINGSABRI/jwtear/master/plugins/wiki/README.md').read
38
38
  if File.exists?(current_wiki) && File.writable?(current_wiki)
39
39
  File.write(current_wiki, updated_wiki)
40
40
  else
metadata CHANGED
@@ -1,55 +1,49 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jwtear
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - KING SABRI
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-08 00:00:00.000000000 Z
11
+ date: 2021-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gli
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '2.19'
20
17
  - - ">="
21
18
  - !ruby/object:Gem::Version
22
- version: 2.19.0
19
+ version: 2.20.0
20
+ - - "~>"
21
+ - !ruby/object:Gem::Version
22
+ version: '2.20'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
- - - "~>"
28
- - !ruby/object:Gem::Version
29
- version: '2.19'
30
27
  - - ">="
31
28
  - !ruby/object:Gem::Version
32
- version: 2.19.0
29
+ version: 2.20.0
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '2.20'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: json-jwt
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '1.10'
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- version: 1.10.2
39
+ version: 1.13.0
43
40
  type: :runtime
44
41
  prerelease: false
45
42
  version_requirements: !ruby/object:Gem::Requirement
46
43
  requirements:
47
44
  - - "~>"
48
45
  - !ruby/object:Gem::Version
49
- version: '1.10'
50
- - - ">="
51
- - !ruby/object:Gem::Version
52
- version: 1.10.2
46
+ version: 1.13.0
53
47
  - !ruby/object:Gem::Dependency
54
48
  name: jwe
55
49
  requirement: !ruby/object:Gem::Requirement
@@ -70,28 +64,28 @@ dependencies:
70
64
  requirements:
71
65
  - - "~>"
72
66
  - !ruby/object:Gem::Version
73
- version: 0.6.0
67
+ version: 0.7.0
74
68
  type: :runtime
75
69
  prerelease: false
76
70
  version_requirements: !ruby/object:Gem::Requirement
77
71
  requirements:
78
72
  - - "~>"
79
73
  - !ruby/object:Gem::Version
80
- version: 0.6.0
74
+ version: 0.7.0
81
75
  - !ruby/object:Gem::Dependency
82
76
  name: tty-pager
83
77
  requirement: !ruby/object:Gem::Requirement
84
78
  requirements:
85
79
  - - "~>"
86
80
  - !ruby/object:Gem::Version
87
- version: 0.12.1
81
+ version: 0.14.0
88
82
  type: :runtime
89
83
  prerelease: false
90
84
  version_requirements: !ruby/object:Gem::Requirement
91
85
  requirements:
92
86
  - - "~>"
93
87
  - !ruby/object:Gem::Version
94
- version: 0.12.1
88
+ version: 0.14.0
95
89
  - !ruby/object:Gem::Dependency
96
90
  name: colorize
97
91
  requirement: !ruby/object:Gem::Requirement
@@ -115,6 +109,7 @@ executables:
115
109
  extensions: []
116
110
  extra_rdoc_files: []
117
111
  files:
112
+ - ".github/workflows/gem-push.yml"
118
113
  - ".gitignore"
119
114
  - CODE_OF_CONDUCT.md
120
115
  - Gemfile
@@ -156,8 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
156
151
  - !ruby/object:Gem::Version
157
152
  version: '0'
158
153
  requirements: []
159
- rubyforge_project:
160
- rubygems_version: 2.7.6.2
154
+ rubygems_version: 3.0.3.1
161
155
  signing_key:
162
156
  specification_version: 4
163
157
  summary: JWTear, a modular command-line tool to parse, create and manipulate JWT tokens