json-jwt 1.4.0 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
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
|