json-jwt 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of json-jwt might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +21 -162
- data/VERSION +1 -1
- data/lib/json/jose.rb +39 -4
- data/lib/json/jwe.rb +4 -8
- data/lib/json/jws.rb +1 -1
- data/lib/json/jwt.rb +4 -34
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e593ec307b6ef4d7c0f401221c585c615c86c918
|
4
|
+
data.tar.gz: 4068c3885a7f8417b577f0b5413f567f94612488
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b15ef784c658a73d9cf7e5d79fc55966008d08c87f8d1b3b4a4384fd3017a410f490e008ecdbd12d4fdd2347c337533857b66db5569d293c9622a90cbcd1604c
|
7
|
+
data.tar.gz: 33b50220dfd570e1982d98a3e1a1ee30f52e4d2a3bfb49b616ba24c60463dcac23554c6fc1cbb3da3ee4f7a684f81c6101c7a84839bc727ca578cff2d0d7c313
|
data/README.md
CHANGED
@@ -14,183 +14,42 @@ gem install json-jwt
|
|
14
14
|
|
15
15
|
* View Source on GitHub (https://github.com/nov/json-jwt)
|
16
16
|
* Report Issues on GitHub (https://github.com/nov/json-jwt/issues)
|
17
|
+
* Documentation on GitHub (https://github.com/nov/json-jwt/wiki)
|
17
18
|
|
18
19
|
## Examples
|
19
20
|
|
20
|
-
### JWT, JWS and JWE
|
21
|
-
|
22
|
-
#### Encoding
|
23
|
-
|
24
21
|
```ruby
|
25
22
|
require 'json/jwt'
|
26
23
|
|
24
|
+
private_key = OpenSSL::PKey::RSA.new <<-PEM
|
25
|
+
-----BEGIN RSA PRIVATE KEY-----
|
26
|
+
MIIEpAIBAAKCAQEAyBKIFSH8dP6bDkGBziB6RXTTfZVTaaNSWNtIzDmgRFi6FbLo
|
27
|
+
:
|
28
|
+
-----END RSA PRIVATE KEY-----
|
29
|
+
PEM
|
30
|
+
|
31
|
+
public_key = OpenSSL::PKey::RSA.new <<-PEM
|
32
|
+
-----BEGIN PUBLIC KEY-----
|
33
|
+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyBKIFSH8dP6bDkGBziB6
|
34
|
+
:
|
35
|
+
-----END PUBLIC KEY-----
|
36
|
+
PEM
|
37
|
+
|
38
|
+
# Sign & Encode
|
27
39
|
claim = {
|
28
40
|
iss: 'nov',
|
29
41
|
exp: 1.week.from_now,
|
30
42
|
nbf: Time.now
|
31
43
|
}
|
44
|
+
jws = JSON::JWT.new(claim).sign(private_key, :RS256)
|
45
|
+
jws.to_s
|
32
46
|
|
33
|
-
#
|
34
|
-
jwt = JSON::JWT.new(claim).to_s
|
35
|
-
|
36
|
-
# With signiture, no encryption
|
37
|
-
jws = JSON::JWT.new(claim).sign(key, algorithm) # algorithm is optional. default HS256
|
38
|
-
jws.to_s # => header.payload.signature
|
39
|
-
jws.to_json(syntax: :general) # => General JWS JSON Serialization
|
40
|
-
jws.to_json(syntax: :flatten) # => Flattened JWS JSON Serialization
|
41
|
-
|
42
|
-
# With signature & encryption
|
43
|
-
jwe = jws.encrypt(key, algorithm, encryption_method) # algorithm & encryption_method are optional. default RSA1_5 & A128CBC-HS256
|
44
|
-
jwe.to_s # => header.encrypted_key.iv.cipher_text.authentication_tag
|
45
|
-
```
|
46
|
-
|
47
|
-
Supported `key` are
|
48
|
-
* `String`
|
49
|
-
* `OpenSSL::PKey::RSA`
|
50
|
-
* `OpenSSL::PKey::EC`
|
51
|
-
* `JSON::JWK`
|
52
|
-
* `JSON::JWK::Set` # NOTE: proper `JSON::JWK` in the set will be selected by `kid` in the header.
|
53
|
-
|
54
|
-
Supported `algorithm` are
|
55
|
-
|
56
|
-
For JWS
|
57
|
-
* `HS256`
|
58
|
-
* `HS384`
|
59
|
-
* `HS512`
|
60
|
-
* `RS256`
|
61
|
-
* `RS384`
|
62
|
-
* `RS512`
|
63
|
-
* `ES256`
|
64
|
-
* `ES384`
|
65
|
-
* `ES512`
|
66
|
-
|
67
|
-
For JWE
|
68
|
-
* `RSA1_5`
|
69
|
-
* `RSA-OAEP`
|
70
|
-
* `dir`
|
71
|
-
|
72
|
-
Supported `encryption_method` are
|
73
|
-
* `A128GCM`
|
74
|
-
* `A256GCM`
|
75
|
-
* `A128CBC-HS256`
|
76
|
-
* `A256CBC-HS512`
|
77
|
-
|
78
|
-
#### Decoding
|
79
|
-
|
80
|
-
```ruby
|
47
|
+
# Decode & Verify
|
81
48
|
input = "jwt_header.jwt_claims.jwt_signature"
|
82
|
-
JSON::JWT.decode(input,
|
83
|
-
```
|
84
|
-
|
85
|
-
`input` can be JSON, in that case, it's handled as General/Flattened JWS JSON Serialization.
|
86
|
-
|
87
|
-
NOTE: General JWS JSON Serialization with multiple signatures aren't supported.
|
88
|
-
|
89
|
-
Supported `key` are
|
90
|
-
* `String`
|
91
|
-
* `OpenSSL::PKey::RSA`
|
92
|
-
* `OpenSSL::PKey::EC`
|
93
|
-
* `JSON::JWK`
|
94
|
-
* `JSON::JWK::Set` # NOTE: proper `JSON::JWK` in the set will be selected by `kid` in the header.
|
95
|
-
* `:skip_verification` # NOTE: skip signature verification
|
96
|
-
|
97
|
-
### JWK
|
98
|
-
|
99
|
-
`JSON::JWK.new` accepts these instances as key inputs
|
100
|
-
* `String` # NOTE: for shared key (kty=oct)
|
101
|
-
* `OpenSSL::PKey::RSA`
|
102
|
-
* `OpenSSL::PKey::EC`
|
103
|
-
* `JSON::JWK`
|
104
|
-
* `Hash`
|
105
|
-
|
106
|
-
This gem also defines
|
107
|
-
* `OpenSSL::PKey::RSA#to_jwk`
|
108
|
-
* `OpenSSL::PKey::EC#to_jwk`
|
109
|
-
|
110
|
-
#### RSA
|
111
|
-
|
112
|
-
```ruby
|
113
|
-
k = OpenSSL::PKey::RSA.new(2048)
|
114
|
-
|
115
|
-
k.to_jwk # NOTE: same with `JSON::JWK.new(k)`
|
116
|
-
# => JSON::JWK (private key)
|
117
|
-
|
118
|
-
k.public_key.to_jwk
|
119
|
-
# => JSON::JWK (public key)
|
49
|
+
JSON::JWT.decode(input, public_key)
|
120
50
|
```
|
121
51
|
|
122
|
-
|
123
|
-
jwk = JSON::JWK.new(
|
124
|
-
kty: "RSA",
|
125
|
-
e: "AQAB",
|
126
|
-
n: "0OIOijENzP0AXnxP-X8Dnazt3m4NTamfNsSCkH4xzgZAJj2Eur9-zmq9IukwN37lIrm3oAE6lL4ytNkv-DQpAivKLE8bh4c9qlB9o32VWyg-mg-2af-JlfGXYoaCW2GDMOV6EKqHBxE0x1EI0tG4gcNwO6A_kYtK6_ACgTQudWz_gnPrL-QCunjIMbbrK9JqgMZhgMARMQpB-j8oet2FFsEcquR5MWtBeAn7qC1AD2ya0EmzplZJP6oCka_VVuxAnyWfRGA0bzCBRIVbcGUXVNIXpRtA_4960e7AlGfMSA-ofN-vo7v0CMkA8BwpZHai9CAJ-cTCX1AVbov83LVIWw",
|
127
|
-
d: "BZCgNopMBdQPuHSzZMA_hmnfBHgGHrWQKlNd7x-NkCGWf-5PpPIJHNK3K0DvKetVi3FLNRYTS3ctvqeyoXgyR36HKlsJLrkpqWnvjvV_jygpUs1sXLKUJcyD7foLawfUCO90KxF_-24367967rLrqXldehkw2F3Ppy2Dw5FyU2qBqcpLeruBt6-UdMmBufzNQLisPJ67vhCTVrTNaHDDeCK2gHI3gqsnnbzOMS45VknmFOgKUp1C8GZu5BsT-AdDApEtY-DRZqnr6BxZv4-hG5OdEUA4_LCaI6JwlaAzv0Z74jpBZDC73cXWKJPgVuhARZcll5cexB2_EpgZDB6akQ",
|
128
|
-
p: "6GFVNgaXcW39NG-sRqKPzFtz1usfAkdCydPmfZirfHRhSh3OojX3Glbe7BI_SRSOLc2d2xw2_ZwKRlruY44aGEf4s5gD_nKgq2QS-1cA5uNAU91wRtY2rdoAuCnk2BX3WTZPnzyxkokFY0S0R_9IpJhRz72ggxYyhx0ymRUBIWc",
|
129
|
-
q: "5h1QX2JWLbcIT_cfrkmMoES1z06Fu88MLORYppiRDqkXl3CJFxKFtKJtDPLTf0MeTFexh81V52Ztsd8UttPInyDl9l5T0AOy8NmqHKqjI1063uy4bnHWetN7ovHftc_TOlnldAoQh9bmhZAhEyGlwa5Kros2YD2amIgDhcOmRO0"
|
130
|
-
)
|
131
|
-
jwk.to_key
|
132
|
-
# => OpenSSL::PKey::RSA (private key)
|
133
|
-
|
134
|
-
jwk = JSON::JWK.new(
|
135
|
-
kty: "RSA",
|
136
|
-
e: "AQAB",
|
137
|
-
n: "0OIOijENzP0AXnxP-X8Dnazt3m4NTamfNsSCkH4xzgZAJj2Eur9-zmq9IukwN37lIrm3oAE6lL4ytNkv-DQpAivKLE8bh4c9qlB9o32VWyg-mg-2af-JlfGXYoaCW2GDMOV6EKqHBxE0x1EI0tG4gcNwO6A_kYtK6_ACgTQudWz_gnPrL-QCunjIMbbrK9JqgMZhgMARMQpB-j8oet2FFsEcquR5MWtBeAn7qC1AD2ya0EmzplZJP6oCka_VVuxAnyWfRGA0bzCBRIVbcGUXVNIXpRtA_4960e7AlGfMSA-ofN-vo7v0CMkA8BwpZHai9CAJ-cTCX1AVbov83LVIWw"
|
138
|
-
)
|
139
|
-
jwk.to_key
|
140
|
-
# => OpenSSL::PKey::RSA (public key)
|
141
|
-
```
|
142
|
-
|
143
|
-
#### EC
|
144
|
-
|
145
|
-
```ruby
|
146
|
-
k = OpenSSL::PKey::EC.new('prime256v1').generate_key
|
147
|
-
|
148
|
-
k.to_jwk
|
149
|
-
# => JSON::JWK (private key)
|
150
|
-
|
151
|
-
k.private_key = nil
|
152
|
-
k.to_jwk
|
153
|
-
# => JSON::JWK (public key)
|
154
|
-
```
|
155
|
-
|
156
|
-
```ruby
|
157
|
-
jwk = JSON::JWK.new(
|
158
|
-
kty: "EC",
|
159
|
-
crv: "P-256",
|
160
|
-
x: "D4L5V9QocZvfuEEGfGD5YCEbIcXR-KfF7RqqZUaovJ8",
|
161
|
-
y: "VX0T94KUo0YkhuvT2q0MXMOTtfaIjDS4fb9ii54g4gU",
|
162
|
-
d: "MCOTV6Ncg7KTuGh1hTa029ZVkqdlaXaYnfLSkZjJ_uE"
|
163
|
-
)
|
164
|
-
jwk.to_key
|
165
|
-
# => OpenSSL::PKey::EC (private key)
|
166
|
-
|
167
|
-
jwk = JSON::JWK.new(
|
168
|
-
kty: "EC",
|
169
|
-
crv: "P-256",
|
170
|
-
x: "D4L5V9QocZvfuEEGfGD5YCEbIcXR-KfF7RqqZUaovJ8",
|
171
|
-
y: "VX0T94KUo0YkhuvT2q0MXMOTtfaIjDS4fb9ii54g4gU"
|
172
|
-
)
|
173
|
-
jwk.to_key
|
174
|
-
# => OpenSSL::PKey::EC (public key)
|
175
|
-
```
|
176
|
-
|
177
|
-
#### oct
|
178
|
-
|
179
|
-
NOTE: no `String#to_jwk` is defined for now.
|
180
|
-
|
181
|
-
```ruby
|
182
|
-
JSON::JWK.new 'secret'
|
183
|
-
# => JSON::JWK
|
184
|
-
```
|
185
|
-
|
186
|
-
```ruby
|
187
|
-
jwk = JSON::JWK.new(
|
188
|
-
kty: "oct",
|
189
|
-
k: "secret"
|
190
|
-
)
|
191
|
-
jwk.to_key
|
192
|
-
# => String
|
193
|
-
```
|
52
|
+
For more details, read [Documentation Wiki](https://github.com/nov/json-jwt/wiki).
|
194
53
|
|
195
54
|
## Note on Patches/Pull Requests
|
196
55
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.5.0
|
data/lib/json/jose.rb
CHANGED
@@ -1,11 +1,46 @@
|
|
1
1
|
require 'securecompare'
|
2
2
|
|
3
3
|
module JSON
|
4
|
-
|
5
|
-
|
4
|
+
module JOSE
|
5
|
+
extend ActiveSupport::Concern
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
included do
|
8
|
+
extend ClassMethods
|
9
|
+
include SecureCompare
|
10
|
+
register_header_keys :alg, :jku, :jwk, :x5u, :x5t, :x5c, :kid, :typ, :cty, :crit
|
11
|
+
alias_method :algorithm, :alg
|
12
|
+
|
13
|
+
attr_accessor :header
|
14
|
+
def header
|
15
|
+
@header ||= {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def content_type
|
19
|
+
@content_type ||= 'application/jose'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
def register_header_keys(*keys)
|
25
|
+
keys.each do |header_key|
|
26
|
+
define_method header_key do
|
27
|
+
self.header[header_key]
|
28
|
+
end
|
29
|
+
define_method "#{header_key}=" do |value|
|
30
|
+
self.header[header_key] = value
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def decode(input, key_or_secret = nil)
|
36
|
+
if input.is_a? Hash
|
37
|
+
decode_json_serialized input, key_or_secret
|
38
|
+
else
|
39
|
+
decode_compact_serialized input, key_or_secret
|
40
|
+
end
|
41
|
+
rescue MultiJson::DecodeError
|
42
|
+
raise JWT::InvalidFormat.new("Invalid JSON Format")
|
43
|
+
end
|
9
44
|
end
|
10
45
|
end
|
11
46
|
end
|
data/lib/json/jwe.rb
CHANGED
@@ -2,13 +2,15 @@ require 'securerandom'
|
|
2
2
|
require 'bindata'
|
3
3
|
|
4
4
|
module JSON
|
5
|
-
class JWE
|
5
|
+
class JWE
|
6
6
|
class InvalidFormat < JWT::InvalidFormat; end
|
7
7
|
class DecryptionFailed < JWT::VerificationFailed; end
|
8
8
|
class UnexpectedAlgorithm < JWT::UnexpectedAlgorithm; end
|
9
9
|
|
10
10
|
NUM_OF_SEGMENTS = 5
|
11
11
|
|
12
|
+
include JOSE
|
13
|
+
|
12
14
|
attr_accessor(
|
13
15
|
:public_key_or_secret, :private_key_or_secret,
|
14
16
|
:plain_text, :cipher_text, :authentication_tag, :iv, :auth_data,
|
@@ -22,10 +24,6 @@ module JSON
|
|
22
24
|
self.plain_text = input.to_s
|
23
25
|
end
|
24
26
|
|
25
|
-
def content_type
|
26
|
-
'application/jose'
|
27
|
-
end
|
28
|
-
|
29
27
|
def encrypt!(public_key_or_secret)
|
30
28
|
self.public_key_or_secret = public_key_or_secret
|
31
29
|
cipher.encrypt
|
@@ -67,7 +65,7 @@ module JSON
|
|
67
65
|
ciphertext: UrlSafeBase64.encode64(cipher_text),
|
68
66
|
tag: UrlSafeBase64.encode64(authentication_tag)
|
69
67
|
}
|
70
|
-
|
68
|
+
else
|
71
69
|
{
|
72
70
|
protected: UrlSafeBase64.encode64(header.to_json),
|
73
71
|
encrypted_key: UrlSafeBase64.encode64(jwe_encrypted_key),
|
@@ -75,8 +73,6 @@ module JSON
|
|
75
73
|
ciphertext: UrlSafeBase64.encode64(cipher_text),
|
76
74
|
tag: UrlSafeBase64.encode64(authentication_tag)
|
77
75
|
}
|
78
|
-
else
|
79
|
-
super
|
80
76
|
end
|
81
77
|
end
|
82
78
|
|
data/lib/json/jws.rb
CHANGED
data/lib/json/jwt.rb
CHANGED
@@ -3,32 +3,21 @@ require 'url_safe_base64'
|
|
3
3
|
require 'multi_json'
|
4
4
|
require 'active_support'
|
5
5
|
require 'active_support/core_ext'
|
6
|
+
require 'json/jose'
|
6
7
|
|
7
8
|
module JSON
|
8
9
|
class JWT < ActiveSupport::HashWithIndifferentAccess
|
9
|
-
attr_accessor :
|
10
|
+
attr_accessor :signature
|
10
11
|
|
11
12
|
class Exception < StandardError; end
|
12
13
|
class InvalidFormat < Exception; end
|
13
14
|
class VerificationFailed < Exception; end
|
14
15
|
class UnexpectedAlgorithm < VerificationFailed; end
|
15
16
|
|
16
|
-
|
17
|
-
def register_header_keys(*keys)
|
18
|
-
keys.each do |header_key|
|
19
|
-
define_method header_key do
|
20
|
-
self.header[header_key]
|
21
|
-
end
|
22
|
-
define_method "#{header_key}=" do |value|
|
23
|
-
self.header[header_key] = value
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
register_header_keys :alg, :jku, :jwk, :x5u, :x5t, :x5c, :kid, :typ, :cty, :crit
|
29
|
-
alias_method :algorithm, :alg
|
17
|
+
include JOSE
|
30
18
|
|
31
19
|
def initialize(claims = {})
|
20
|
+
@content_type = 'application/jwt'
|
32
21
|
self.typ = :JWT
|
33
22
|
self.alg = :none
|
34
23
|
[:exp, :nbf, :iat].each do |key|
|
@@ -37,14 +26,6 @@ module JSON
|
|
37
26
|
update claims
|
38
27
|
end
|
39
28
|
|
40
|
-
def content_type
|
41
|
-
'application/jwt'
|
42
|
-
end
|
43
|
-
|
44
|
-
def header
|
45
|
-
@header ||= {}
|
46
|
-
end
|
47
|
-
|
48
29
|
def sign(private_key_or_secret, algorithm = :HS256)
|
49
30
|
jws = JWS.new self
|
50
31
|
jws.alg = algorithm
|
@@ -97,16 +78,6 @@ module JSON
|
|
97
78
|
end
|
98
79
|
|
99
80
|
class << self
|
100
|
-
def decode(input, key_or_secret = nil)
|
101
|
-
if input.is_a? Hash
|
102
|
-
decode_json_serialized input, key_or_secret
|
103
|
-
else
|
104
|
-
decode_compact_serialized input, key_or_secret
|
105
|
-
end
|
106
|
-
rescue MultiJson::DecodeError
|
107
|
-
raise InvalidFormat.new("Invalid JSON Format")
|
108
|
-
end
|
109
|
-
|
110
81
|
def decode_compact_serialized(jwt_string, key_or_secret)
|
111
82
|
case jwt_string.count('.') + 1
|
112
83
|
when JWS::NUM_OF_SEGMENTS
|
@@ -132,7 +103,6 @@ module JSON
|
|
132
103
|
end
|
133
104
|
end
|
134
105
|
|
135
|
-
require 'json/jose'
|
136
106
|
require 'json/jws'
|
137
107
|
require 'json/jwe'
|
138
108
|
require 'json/jwk'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json-jwt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nov matake
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-09-
|
11
|
+
date: 2015-09-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: multi_json
|