jwt 1.5.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +20 -0
  3. data/.ebert.yml +18 -0
  4. data/.gitignore +11 -0
  5. data/.reek.yml +40 -0
  6. data/.rspec +1 -0
  7. data/.rubocop.yml +98 -0
  8. data/.travis.yml +14 -0
  9. data/CHANGELOG.md +476 -0
  10. data/Gemfile +3 -0
  11. data/LICENSE +7 -0
  12. data/Manifest +3 -1
  13. data/README.md +478 -0
  14. data/Rakefile +8 -15
  15. data/lib/jwt/algos/ecdsa.rb +35 -0
  16. data/lib/jwt/algos/eddsa.rb +23 -0
  17. data/lib/jwt/algos/hmac.rb +33 -0
  18. data/lib/jwt/algos/rsa.rb +19 -0
  19. data/lib/jwt/algos/unsupported.rb +16 -0
  20. data/lib/jwt/decode.rb +49 -0
  21. data/lib/jwt/default_options.rb +15 -0
  22. data/lib/jwt/encode.rb +51 -0
  23. data/lib/jwt/error.rb +16 -0
  24. data/lib/jwt/security_utils.rb +51 -0
  25. data/lib/jwt/signature.rb +50 -0
  26. data/lib/jwt/verify.rb +102 -0
  27. data/lib/jwt/version.rb +24 -0
  28. data/lib/jwt.rb +33 -203
  29. data/ruby-jwt.gemspec +31 -0
  30. data/spec/fixtures/certs/ec256-private.pem +8 -0
  31. data/spec/fixtures/certs/ec256-public.pem +4 -0
  32. data/spec/fixtures/certs/ec256-wrong-private.pem +8 -0
  33. data/spec/fixtures/certs/ec256-wrong-public.pem +4 -0
  34. data/spec/fixtures/certs/ec384-private.pem +9 -0
  35. data/spec/fixtures/certs/ec384-public.pem +5 -0
  36. data/spec/fixtures/certs/ec384-wrong-private.pem +9 -0
  37. data/spec/fixtures/certs/ec384-wrong-public.pem +5 -0
  38. data/spec/fixtures/certs/ec512-private.pem +10 -0
  39. data/spec/fixtures/certs/ec512-public.pem +6 -0
  40. data/spec/fixtures/certs/ec512-wrong-private.pem +10 -0
  41. data/spec/fixtures/certs/ec512-wrong-public.pem +6 -0
  42. data/spec/fixtures/certs/rsa-1024-private.pem +15 -0
  43. data/spec/fixtures/certs/rsa-1024-public.pem +6 -0
  44. data/spec/fixtures/certs/rsa-2048-private.pem +27 -0
  45. data/spec/fixtures/certs/rsa-2048-public.pem +9 -0
  46. data/spec/fixtures/certs/rsa-2048-wrong-private.pem +27 -0
  47. data/spec/fixtures/certs/rsa-2048-wrong-public.pem +9 -0
  48. data/spec/fixtures/certs/rsa-4096-private.pem +51 -0
  49. data/spec/fixtures/certs/rsa-4096-public.pem +14 -0
  50. data/spec/integration/readme_examples_spec.rb +202 -0
  51. data/spec/jwt/verify_spec.rb +232 -0
  52. data/spec/jwt_spec.rb +236 -384
  53. data/spec/spec_helper.rb +28 -0
  54. metadata +187 -26
  55. data/jwt.gemspec +0 -34
  56. data/lib/jwt/json.rb +0 -32
  57. data/spec/helper.rb +0 -19
