jwt 1.5.6 → 2.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/test.yml +74 -0
- data/.gitignore +1 -1
- data/.rspec +1 -0
- data/.rubocop.yml +95 -0
- data/.rubocop_todo.yml +191 -0
- data/.sourcelevel.yml +18 -0
- data/AUTHORS +101 -0
- data/Appraisals +10 -0
- data/CHANGELOG.md +349 -8
- data/Gemfile +2 -1
- data/README.md +225 -68
- data/Rakefile +4 -1
- data/lib/jwt.rb +14 -176
- data/lib/jwt/algos.rb +44 -0
- data/lib/jwt/algos/ecdsa.rb +35 -0
- data/lib/jwt/algos/eddsa.rb +23 -0
- data/lib/jwt/algos/hmac.rb +34 -0
- data/lib/jwt/algos/none.rb +15 -0
- data/lib/jwt/algos/ps.rb +43 -0
- data/lib/jwt/algos/rsa.rb +19 -0
- data/lib/jwt/algos/unsupported.rb +17 -0
- data/lib/jwt/base64.rb +19 -0
- data/lib/jwt/claims_validator.rb +35 -0
- data/lib/jwt/decode.rb +83 -31
- data/lib/jwt/default_options.rb +15 -0
- data/lib/jwt/encode.rb +69 -0
- data/lib/jwt/error.rb +6 -0
- data/lib/jwt/json.rb +10 -9
- data/lib/jwt/jwk.rb +51 -0
- data/lib/jwt/jwk/ec.rb +150 -0
- data/lib/jwt/jwk/hmac.rb +58 -0
- data/lib/jwt/jwk/key_base.rb +18 -0
- data/lib/jwt/jwk/key_finder.rb +62 -0
- data/lib/jwt/jwk/rsa.rb +115 -0
- data/lib/jwt/security_utils.rb +57 -0
- data/lib/jwt/signature.rb +39 -0
- data/lib/jwt/verify.rb +45 -53
- data/lib/jwt/version.rb +3 -3
- data/ruby-jwt.gemspec +6 -8
- metadata +39 -95
- data/.codeclimate.yml +0 -20
- data/.travis.yml +0 -13
- data/Manifest +0 -8
- data/spec/fixtures/certs/ec256-private.pem +0 -8
- data/spec/fixtures/certs/ec256-public.pem +0 -4
- data/spec/fixtures/certs/ec256-wrong-private.pem +0 -8
- data/spec/fixtures/certs/ec256-wrong-public.pem +0 -4
- data/spec/fixtures/certs/ec384-private.pem +0 -9
- data/spec/fixtures/certs/ec384-public.pem +0 -5
- data/spec/fixtures/certs/ec384-wrong-private.pem +0 -9
- data/spec/fixtures/certs/ec384-wrong-public.pem +0 -5
- data/spec/fixtures/certs/ec512-private.pem +0 -10
- data/spec/fixtures/certs/ec512-public.pem +0 -6
- data/spec/fixtures/certs/ec512-wrong-private.pem +0 -10
- data/spec/fixtures/certs/ec512-wrong-public.pem +0 -6
- data/spec/fixtures/certs/rsa-1024-private.pem +0 -15
- data/spec/fixtures/certs/rsa-1024-public.pem +0 -6
- data/spec/fixtures/certs/rsa-2048-private.pem +0 -27
- data/spec/fixtures/certs/rsa-2048-public.pem +0 -9
- data/spec/fixtures/certs/rsa-2048-wrong-private.pem +0 -27
- data/spec/fixtures/certs/rsa-2048-wrong-public.pem +0 -9
- data/spec/fixtures/certs/rsa-4096-private.pem +0 -51
- data/spec/fixtures/certs/rsa-4096-public.pem +0 -14
- data/spec/integration/readme_examples_spec.rb +0 -190
- data/spec/jwt/verify_spec.rb +0 -197
- data/spec/jwt_spec.rb +0 -240
- data/spec/spec_helper.rb +0 -31
@@ -1,9 +0,0 @@
|
|
1
|
-
-----BEGIN PUBLIC KEY-----
|
2
|
-
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4GzZTLU48c4WbyvHi+QK
|
3
|
-
rB71x+T0eq5hqDbQqnlYjhD1Ika7io1iplsdJWJuyxfYbUkb2Ol0fj4koZ/GS6lg
|
4
|
-
CZr4+8UHbr1qf0Eu5HZSpszs2YxY8U5RHnrpw67co7hlgAR9HbyNf5XIYgLV9ldH
|
5
|
-
H/eazwnc3F/hgNsV0xjScVilejgocJ4zcsyymvW8t42lteM7bI867ZuJhGop/V+Y
|
6
|
-
0HFyrMsPoQyLuCUpr6ulOfrkr7ZOdhAIG8r1HcjOp/AUjM15vfXcbUZjkM/Vloif
|
7
|
-
X1YitU3upMGJ8/DpFGffMOImrn5r6BT494V8rRyN2qvQoAkLJpqZ0avLxwiR2lgV
|
8
|
-
QQIDAQAB
|
9
|
-
-----END PUBLIC KEY-----
|
@@ -1,27 +0,0 @@
|
|
1
|
-
-----BEGIN RSA PRIVATE KEY-----
|
2
|
-
MIIEpAIBAAKCAQEAzHAVGaW9j4l3/b4ngcjjoIoIcnsQEWOMqErb5VhLZMGIq1gE
|
3
|
-
O5qxPDAwooKsNotzcAOB3ZyLn7p5D+dmOrNUYkYWgYITNGeSifrnVqQugd5Fh1L8
|
4
|
-
K7zOGltUo2UtjbN4uJ56tzxBMZp2wejs2/Qu0eu0xZK3To+YkDcWOk92rmNgmUSQ
|
5
|
-
C/kNyIOj+yBvOo3wTk6HvbhoIarCgJ6Lay1v/hMLyQLzwRY/Qfty1FTIDyTv2dch
|
6
|
-
47FsfkZ1KAL+MbUnHuCBPzGxRjXa8Iy9Z7YGxrYasUt1b0um64bscxoIiCu8yLL8
|
7
|
-
jlg01Rwrjr/MTwKRhwXlMp8B7HTonwtaG6arJwIDAQABAoIBAGFR4dmJusl/qW1T
|
8
|
-
fj8cQLAFxaupxaZhe24J5NAyzgEy2Dqo9ariIwkB78UM66ozjEqAgOvcP+NTw5m8
|
9
|
-
kD/VapA1yTTxlO7XdzzUAhiOo80S4IphCMZRZNPLMmluGtdf3lIUr1pXBrn0TCBX
|
10
|
-
H5o9jaREzpNXGof9d6T/dEdh2J9+uE/p1xE5GSxQfaPheZzCG7636La/DcArg/UR
|
11
|
-
+TusPqp62BEmk96pE/KKJRmEeH+WnPfSh6sMpLxi3hkEU7AynpliGT6Z6xV4csBI
|
12
|
-
S/rdpkcj5DWpbnQzkwdrnL2Q+POEq/vlx5/NlezvtQPNLvQWDyY4yBCoMKGb3EbX
|
13
|
-
xrxP7MECgYEA/kwe4P0Mqk+087IyhjDBGPfcMt8gfYc9nzNfIYSWdSwuSag/hqHq
|
14
|
-
I4GwHQzUV9ix3iM6w5hin10yAzWxCYZg9hquV+lSvNNpGB76FX6oOqwuAhyQMRwv
|
15
|
-
eW+VUyfFXeJugwL5JuIaNTvwPpQVDHYtELLifie+uzJ5HC6dhg/XchcCgYEAzc5/
|
16
|
-
+IXjOlExd/mBgFk/5Y87ifA0ZOgbaJXifYgU0aNSgz1piHxU3n2p4jJ9lSdwwCl2
|
17
|
-
Fb5EN7666t20PL5QcXJ5ZdaTRLzRlYiqTWzfYHBgttbB1Jl3Ed9GsKuzRgaRqGFC
|
18
|
-
ANJSqZlKG0NZ3keRtuKdFwq+IVOnsQr9g0TZiXECgYEAqUgtCiMKCloTIGMQpSnR
|
19
|
-
cXiWWjsUmturls4Q1vQ3YHrvuVLKLyqb/dT4Uu5WcMAs765OESThCit0/pQAbVHK
|
20
|
-
PCpYwubskAzAGjGM00BEZwJ1gixXhIm5xMIWCowgI7Z3ULlq+IptXeCvtkjHlksZ
|
21
|
-
BtO+WLLGkkEwRCV38WWcSzMCgYA/Xxqgl/mD94RYAQgTUWgPc69Nph08BQyLg7ue
|
22
|
-
E8z1UGkT6FEaqc4oRGGPOSTaTK63PQ0TXOb8k0pTD7l0CtYSWMFwzkXCoLGYbeCi
|
23
|
-
vqd5tqDRLAe7QxYa9rl5pSUqptMrGeeNATZa6sya4H5Hp5oCyny8n54z/OJh7ZRq
|
24
|
-
W0TwwQKBgQDDP7ksm2pcqadaVAmODdOlaDHbaEcxp8wN7YVz0lM3UpJth96ukbj7
|
25
|
-
S39eJhXYWOn6oJQb/lN9fGOYqjg3y6IchGZDp67ATvWYvn/NY0R7mt4K4oHx5TuN
|
26
|
-
rSQlP3WmOGv8Kemw892uRfW/jZyBEHhsfS213WDttVPn9F635GdNWw==
|
27
|
-
-----END RSA PRIVATE KEY-----
|
@@ -1,9 +0,0 @@
|
|
1
|
-
-----BEGIN PUBLIC KEY-----
|
2
|
-
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzHAVGaW9j4l3/b4ngcjj
|
3
|
-
oIoIcnsQEWOMqErb5VhLZMGIq1gEO5qxPDAwooKsNotzcAOB3ZyLn7p5D+dmOrNU
|
4
|
-
YkYWgYITNGeSifrnVqQugd5Fh1L8K7zOGltUo2UtjbN4uJ56tzxBMZp2wejs2/Qu
|
5
|
-
0eu0xZK3To+YkDcWOk92rmNgmUSQC/kNyIOj+yBvOo3wTk6HvbhoIarCgJ6Lay1v
|
6
|
-
/hMLyQLzwRY/Qfty1FTIDyTv2dch47FsfkZ1KAL+MbUnHuCBPzGxRjXa8Iy9Z7YG
|
7
|
-
xrYasUt1b0um64bscxoIiCu8yLL8jlg01Rwrjr/MTwKRhwXlMp8B7HTonwtaG6ar
|
8
|
-
JwIDAQAB
|
9
|
-
-----END PUBLIC KEY-----
|
@@ -1,51 +0,0 @@
|
|
1
|
-
-----BEGIN RSA PRIVATE KEY-----
|
2
|
-
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
-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
-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
-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
-
ocm7bjZCwbJGMm7orLViqWfsFX3O35PeoJ5h/7uJ7iRwvTFERkTdwWP/0BeKBeIt
|
7
|
-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
-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
-
yedJJYxLjwhHJwtzFAeaq18H3O791YKhjAJ6YxK3zJ59jTE6Pkvqjq183f2PGHVR
|
10
|
-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
-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
-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
-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
-
FO90iR7t8hFWYHqjf/k9eCtDdi164MGukYJqgVoQG6kYLLgCfI21DMlJk9otLFtu
|
15
|
-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
-
cFadMtoXr/ZvxJrIZgkddJ7snGHjBcP5DCkgM7MZy6aoilWv1/UNrOF9MdgNA9zz
|
17
|
-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
-
6lGFj7c2mv7PCpJRVgbVGL/RTVVap/+jbcRVLdnYKsII/dANG7iXnfwRgkLWet5D
|
19
|
-
OOsPuvIuyiSaJIwcdRE3SSO+tZhKLt+gh/oLxBPw5Ex0FwsVTtYn3Q/X3EAx+Wph
|
20
|
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-
V13mHA8XBQ25OW2K7BGJhMHdbuvTnl6jsOfC4+t7P2bUAYxoP6/ncxTzZ5OlBN5k
|
48
|
-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
-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
-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
|
51
|
-
-----END RSA PRIVATE KEY-----
|
@@ -1,14 +0,0 @@
|
|
1
|
-
-----BEGIN PUBLIC KEY-----
|
2
|
-
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqETmgWBi5rCmb7euJplA
|
3
|
-
/9xs65+bncc9Yvs5zjyycXSW82JfRuyguGm0OvA2wog24dR4N2kT/87DcGtp5JqJ
|
4
|
-
WADVFNr+2V2r6i57/OMLruRpn3p2r95dmo0COE+BxPFl7XEBT8JbH57ZtpgcB3/x
|
5
|
-
kS14nLOWFf96hrXPlXJC+VMVKVZmA8k2LRh42vT5wUf4U0Doy/p7yFNSFFa6Q8ww
|
6
|
-
e4TBy/z/f+rhFD1w8rxlYjallee/ocm7bjZCwbJGMm7orLViqWfsFX3O35PeoJ5h
|
7
|
-
/7uJ7iRwvTFERkTdwWP/0BeKBeItBR3YFc2mut+V9W+WKRkMSL6Crc+oVSx3p8aB
|
8
|
-
7j9SZFzQiRtes4BYETpX1xl2mgIq5hvsFbLw7ESrlIodiwUMTrSIid2DQ6q80kv1
|
9
|
-
zXPr4+Id6L0sJLxPCaXnTmNtasSwyedJJYxLjwhHJwtzFAeaq18H3O791YKhjAJ6
|
10
|
-
YxK3zJ59jTE6Pkvqjq183f2PGHVRvgSN7aCmI6MBUUB5wDP2K8zX2sh40/uPDVSd
|
11
|
-
6ei1vl3DpPk+h8iExx6AzbohfqZ+5RUUNx127L3MaQvOVC5TxV+R99gwKW++wzcV
|
12
|
-
uO3m2KqVUj+K1uYBy3KBCUMBbckpEWGbN++jcdV5oJX6fsC66nOmKlntYwCL/pRw
|
13
|
-
w+oLsbzF8J3dxeDbKNF9JDsCAwEAAQ==
|
14
|
-
-----END PUBLIC KEY-----
|
@@ -1,190 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require_relative '../spec_helper'
|
3
|
-
require 'jwt'
|
4
|
-
|
5
|
-
describe 'README.md code test' do
|
6
|
-
context 'algorithm usage' do
|
7
|
-
let(:payload) { { data: 'test' } }
|
8
|
-
|
9
|
-
it 'NONE' do
|
10
|
-
token = JWT.encode payload, nil, 'none'
|
11
|
-
decoded_token = JWT.decode token, nil, false
|
12
|
-
|
13
|
-
expect(token).to eq 'eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJkYXRhIjoidGVzdCJ9.'
|
14
|
-
expect(decoded_token).to eq [
|
15
|
-
{ 'data' => 'test' },
|
16
|
-
{ 'typ' => 'JWT', 'alg' => 'none' }
|
17
|
-
]
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'HMAC' do
|
21
|
-
token = JWT.encode payload, 'my$ecretK3y', 'HS256'
|
22
|
-
decoded_token = JWT.decode token, 'my$ecretK3y', false
|
23
|
-
|
24
|
-
expect(token).to eq 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.ZxW8go9hz3ETCSfxFxpwSkYg_602gOPKearsf6DsxgY'
|
25
|
-
expect(decoded_token).to eq [
|
26
|
-
{ 'data' => 'test' },
|
27
|
-
{ 'typ' => 'JWT', 'alg' => 'HS256' }
|
28
|
-
]
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'RSA' do
|
32
|
-
rsa_private = OpenSSL::PKey::RSA.generate 2048
|
33
|
-
rsa_public = rsa_private.public_key
|
34
|
-
|
35
|
-
token = JWT.encode payload, rsa_private, 'RS256'
|
36
|
-
decoded_token = JWT.decode token, rsa_public, true, algorithm: 'RS256'
|
37
|
-
|
38
|
-
expect(decoded_token).to eq [
|
39
|
-
{ 'data' => 'test' },
|
40
|
-
{ 'typ' => 'JWT', 'alg' => 'RS256' }
|
41
|
-
]
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'ECDSA' do
|
45
|
-
ecdsa_key = OpenSSL::PKey::EC.new 'prime256v1'
|
46
|
-
ecdsa_key.generate_key
|
47
|
-
ecdsa_public = OpenSSL::PKey::EC.new ecdsa_key
|
48
|
-
ecdsa_public.private_key = nil
|
49
|
-
|
50
|
-
token = JWT.encode payload, ecdsa_key, 'ES256'
|
51
|
-
decoded_token = JWT.decode token, ecdsa_public, true, algorithm: 'ES256'
|
52
|
-
|
53
|
-
expect(decoded_token).to eq [
|
54
|
-
{ 'data' => 'test' },
|
55
|
-
{ 'typ' => 'JWT', 'alg' => 'ES256' }
|
56
|
-
]
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
context 'claims' do
|
61
|
-
let(:hmac_secret) { 'MyP4ssW0rD' }
|
62
|
-
|
63
|
-
context 'exp' do
|
64
|
-
it 'without leeway' do
|
65
|
-
exp = Time.now.to_i + 4 * 3600
|
66
|
-
exp_payload = { data: 'data', exp: exp }
|
67
|
-
|
68
|
-
token = JWT.encode exp_payload, hmac_secret, 'HS256'
|
69
|
-
|
70
|
-
expect do
|
71
|
-
JWT.decode token, hmac_secret, true, algorithm: 'HS256'
|
72
|
-
end.not_to raise_error
|
73
|
-
end
|
74
|
-
|
75
|
-
it 'with leeway' do
|
76
|
-
exp = Time.now.to_i - 10
|
77
|
-
leeway = 30 # seconds
|
78
|
-
|
79
|
-
exp_payload = { data: 'data', exp: exp }
|
80
|
-
|
81
|
-
token = JWT.encode exp_payload, hmac_secret, 'HS256'
|
82
|
-
|
83
|
-
expect do
|
84
|
-
JWT.decode token, hmac_secret, true, leeway: leeway, algorithm: 'HS256'
|
85
|
-
end.not_to raise_error
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
context 'nbf' do
|
90
|
-
it 'without leeway' do
|
91
|
-
nbf = Time.now.to_i - 3600
|
92
|
-
nbf_payload = { data: 'data', nbf: nbf }
|
93
|
-
token = JWT.encode nbf_payload, hmac_secret, 'HS256'
|
94
|
-
|
95
|
-
expect do
|
96
|
-
JWT.decode token, hmac_secret, true, algorithm: 'HS256'
|
97
|
-
end.not_to raise_error
|
98
|
-
end
|
99
|
-
|
100
|
-
it 'with leeway' do
|
101
|
-
nbf = Time.now.to_i + 10
|
102
|
-
leeway = 30
|
103
|
-
nbf_payload = { data: 'data', nbf: nbf }
|
104
|
-
token = JWT.encode nbf_payload, hmac_secret, 'HS256'
|
105
|
-
|
106
|
-
expect do
|
107
|
-
JWT.decode token, hmac_secret, true, leeway: leeway, algorithm: 'HS256'
|
108
|
-
end.not_to raise_error
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
it 'iss' do
|
113
|
-
iss = 'My Awesome Company Inc. or https://my.awesome.website/'
|
114
|
-
iss_payload = { data: 'data', iss: iss }
|
115
|
-
|
116
|
-
token = JWT.encode iss_payload, hmac_secret, 'HS256'
|
117
|
-
|
118
|
-
expect do
|
119
|
-
JWT.decode token, hmac_secret, true, iss: iss, algorithm: 'HS256'
|
120
|
-
end.not_to raise_error
|
121
|
-
end
|
122
|
-
|
123
|
-
context 'aud' do
|
124
|
-
it 'array' do
|
125
|
-
aud = %w(Young Old)
|
126
|
-
aud_payload = { data: 'data', aud: aud }
|
127
|
-
|
128
|
-
token = JWT.encode aud_payload, hmac_secret, 'HS256'
|
129
|
-
|
130
|
-
expect do
|
131
|
-
JWT.decode token, hmac_secret, true, aud: %w(Old Young), verify_aud: true, algorithm: 'HS256'
|
132
|
-
end.not_to raise_error
|
133
|
-
end
|
134
|
-
|
135
|
-
it 'string' do
|
136
|
-
expect do
|
137
|
-
end.not_to raise_error
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
it 'jti' do
|
142
|
-
iat = Time.now.to_i
|
143
|
-
hmac_secret = 'test'
|
144
|
-
jti_raw = [hmac_secret, iat].join(':').to_s
|
145
|
-
jti = Digest::MD5.hexdigest(jti_raw)
|
146
|
-
jti_payload = { data: 'data', iat: iat, jti: jti }
|
147
|
-
|
148
|
-
token = JWT.encode jti_payload, hmac_secret, 'HS256'
|
149
|
-
|
150
|
-
expect do
|
151
|
-
JWT.decode token, hmac_secret, true, verify_jti: true, algorithm: 'HS256'
|
152
|
-
end.not_to raise_error
|
153
|
-
end
|
154
|
-
|
155
|
-
context 'iat' do
|
156
|
-
it 'without leeway' do
|
157
|
-
iat = Time.now.to_i
|
158
|
-
iat_payload = { data: 'data', iat: iat }
|
159
|
-
|
160
|
-
token = JWT.encode iat_payload, hmac_secret, 'HS256'
|
161
|
-
|
162
|
-
expect do
|
163
|
-
JWT.decode token, hmac_secret, true, verify_iat: true, algorithm: 'HS256'
|
164
|
-
end.not_to raise_error
|
165
|
-
end
|
166
|
-
|
167
|
-
it 'with leeway' do
|
168
|
-
iat = Time.now.to_i - 7
|
169
|
-
iat_payload = { data: 'data', iat: iat, leeway: 10 }
|
170
|
-
|
171
|
-
token = JWT.encode iat_payload, hmac_secret, 'HS256'
|
172
|
-
|
173
|
-
expect do
|
174
|
-
JWT.decode token, hmac_secret, true, verify_iat: true, algorithm: 'HS256'
|
175
|
-
end.not_to raise_error
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
it 'sub' do
|
180
|
-
sub = 'Subject'
|
181
|
-
sub_payload = { data: 'data', sub: sub }
|
182
|
-
|
183
|
-
token = JWT.encode sub_payload, hmac_secret, 'HS256'
|
184
|
-
|
185
|
-
expect do
|
186
|
-
JWT.decode token, hmac_secret, true, 'sub' => sub, :verify_sub => true, :algorithm => 'HS256'
|
187
|
-
end.not_to raise_error
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
data/spec/jwt/verify_spec.rb
DELETED
@@ -1,197 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'spec_helper'
|
3
|
-
require 'jwt/verify'
|
4
|
-
|
5
|
-
module JWT
|
6
|
-
RSpec.describe Verify do
|
7
|
-
let(:base_payload) { { 'user_id' => 'some@user.tld' } }
|
8
|
-
let(:options) { { leeway: 0 } }
|
9
|
-
|
10
|
-
context '.verify_aud(payload, options)' do
|
11
|
-
let(:scalar_aud) { 'ruby-jwt-audience' }
|
12
|
-
let(:array_aud) { %w(ruby-jwt-aud test-aud ruby-ruby-ruby) }
|
13
|
-
let(:scalar_payload) { base_payload.merge('aud' => scalar_aud) }
|
14
|
-
let(:array_payload) { base_payload.merge('aud' => array_aud) }
|
15
|
-
|
16
|
-
it 'must raise JWT::InvalidAudError when the singular audience does not match' do
|
17
|
-
expect do
|
18
|
-
Verify.verify_aud(scalar_payload, options.merge(aud: 'no-match'))
|
19
|
-
end.to raise_error JWT::InvalidAudError
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'must raise JWT::InvalidAudError when the payload has an array and none match the supplied value' do
|
23
|
-
expect do
|
24
|
-
Verify.verify_aud(array_payload, options.merge(aud: 'no-match'))
|
25
|
-
end.to raise_error JWT::InvalidAudError
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'must raise JWT::InvalidAudError when the singular audience does not match and the options aud key is a string' do
|
29
|
-
expect do
|
30
|
-
Verify.verify_aud(scalar_payload, options.merge('aud' => 'no-match'))
|
31
|
-
end.to raise_error JWT::InvalidAudError
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'must allow a matching singular audience to pass' do
|
35
|
-
Verify.verify_aud(scalar_payload, options.merge(aud: scalar_aud))
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'must allow a matching audence to pass when the options key is a string' do
|
39
|
-
Verify.verify_aud(scalar_payload, options.merge('aud' => scalar_aud))
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'must allow an array with any value matching the one in the options' do
|
43
|
-
Verify.verify_aud(array_payload, options.merge(aud: array_aud.first))
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'must allow an array with any value matching the one in the options with a string options key' do
|
47
|
-
Verify.verify_aud(array_payload, options.merge('aud' => array_aud.first))
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'should allow strings or symbolds in options array' do
|
51
|
-
options['aud'] = [
|
52
|
-
'ruby-jwt-aud',
|
53
|
-
'test-aud',
|
54
|
-
'ruby-ruby-ruby',
|
55
|
-
:test
|
56
|
-
]
|
57
|
-
|
58
|
-
array_payload['aud'].push('test')
|
59
|
-
|
60
|
-
Verify.verify_aud(array_payload, options)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
context '.verify_expiration(payload, options)' do
|
65
|
-
let(:leeway) { 10 }
|
66
|
-
let(:payload) { base_payload.merge('exp' => (Time.now.to_i - 5)) }
|
67
|
-
|
68
|
-
it 'must raise JWT::ExpiredSignature when the token has expired' do
|
69
|
-
expect do
|
70
|
-
Verify.verify_expiration(payload, options)
|
71
|
-
end.to raise_error JWT::ExpiredSignature
|
72
|
-
end
|
73
|
-
|
74
|
-
it 'must allow some leeway in the expiration when configured' do
|
75
|
-
Verify.verify_expiration(payload, options.merge(leeway: 10))
|
76
|
-
end
|
77
|
-
|
78
|
-
it 'must be expired if the exp claim equals the current time' do
|
79
|
-
payload['exp'] = Time.now.to_i
|
80
|
-
|
81
|
-
expect do
|
82
|
-
Verify.verify_expiration(payload, options)
|
83
|
-
end.to raise_error JWT::ExpiredSignature
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
context '.verify_iat(payload, options)' do
|
88
|
-
let(:iat) { Time.now.to_f }
|
89
|
-
let(:payload) { base_payload.merge('iat' => iat) }
|
90
|
-
|
91
|
-
it 'must allow a valid iat' do
|
92
|
-
Verify.verify_iat(payload, options)
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'must allow configured leeway' do
|
96
|
-
Verify.verify_iat(payload.merge('iat' => (iat + 60)), options.merge(leeway: 70))
|
97
|
-
end
|
98
|
-
|
99
|
-
it 'must properly handle integer times' do
|
100
|
-
Verify.verify_iat(payload.merge('iat' => Time.now.to_i), options)
|
101
|
-
end
|
102
|
-
|
103
|
-
it 'must raise JWT::InvalidIatError when the iat value is not Numeric' do
|
104
|
-
expect do
|
105
|
-
Verify.verify_iat(payload.merge('iat' => 'not a number'), options)
|
106
|
-
end.to raise_error JWT::InvalidIatError
|
107
|
-
end
|
108
|
-
|
109
|
-
it 'must raise JWT::InvalidIatError when the iat value is in the future' do
|
110
|
-
expect do
|
111
|
-
Verify.verify_iat(payload.merge('iat' => (iat + 120)), options)
|
112
|
-
end.to raise_error JWT::InvalidIatError
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
context '.verify_iss(payload, options)' do
|
117
|
-
let(:iss) { 'ruby-jwt-gem' }
|
118
|
-
let(:payload) { base_payload.merge('iss' => iss) }
|
119
|
-
|
120
|
-
let(:invalid_token) { JWT.encode base_payload, payload[:secret] }
|
121
|
-
|
122
|
-
it 'must raise JWT::InvalidIssuerError when the configured issuer does not match the payload issuer' do
|
123
|
-
expect do
|
124
|
-
Verify.verify_iss(payload, options.merge(iss: 'mismatched-issuer'))
|
125
|
-
end.to raise_error JWT::InvalidIssuerError
|
126
|
-
end
|
127
|
-
|
128
|
-
it 'must raise JWT::InvalidIssuerError when the payload does not include an issuer' do
|
129
|
-
expect do
|
130
|
-
Verify.verify_iss(base_payload, options.merge(iss: iss))
|
131
|
-
end.to raise_error(JWT::InvalidIssuerError, /received <none>/)
|
132
|
-
end
|
133
|
-
|
134
|
-
it 'must allow a matching issuer to pass' do
|
135
|
-
Verify.verify_iss(payload, options.merge(iss: iss))
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
context '.verify_jti(payload, options)' do
|
140
|
-
let(:payload) { base_payload.merge('jti' => 'some-random-uuid-or-whatever') }
|
141
|
-
|
142
|
-
it 'must allow any jti when the verfy_jti key in the options is truthy but not a proc' do
|
143
|
-
Verify.verify_jti(payload, options.merge(verify_jti: true))
|
144
|
-
end
|
145
|
-
|
146
|
-
it 'must raise JWT::InvalidJtiError when the jti is missing' do
|
147
|
-
expect do
|
148
|
-
Verify.verify_jti(base_payload, options)
|
149
|
-
end.to raise_error JWT::InvalidJtiError, /missing/i
|
150
|
-
end
|
151
|
-
|
152
|
-
it 'must raise JWT::InvalidJtiError when the jti is an empty string' do
|
153
|
-
expect do
|
154
|
-
Verify.verify_jti(base_payload.merge('jti' => ' '), options)
|
155
|
-
end.to raise_error JWT::InvalidJtiError, /missing/i
|
156
|
-
end
|
157
|
-
|
158
|
-
it 'must raise JWT::InvalidJtiError when verify_jti proc returns false' do
|
159
|
-
expect do
|
160
|
-
Verify.verify_jti(payload, options.merge(verify_jti: ->(_jti) { false }))
|
161
|
-
end.to raise_error JWT::InvalidJtiError, /invalid/i
|
162
|
-
end
|
163
|
-
|
164
|
-
it 'true proc should not raise JWT::InvalidJtiError' do
|
165
|
-
Verify.verify_jti(payload, options.merge(verify_jti: ->(_jti) { true }))
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
context '.verify_not_before(payload, options)' do
|
170
|
-
let(:payload) { base_payload.merge('nbf' => (Time.now.to_i + 5)) }
|
171
|
-
|
172
|
-
it 'must raise JWT::ImmatureSignature when the nbf in the payload is in the future' do
|
173
|
-
expect do
|
174
|
-
Verify.verify_not_before(payload, options)
|
175
|
-
end.to raise_error JWT::ImmatureSignature
|
176
|
-
end
|
177
|
-
|
178
|
-
it 'must allow some leeway in the token age when configured' do
|
179
|
-
Verify.verify_not_before(payload, options.merge(leeway: 10))
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
context '.verify_sub(payload, options)' do
|
184
|
-
let(:sub) { 'ruby jwt subject' }
|
185
|
-
|
186
|
-
it 'must raise JWT::InvalidSubError when the subjects do not match' do
|
187
|
-
expect do
|
188
|
-
Verify.verify_sub(base_payload.merge('sub' => 'not-a-match'), options.merge(sub: sub))
|
189
|
-
end.to raise_error JWT::InvalidSubError
|
190
|
-
end
|
191
|
-
|
192
|
-
it 'must allow a matching sub' do
|
193
|
-
Verify.verify_sub(base_payload.merge('sub' => sub), options.merge(sub: sub))
|
194
|
-
end
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|