@@ -0,0 +1,5 @@
1
+ -----BEGIN PUBLIC KEY-----
2
+ MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEMF5MeARQRi1285ecla38Su3q/IUot/Ig
3
+ xCtvu3Ha0dd+1p+SVJy+Fk8F085MlIHwTi97BzaM8H4FNNxg/xDlBCqs7CCYs9nG
4
+ z2xQC3eIUvvE+LMwy1QvSZdVupNAgLZj
5
+ -----END PUBLIC KEY-----
@@ -0,0 +1,10 @@
1
+ -----BEGIN EC PARAMETERS-----
2
+ BgUrgQQAIw==
3
+ -----END EC PARAMETERS-----
4
+ -----BEGIN EC PRIVATE KEY-----
5
+ MIHcAgEBBEIB0/+ffxEj7j62xvGaB5pvzk888e412ESO/EK/K0QlS9dSF8+Rj1rG
6
+ zqpRB8fvDnoe8xdmkW/W5GKzojMyv7YQYumgBwYFK4EEACOhgYkDgYYABAEw74Yw
7
+ aTbPY6TtWmxx6LJDzCX2nKWCPnKdZcEH9Ncu8g5RjRBRq2yacja3OoS6nA2YeDng
8
+ reBJxZr376P6Ns6XcQFWDA6K/MCTrEBCsPxXZNxd8KR9vMGWhgNtWRrcKzwJfQkr
9
+ suyehZkbbYyFnAWyARKHZuV7VUXmeEmRS/f93MPqVA==
10
+ -----END EC PRIVATE KEY-----
@@ -0,0 +1,6 @@
1
+ -----BEGIN PUBLIC KEY-----
2
+ MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBMO+GMGk2z2Ok7VpsceiyQ8wl9pyl
3
+ gj5ynWXBB/TXLvIOUY0QUatsmnI2tzqEupwNmHg54K3gScWa9++j+jbOl3EBVgwO
4
+ ivzAk6xAQrD8V2TcXfCkfbzBloYDbVka3Cs8CX0JK7LsnoWZG22MhZwFsgESh2bl
5
+ e1VF5nhJkUv3/dzD6lQ=
6
+ -----END PUBLIC KEY-----
@@ -0,0 +1,10 @@
1
+ -----BEGIN EC PARAMETERS-----
2
+ BgUrgQQAIw==
3
+ -----END EC PARAMETERS-----
4
+ -----BEGIN EC PRIVATE KEY-----
5
+ MIHbAgEBBEG/KbA2oCbiCT6L3V8XSz2WKBy0XhGvIFbl/ZkXIXnkYt+1B7wViSVo
6
+ KCHuMFsi6xU/5nE1EuDG2UsQJmKeAMkIOKAHBgUrgQQAI6GBiQOBhgAEAG0TFWe5
7
+ cZ5DZIyfuysrCoQySTNxd+aT8sPIxsx7mW6YBTsuO6rEgxyegd2Auy4xtikxpzKv
8
+ soMXR02999Aaus2jAAt/wxrhhr41BDP4MV0b6Zngb72hna0pcGqit5OyU8AbOJUZ
9
+ +rdyowRGsOY+aPbOyVhdNcsEdxYC8GdIyCQLBC1H
10
+ -----END EC PRIVATE KEY-----
@@ -0,0 +1,6 @@
1
+ -----BEGIN PUBLIC KEY-----
2
+ MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAbRMVZ7lxnkNkjJ+7KysKhDJJM3F3
3
+ 5pPyw8jGzHuZbpgFOy47qsSDHJ6B3YC7LjG2KTGnMq+ygxdHTb330Bq6zaMAC3/D
4
+ GuGGvjUEM/gxXRvpmeBvvaGdrSlwaqK3k7JTwBs4lRn6t3KjBEaw5j5o9s7JWF01
5
+ ywR3FgLwZ0jIJAsELUc=
6
+ -----END PUBLIC KEY-----
@@ -0,0 +1,15 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIICXgIBAAKBgQDO/ahgFDvniFoQ1dm+MdnkBi+Ts5W9AtQNgw4ZHIdPnqEzSgW7
3
+ 0opKEu8hnlLqsIyU2BC2op/xOanipdbXObuFlA6bth1cYRI+YJlR3BbPGOIL6YbJ
4
+ ud9m0gIsBlCDLm4e/E45ZS+emudISP7/SF7zxvxZlnr1z7HTm7nIIVBvuQIDAQAB
5
+ AoGBAMzFQAccvU6GI6O4C5sOsiHUxMh3xtCftaxQVGgfQvVPVuXoeteep1Q0ewFl
6
+ IV4vnkO5pH8pTtVTWG9x5KIy6QCql4qvr2jkOm4mo9uogrpNklvBl2lN4Lxubj0N
7
+ mGRXaM3hckZl8+JT6uzfBfjy+pd8AOigJGPQCOZn4gmANW7pAkEA82Nh4wpj6ZRU
8
+ NBiBq3ONZuH4xJm59MI2FWRJsGUFUYdSaFwyKKim52/13d8iUb7v9utWQFRatCXz
9
+ Lqw9fQyVrwJBANm3dBOVxpUPrYEQsG0q2rdP+u6U3woylxwtQgJxImZKZmmJlPr8
10
+ 9v23rhydvCe1ERPYe7EjF4RGWVPN3KLdExcCQDdzNfL3BApMS97OkoRQQC/nXbjU
11
+ 2SPlN1MqVQuGCG8pqGG0V40h11y1CkvxMS10ldEojq77SOrwFnZUsXGS82sCQQC6
12
+ XdO7QCaxSq5XIRYlHN4EtS40NLOIYy3/LK6osHel4GIyTVd+UjSLk0QzssJxqwln
13
+ V5TqWQO0cxPcLQiFUYEZAkEA2G84ilb9QXOgbNyoE1VifNk49hhodbSskLb86uwY
14
+ Vgtzq1ZsqoPBCasr4WRiXt270n+mo5dNYRlZwiUn9lH78Q==
15
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,6 @@
1
+ -----BEGIN PUBLIC KEY-----
2
+ MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDO/ahgFDvniFoQ1dm+MdnkBi+T
3
+ s5W9AtQNgw4ZHIdPnqEzSgW70opKEu8hnlLqsIyU2BC2op/xOanipdbXObuFlA6b
4
+ th1cYRI+YJlR3BbPGOIL6YbJud9m0gIsBlCDLm4e/E45ZS+emudISP7/SF7zxvxZ
5
+ lnr1z7HTm7nIIVBvuQIDAQAB
6
+ -----END PUBLIC KEY-----
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEpAIBAAKCAQEA4GzZTLU48c4WbyvHi+QKrB71x+T0eq5hqDbQqnlYjhD1Ika7
3
+ io1iplsdJWJuyxfYbUkb2Ol0fj4koZ/GS6lgCZr4+8UHbr1qf0Eu5HZSpszs2YxY
4
+ 8U5RHnrpw67co7hlgAR9HbyNf5XIYgLV9ldHH/eazwnc3F/hgNsV0xjScVilejgo
5
+ cJ4zcsyymvW8t42lteM7bI867ZuJhGop/V+Y0HFyrMsPoQyLuCUpr6ulOfrkr7ZO
6
+ dhAIG8r1HcjOp/AUjM15vfXcbUZjkM/VloifX1YitU3upMGJ8/DpFGffMOImrn5r
7
+ 6BT494V8rRyN2qvQoAkLJpqZ0avLxwiR2lgVQQIDAQABAoIBAEH0Ozgr2fxWEInD
8
+ V/VooypKPvjr9F1JejGxSkmPN9MocKIOH3dsbZ1uEXa3ItBUxan4XlK06SNgp+tH
9
+ xULfF/Y6sQlsse59hBq50Uoa69dRShn1AP6JgZVvkduMPBNxUYL5zrs6emsQXb9Q
10
+ DglDRQfEAJ7vyxSIqQDxYcyT8uSUF70dqFe+E9B2VE3D6ccHc98k41pJrAFAUFH1
11
+ wwvDhfyYr7/Ultut9wzpZvU1meF3Vna3GOUHfxrG6wu1G+WIWHGjouzThsc1qiVI
12
+ BtMCJxuCt5fOXRbU4STbMqhB6sZHiOh6J/dZU6JwRYt+IS8FB6kCNFSEWZWQledJ
13
+ XqtYSQECgYEA9nmnFTRj3fTBq9zMXfCRujkSy6X2bOb39ftNXzHFuc+I6xmv/3Bs
14
+ P9tDdjueP/SnCb7i/9hXkpEIcxjrjiqgcvD2ym1hE4q+odMzRAXYMdnmzI34SVZE
15
+ U5hYJcYsXNKrTTleba7QgqdORmyJ9FwqLO40udvmrZMY223XDwgRkOkCgYEA6RkO
16
+ 5wjjrWWp/G1YN3KXZTS1m2/eGrUThohXKAfAjbWWiouNLW2msXrxEWsPRL6xKiHu
17
+ X9cwZwzi3MstAgk+bphUGUVUkGKNDjWHJA25tDYjbPtkd6xbL4eCHsKpNL3HNYr9
18
+ N0CIvgn7qjaHRBem0iK7T6keY4axaSVddEwYapkCgYEA13K5qaB1F4Smcpt8DTWH
19
+ vPe8xUUaZlFzOJLmLCsuwmB2N8Ppg2j7RspcaxJsH021YaB5ftjWm+ipMSr8ZPY/
20
+ 8JlPsNzxuYpTXtNmAbT2KYVm6THEch61dTk6/DIBf1YrpUJbl5by7vJeStL/uBmE
21
+ SGgksL5XIyzs0opuLdaIvFkCgYAyBLWE8AxjFfCvAQuwAj/ocLITo6KmWnrRIIqL
22
+ RXaVMgUWv7FQsTnW1cnK8g05tC2yG8vZ9wQk6Mf5lwOWb0NdWgSZ0528ydj41pWk
23
+ L+nMeN2LMjqxz2NVxJ8wWJcUgTCxFZ0WcRumo9/D+6V1ABpE9zz4cBLcSnfhVypB
24
+ nV6T6QKBgQCSZNCQ9HPxjAgYcsqc5sjNwuN1GHQZSav3Tye3k6zHENe1lsteT9K8
25
+ xciGIuhybKZBvB4yImIIHCtnH+AS+mHAGqHarjNDMfvjOq0dMibPx4+bkIiHdBIH
26
+ Xz+j5kmntvFiUnzr0Z/Tcqo+r8FvyCo1YWgwqGP8XoFrswD7gy7cZw==
27
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,9 @@
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-----
@@ -0,0 +1,27 @@
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-----
@@ -0,0 +1,9 @@
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-----
@@ -0,0 +1,51 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ 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
51
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,14 @@
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-----
@@ -0,0 +1,202 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../spec_helper'
4
+ require 'jwt'
5
+
6
+ describe 'README.md code test' do
7
+ context 'algorithm usage' do
8
+ let(:payload) { { data: 'test' } }
9
+
10
+ it 'NONE' do
11
+ token = JWT.encode payload, nil, 'none'
12
+ decoded_token = JWT.decode token, nil, false
13
+
14
+ expect(token).to eq 'eyJhbGciOiJub25lIn0.eyJkYXRhIjoidGVzdCJ9.'
15
+ expect(decoded_token).to eq [
16
+ { 'data' => 'test' },
17
+ { 'alg' => 'none' }
18
+ ]
19
+ end
20
+
21
+ it 'HMAC' do
22
+ token = JWT.encode payload, 'my$ecretK3y', 'HS256'
23
+ decoded_token = JWT.decode token, 'my$ecretK3y', false
24
+
25
+ expect(token).to eq 'eyJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.pNIWIL34Jo13LViZAJACzK6Yf0qnvT_BuwOxiMCPE-Y'
26
+ expect(decoded_token).to eq [
27
+ { 'data' => 'test' },
28
+ { 'alg' => 'HS256' }
29
+ ]
30
+ end
31
+
32
+ it 'RSA' do
33
+ rsa_private = OpenSSL::PKey::RSA.generate 2048
34
+ rsa_public = rsa_private.public_key
35
+
36
+ token = JWT.encode payload, rsa_private, 'RS256'
37
+ decoded_token = JWT.decode token, rsa_public, true, algorithm: 'RS256'
38
+
39
+ expect(decoded_token).to eq [
40
+ { 'data' => 'test' },
41
+ { 'alg' => 'RS256' }
42
+ ]
43
+ end
44
+
45
+ it 'ECDSA' do
46
+ ecdsa_key = OpenSSL::PKey::EC.new 'prime256v1'
47
+ ecdsa_key.generate_key
48
+ ecdsa_public = OpenSSL::PKey::EC.new ecdsa_key
49
+ ecdsa_public.private_key = nil
50
+
51
+ token = JWT.encode payload, ecdsa_key, 'ES256'
52
+ decoded_token = JWT.decode token, ecdsa_public, true, algorithm: 'ES256'
53
+
54
+ expect(decoded_token).to eq [
55
+ { 'data' => 'test' },
56
+ { 'alg' => 'ES256' }
57
+ ]
58
+ end
59
+ end
60
+
61
+ context 'claims' do
62
+ let(:hmac_secret) { 'MyP4ssW0rD' }
63
+
64
+ context 'exp' do
65
+ it 'without leeway' do
66
+ exp = Time.now.to_i + 4 * 3600
67
+ exp_payload = { data: 'data', exp: exp }
68
+
69
+ token = JWT.encode exp_payload, hmac_secret, 'HS256'
70
+
71
+ expect do
72
+ JWT.decode token, hmac_secret, true, algorithm: 'HS256'
73
+ end.not_to raise_error
74
+ end
75
+
76
+ it 'with leeway' do
77
+ exp = Time.now.to_i - 10
78
+ leeway = 30 # seconds
79
+
80
+ exp_payload = { data: 'data', exp: exp }
81
+
82
+ token = JWT.encode exp_payload, hmac_secret, 'HS256'
83
+
84
+ expect do
85
+ JWT.decode token, hmac_secret, true, leeway: leeway, algorithm: 'HS256'
86
+ end.not_to raise_error
87
+ end
88
+ end
89
+
90
+ context 'nbf' do
91
+ it 'without leeway' do
92
+ nbf = Time.now.to_i - 3600
93
+ nbf_payload = { data: 'data', nbf: nbf }
94
+ token = JWT.encode nbf_payload, hmac_secret, 'HS256'
95
+
96
+ expect do
97
+ JWT.decode token, hmac_secret, true, algorithm: 'HS256'
98
+ end.not_to raise_error
99
+ end
100
+
101
+ it 'with leeway' do
102
+ nbf = Time.now.to_i + 10
103
+ leeway = 30
104
+ nbf_payload = { data: 'data', nbf: nbf }
105
+ token = JWT.encode nbf_payload, hmac_secret, 'HS256'
106
+
107
+ expect do
108
+ JWT.decode token, hmac_secret, true, leeway: leeway, algorithm: 'HS256'
109
+ end.not_to raise_error
110
+ end
111
+ end
112
+
113
+ it 'iss' do
114
+ iss = 'My Awesome Company Inc. or https://my.awesome.website/'
115
+ iss_payload = { data: 'data', iss: iss }
116
+
117
+ token = JWT.encode iss_payload, hmac_secret, 'HS256'
118
+
119
+ expect do
120
+ JWT.decode token, hmac_secret, true, iss: iss, algorithm: 'HS256'
121
+ end.not_to raise_error
122
+ end
123
+
124
+ context 'aud' do
125
+ it 'array' do
126
+ aud = %w[Young Old]
127
+ aud_payload = { data: 'data', aud: aud }
128
+
129
+ token = JWT.encode aud_payload, hmac_secret, 'HS256'
130
+
131
+ expect do
132
+ JWT.decode token, hmac_secret, true, aud: %w[Old Young], verify_aud: true, algorithm: 'HS256'
133
+ end.not_to raise_error
134
+ end
135
+
136
+ it 'string' do
137
+ expect do
138
+ end.not_to raise_error
139
+ end
140
+ end
141
+
142
+ it 'jti' do
143
+ iat = Time.now.to_i
144
+ hmac_secret = 'test'
145
+ jti_raw = [hmac_secret, iat].join(':').to_s
146
+ jti = Digest::MD5.hexdigest(jti_raw)
147
+ jti_payload = { data: 'data', iat: iat, jti: jti }
148
+
149
+ token = JWT.encode jti_payload, hmac_secret, 'HS256'
150
+
151
+ expect do
152
+ JWT.decode token, hmac_secret, true, verify_jti: true, algorithm: 'HS256'
153
+ end.not_to raise_error
154
+ end
155
+
156
+ context 'iat' do
157
+ it 'without leeway' do
158
+ iat = Time.now.to_i
159
+ iat_payload = { data: 'data', iat: iat }
160
+
161
+ token = JWT.encode iat_payload, hmac_secret, 'HS256'
162
+
163
+ expect do
164
+ JWT.decode token, hmac_secret, true, verify_iat: true, algorithm: 'HS256'
165
+ end.not_to raise_error
166
+ end
167
+
168
+ it 'with leeway' do
169
+ iat = Time.now.to_i - 7
170
+ iat_payload = { data: 'data', iat: iat, leeway: 10 }
171
+
172
+ token = JWT.encode iat_payload, hmac_secret, 'HS256'
173
+
174
+ expect do
175
+ JWT.decode token, hmac_secret, true, verify_iat: true, algorithm: 'HS256'
176
+ end.not_to raise_error
177
+ end
178
+ end
179
+
180
+ context 'custom header fields' do
181
+ it 'with custom field' do
182
+ payload = { data: 'test' }
183
+
184
+ token = JWT.encode payload, nil, 'none', typ: 'JWT'
185
+ _, header = JWT.decode token, nil, false
186
+
187
+ expect(header['typ']).to eq 'JWT'
188
+ end
189
+ end
190
+
191
+ it 'sub' do
192
+ sub = 'Subject'
193
+ sub_payload = { data: 'data', sub: sub }
194
+
195
+ token = JWT.encode sub_payload, hmac_secret, 'HS256'
196
+
197
+ expect do
198
+ JWT.decode token, hmac_secret, true, 'sub' => sub, :verify_sub => true, :algorithm => 'HS256'
199
+ end.not_to raise_error
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,232 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'jwt/verify'
5
+
6
+ module JWT
7
+ RSpec.describe Verify do
8
+ let(:base_payload) { { 'user_id' => 'some@user.tld' } }
9
+ let(:options) { { leeway: 0 } }
10
+
11
+ context '.verify_aud(payload, options)' do
12
+ let(:scalar_aud) { 'ruby-jwt-aud' }
13
+ let(:array_aud) { %w[ruby-jwt-aud test-aud ruby-ruby-ruby] }
14
+ let(:scalar_payload) { base_payload.merge('aud' => scalar_aud) }
15
+ let(:array_payload) { base_payload.merge('aud' => array_aud) }
16
+
17
+ it 'must raise JWT::InvalidAudError when the singular audience does not match' do
18
+ expect do
19
+ Verify.verify_aud(scalar_payload, options.merge(aud: 'no-match'))
20
+ end.to raise_error JWT::InvalidAudError
21
+ end
22
+
23
+ it 'must raise JWT::InvalidAudError when the payload has an array and none match the supplied value' do
24
+ expect do
25
+ Verify.verify_aud(array_payload, options.merge(aud: 'no-match'))
26
+ end.to raise_error JWT::InvalidAudError
27
+ end
28
+
29
+ it 'must allow a matching singular audience to pass' do
30
+ Verify.verify_aud(scalar_payload, options.merge(aud: scalar_aud))
31
+ end
32
+
33
+ it 'must allow an array with any value matching the one in the options' do
34
+ Verify.verify_aud(array_payload, options.merge(aud: array_aud.first))
35
+ end
36
+
37
+ it 'must allow an array with any value matching any value in the options array' do
38
+ Verify.verify_aud(array_payload, options.merge(aud: array_aud))
39
+ end
40
+
41
+ it 'must allow a singular audience payload matching any value in the options array' do
42
+ Verify.verify_aud(scalar_payload, options.merge(aud: array_aud))
43
+ end
44
+ end
45
+
46
+ context '.verify_expiration(payload, options)' do
47
+ let(:payload) { base_payload.merge('exp' => (Time.now.to_i - 5)) }
48
+
49
+ it 'must raise JWT::ExpiredSignature when the token has expired' do
50
+ expect do
51
+ Verify.verify_expiration(payload, options)
52
+ end.to raise_error JWT::ExpiredSignature
53
+ end
54
+
55
+ it 'must allow some leeway in the expiration when global leeway is configured' do
56
+ Verify.verify_expiration(payload, options.merge(leeway: 10))
57
+ end
58
+
59
+ it 'must allow some leeway in the expiration when exp_leeway is configured' do
60
+ Verify.verify_expiration(payload, options.merge(exp_leeway: 10))
61
+ end
62
+
63
+ it 'must be expired if the exp claim equals the current time' do
64
+ payload['exp'] = Time.now.to_i
65
+
66
+ expect do
67
+ Verify.verify_expiration(payload, options)
68
+ end.to raise_error JWT::ExpiredSignature
69
+ end
70
+
71
+ context 'when leeway is not specified' do
72
+ let(:options) { {} }
73
+
74
+ it 'used a default leeway of 0' do
75
+ expect do
76
+ Verify.verify_expiration(payload, options)
77
+ end.to raise_error JWT::ExpiredSignature
78
+ end
79
+ end
80
+ end
81
+
82
+ context '.verify_iat(payload, options)' do
83
+ let(:iat) { Time.now.to_f }
84
+ let(:payload) { base_payload.merge('iat' => iat) }
85
+
86
+ it 'must allow a valid iat' do
87
+ Verify.verify_iat(payload, options)
88
+ end
89
+
90
+ it 'must allow configured leeway' do
91
+ Verify.verify_iat(payload.merge('iat' => (iat + 60)), options.merge(leeway: 70))
92
+ end
93
+
94
+ it 'must allow configured iat_leeway' do
95
+ Verify.verify_iat(payload.merge('iat' => (iat + 60)), options.merge(iat_leeway: 70))
96
+ end
97
+
98
+ it 'must properly handle integer times' do
99
+ Verify.verify_iat(payload.merge('iat' => Time.now.to_i), options)
100
+ end
101
+
102
+ it 'must raise JWT::InvalidIatError when the iat value is not Numeric' do
103
+ expect do
104
+ Verify.verify_iat(payload.merge('iat' => 'not a number'), options)
105
+ end.to raise_error JWT::InvalidIatError
106
+ end
107
+
108
+ it 'must raise JWT::InvalidIatError when the iat value is in the future' do
109
+ expect do
110
+ Verify.verify_iat(payload.merge('iat' => (iat + 120)), options)
111
+ end.to raise_error JWT::InvalidIatError
112
+ end
113
+ end
114
+
115
+ context '.verify_iss(payload, options)' do
116
+ let(:iss) { 'ruby-jwt-gem' }
117
+ let(:payload) { base_payload.merge('iss' => iss) }
118
+
119
+ let(:invalid_token) { JWT.encode base_payload, payload[:secret] }
120
+
121
+ context 'when iss is a String' do
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
+ context 'when iss is an Array' do
139
+ it 'must raise JWT::InvalidIssuerError when no matching issuers in array' do
140
+ expect do
141
+ Verify.verify_iss(payload, options.merge(iss: %w[first second]))
142
+ end.to raise_error JWT::InvalidIssuerError
143
+ end
144
+
145
+ it 'must raise JWT::InvalidIssuerError when the payload does not include an issuer' do
146
+ expect do
147
+ Verify.verify_iss(base_payload, options.merge(iss: %w[first second]))
148
+ end.to raise_error(JWT::InvalidIssuerError, /received <none>/)
149
+ end
150
+
151
+ it 'must allow an array with matching issuer to pass' do
152
+ Verify.verify_iss(payload, options.merge(iss: ['first', iss, 'third']))
153
+ end
154
+ end
155
+ end
156
+
157
+ context '.verify_jti(payload, options)' do
158
+ let(:payload) { base_payload.merge('jti' => 'some-random-uuid-or-whatever') }
159
+
160
+ it 'must allow any jti when the verfy_jti key in the options is truthy but not a proc' do
161
+ Verify.verify_jti(payload, options.merge(verify_jti: true))
162
+ end
163
+
164
+ it 'must raise JWT::InvalidJtiError when the jti is missing' do
165
+ expect do
166
+ Verify.verify_jti(base_payload, options)
167
+ end.to raise_error JWT::InvalidJtiError, /missing/i
168
+ end
169
+
170
+ it 'must raise JWT::InvalidJtiError when the jti is an empty string' do
171
+ expect do
172
+ Verify.verify_jti(base_payload.merge('jti' => ' '), options)
173
+ end.to raise_error JWT::InvalidJtiError, /missing/i
174
+ end
175
+
176
+ it 'must raise JWT::InvalidJtiError when verify_jti proc returns false' do
177
+ expect do
178
+ Verify.verify_jti(payload, options.merge(verify_jti: ->(_jti) { false }))
179
+ end.to raise_error JWT::InvalidJtiError, /invalid/i
180
+ end
181
+
182
+ it 'true proc should not raise JWT::InvalidJtiError' do
183
+ Verify.verify_jti(payload, options.merge(verify_jti: ->(_jti) { true }))
184
+ end
185
+
186
+ it 'it should not throw arguement error with 2 args' do
187
+ expect do
188
+ Verify.verify_jti(payload, options.merge(verify_jti: ->(_jti, pl) {
189
+ true
190
+ }))
191
+ end.to_not raise_error
192
+ end
193
+ it 'should have payload as second param in proc' do
194
+ Verify.verify_jti(payload, options.merge(verify_jti: ->(_jti, pl) {
195
+ expect(pl).to eq(payload)
196
+ }))
197
+ end
198
+ end
199
+
200
+ context '.verify_not_before(payload, options)' do
201
+ let(:payload) { base_payload.merge('nbf' => (Time.now.to_i + 5)) }
202
+
203
+ it 'must raise JWT::ImmatureSignature when the nbf in the payload is in the future' do
204
+ expect do
205
+ Verify.verify_not_before(payload, options)
206
+ end.to raise_error JWT::ImmatureSignature
207
+ end
208
+
209
+ it 'must allow some leeway in the token age when global leeway is configured' do
210
+ Verify.verify_not_before(payload, options.merge(leeway: 10))
211
+ end
212
+
213
+ it 'must allow some leeway in the token age when nbf_leeway is configured' do
214
+ Verify.verify_not_before(payload, options.merge(nbf_leeway: 10))
215
+ end
216
+ end
217
+
218
+ context '.verify_sub(payload, options)' do
219
+ let(:sub) { 'ruby jwt subject' }
220
+
221
+ it 'must raise JWT::InvalidSubError when the subjects do not match' do
222
+ expect do
223
+ Verify.verify_sub(base_payload.merge('sub' => 'not-a-match'), options.merge(sub: sub))
224
+ end.to raise_error JWT::InvalidSubError
225
+ end
226
+
227
+ it 'must allow a matching sub' do
228
+ Verify.verify_sub(base_payload.merge('sub' => sub), options.merge(sub: sub))
229
+ end
230
+ end
231
+ end
232
+ end