Embed jwt-2.1.0

This commit is contained in:
Sruthi Chandran 2019-03-15 21:16:06 +05:30
parent 6f9529cc78
commit a6c13ce3b5
52 changed files with 2782 additions and 0 deletions

View file

@ -0,0 +1,20 @@
engines:
rubocop:
enabled: true
golint:
enabled: false
gofmt:
enabled: false
eslint:
enabled: false
csslint:
enabled: false
ratings:
paths:
- lib/**
- "**.rb"
exclude_paths:
- spec/**/*
- vendor/**/*

18
debian/gems-compat/jwt-2.1.0/.ebert.yml vendored Normal file
View file

@ -0,0 +1,18 @@
styleguide: excpt/linters
engines:
reek:
enabled: true
fixme:
enabled: true
rubocop:
enabled: true
channel: rubocop-0-49
duplication:
config:
languages:
- ruby
enabled: true
remark-lint:
enabled: true
exclude_paths:
- spec

11
debian/gems-compat/jwt-2.1.0/.gitignore vendored Normal file
View file

@ -0,0 +1,11 @@
.idea/
jwt.gemspec
pkg
Gemfile.lock
coverage/
.DS_Store
.rbenv-gemsets
.ruby-version
.vscode/
.bundle
bin/

40
debian/gems-compat/jwt-2.1.0/.reek.yml vendored Normal file
View file

@ -0,0 +1,40 @@
---
TooManyStatements:
max_statements: 10
UncommunicativeMethodName:
reject:
- !ruby/regexp /^[a-z]$/
- !ruby/regexp /[0-9]$/
UncommunicativeParameterName:
reject:
- !ruby/regexp /^.$/
- !ruby/regexp /[0-9]$/
- !ruby/regexp /^_/
UncommunicativeVariableName:
reject:
- !ruby/regexp /^.$/
- !ruby/regexp /[0-9]$/
UtilityFunction:
enabled: false
LongParameterList:
enabled: false
DuplicateMethodCall:
max_calls: 2
IrresponsibleModule:
enabled: false
NestedIterators:
max_allowed_nesting: 2
PrimaDonnaMethod:
enabled: false
UnusedParameters:
enabled: false
FeatureEnvy:
enabled: false
ControlParameter:
enabled: false
UnusedPrivateMethod:
enabled: false
InstanceVariableAssumption:
exclude:
- !ruby/regexp /Controller$/
- !ruby/regexp /Mailer$/s

1
debian/gems-compat/jwt-2.1.0/.rspec vendored Normal file
View file

@ -0,0 +1 @@
--color

View file

@ -0,0 +1,98 @@
AllCops:
Exclude:
- 'bin/**/*'
- 'db/**/*'
- 'config/**/*'
- 'script/**/*'
Rails:
Enabled: true
Style/AlignParameters:
EnforcedStyle: with_fixed_indentation
Style/CaseIndentation:
EnforcedStyle: end
Style/AsciiComments:
Enabled: false
Style/IndentHash:
Enabled: false
Style/CollectionMethods:
Enabled: true
PreferredMethods:
inject: 'inject'
Style/Documentation:
Enabled: false
Style/BlockDelimiters:
Exclude:
- spec/**/*_spec.rb
Style/BracesAroundHashParameters:
Exclude:
- spec/**/*_spec.rb
Style/GuardClause:
Enabled: false
Style/IfUnlessModifier:
Enabled: false
Style/SpaceInsideHashLiteralBraces:
Enabled: false
Style/Lambda:
Enabled: false
Style/RaiseArgs:
Enabled: false
Style/SignalException:
Enabled: false
Metrics/AbcSize:
Max: 20
Metrics/ClassLength:
Max: 100
Metrics/ModuleLength:
Max: 100
Metrics/LineLength:
Enabled: false
Metrics/MethodLength:
Max: 15
Style/SingleLineBlockParams:
Enabled: false
Lint/EndAlignment:
EnforcedStyleAlignWith: variable
Style/FormatString:
Enabled: false
Style/MultilineMethodCallIndentation:
EnforcedStyle: indented
Style/MultilineOperationIndentation:
EnforcedStyle: indented
Style/WordArray:
Enabled: false
Style/RedundantSelf:
Enabled: false
Style/AlignHash:
Enabled: true
EnforcedLastArgumentHashStyle: always_ignore
Style/TrivialAccessors:
AllowPredicates: true

View file

@ -0,0 +1,14 @@
sudo: required
cache: bundler
dist: trusty
language: ruby
rvm:
- 2.2.0
- 2.3.0
- 2.4.0
script: "bundle exec rspec && bundle exec codeclimate-test-reporter"
before_install:
- sudo add-apt-repository ppa:chris-lea/libsodium -y
- sudo apt-get update -q
- sudo apt-get install libsodium-dev -y
- gem install bundler

View file

@ -0,0 +1,476 @@
# Change Log
## [2.1.0](https://github.com/jwt/ruby-jwt/tree/2.1.0) (2017-10-06)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.0.0...2.1.0)
**Implemented enhancements:**
- Ed25519 support planned? [\#217](https://github.com/jwt/ruby-jwt/issues/217)
- Verify JTI Proc [\#207](https://github.com/jwt/ruby-jwt/issues/207)
- Allow a list of algorithms for decode [\#241](https://github.com/jwt/ruby-jwt/pull/241) ([lautis](https://github.com/lautis))
- verify takes 2 params, second being payload closes: \#207 [\#238](https://github.com/jwt/ruby-jwt/pull/238) ([ab320012](https://github.com/ab320012))
- simplified logic for keyfinder [\#237](https://github.com/jwt/ruby-jwt/pull/237) ([ab320012](https://github.com/ab320012))
- Show backtrace if rbnacl-libsodium not loaded [\#231](https://github.com/jwt/ruby-jwt/pull/231) ([buzztaiki](https://github.com/buzztaiki))
- Support for ED25519 [\#229](https://github.com/jwt/ruby-jwt/pull/229) ([ab320012](https://github.com/ab320012))
**Fixed bugs:**
- JWT.encode failing on encode for string [\#235](https://github.com/jwt/ruby-jwt/issues/235)
- The README says it uses an algorithm by default [\#226](https://github.com/jwt/ruby-jwt/issues/226)
- Fix string payload issue [\#236](https://github.com/jwt/ruby-jwt/pull/236) ([excpt](https://github.com/excpt))
**Closed issues:**
- Change from 1.5.6 to 2.0.0 and appears a "Completed 401 Unauthorized" [\#240](https://github.com/jwt/ruby-jwt/issues/240)
- Why doesn't the decode function use a default algorithm? [\#227](https://github.com/jwt/ruby-jwt/issues/227)
**Merged pull requests:**
- Update README.md [\#242](https://github.com/jwt/ruby-jwt/pull/242) ([excpt](https://github.com/excpt))
- Update ebert configuration [\#232](https://github.com/jwt/ruby-jwt/pull/232) ([excpt](https://github.com/excpt))
- added algos/strategy classes + structs for inputs [\#230](https://github.com/jwt/ruby-jwt/pull/230) ([ab320012](https://github.com/ab320012))
- Add HS256 algorithm to decode default options [\#228](https://github.com/jwt/ruby-jwt/pull/228) ([madkin10](https://github.com/madkin10))
## [v2.0.0](https://github.com/jwt/ruby-jwt/tree/v2.0.0) (2017-09-03)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.0.0.beta1...v2.0.0)
**Fixed bugs:**
- Support versions outside 2.1 [\#209](https://github.com/jwt/ruby-jwt/issues/209)
- Verifying expiration without leeway throws exception [\#206](https://github.com/jwt/ruby-jwt/issues/206)
- Ruby interpreter warning [\#200](https://github.com/jwt/ruby-jwt/issues/200)
- TypeError: no implicit conversion of String into Integer [\#188](https://github.com/jwt/ruby-jwt/issues/188)
- Fix JWT.encode\(nil\) [\#203](https://github.com/jwt/ruby-jwt/pull/203) ([tmm1](https://github.com/tmm1))
**Closed issues:**
- Possibility to disable claim verifications [\#222](https://github.com/jwt/ruby-jwt/issues/222)
- Proper way to verify Firebase id tokens [\#216](https://github.com/jwt/ruby-jwt/issues/216)
**Merged pull requests:**
- Release 2.0.0 preparations :\) [\#225](https://github.com/jwt/ruby-jwt/pull/225) ([excpt](https://github.com/excpt))
- Skip 'exp' claim validation for array payloads [\#224](https://github.com/jwt/ruby-jwt/pull/224) ([excpt](https://github.com/excpt))
- Use a default leeway of 0 [\#223](https://github.com/jwt/ruby-jwt/pull/223) ([travisofthenorth](https://github.com/travisofthenorth))
- Fix reported codesmells [\#221](https://github.com/jwt/ruby-jwt/pull/221) ([excpt](https://github.com/excpt))
- Add fancy gem version badge [\#220](https://github.com/jwt/ruby-jwt/pull/220) ([excpt](https://github.com/excpt))
- Add missing dist option to .travis.yml [\#219](https://github.com/jwt/ruby-jwt/pull/219) ([excpt](https://github.com/excpt))
- Fix ruby version requirements in gemspec file [\#218](https://github.com/jwt/ruby-jwt/pull/218) ([excpt](https://github.com/excpt))
- Fix a little typo in the readme [\#214](https://github.com/jwt/ruby-jwt/pull/214) ([RyanBrushett](https://github.com/RyanBrushett))
- Update README.md [\#212](https://github.com/jwt/ruby-jwt/pull/212) ([zuzannast](https://github.com/zuzannast))
- Fix typo in HS512256 algorithm description [\#211](https://github.com/jwt/ruby-jwt/pull/211) ([ojab](https://github.com/ojab))
- Allow configuration of multiple acceptable issuers [\#210](https://github.com/jwt/ruby-jwt/pull/210) ([ojab](https://github.com/ojab))
- Enforce `exp` to be an `Integer` [\#205](https://github.com/jwt/ruby-jwt/pull/205) ([lucasmazza](https://github.com/lucasmazza))
- ruby 1.9.3 support message upd [\#204](https://github.com/jwt/ruby-jwt/pull/204) ([maokomioko](https://github.com/maokomioko))
- Guard against partially loaded RbNaCl when failing to load libsodium [\#202](https://github.com/jwt/ruby-jwt/pull/202) ([Dorian](https://github.com/Dorian))
## [v2.0.0.beta1](https://github.com/jwt/ruby-jwt/tree/v2.0.0.beta1) (2017-02-27)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/v1.5.6...v2.0.0.beta1)
**Implemented enhancements:**
- Error with method sign for String [\#171](https://github.com/jwt/ruby-jwt/issues/171)
- Refactor the encondig code [\#121](https://github.com/jwt/ruby-jwt/issues/121)
- Refactor [\#196](https://github.com/jwt/ruby-jwt/pull/196) ([EmilioCristalli](https://github.com/EmilioCristalli))
- Move signature logic to its own module [\#195](https://github.com/jwt/ruby-jwt/pull/195) ([EmilioCristalli](https://github.com/EmilioCristalli))
- Add options for claim-specific leeway [\#187](https://github.com/jwt/ruby-jwt/pull/187) ([EmilioCristalli](https://github.com/EmilioCristalli))
- Add user friendly encode error if private key is a String, \#171 [\#176](https://github.com/jwt/ruby-jwt/pull/176) ([xamenrax](https://github.com/xamenrax))
- Return empty string if signature less than byte\_size \#155 [\#175](https://github.com/jwt/ruby-jwt/pull/175) ([xamenrax](https://github.com/xamenrax))
- Remove 'typ' optional parameter [\#174](https://github.com/jwt/ruby-jwt/pull/174) ([xamenrax](https://github.com/xamenrax))
- Pass payload to keyfinder [\#172](https://github.com/jwt/ruby-jwt/pull/172) ([CodeMonkeySteve](https://github.com/CodeMonkeySteve))
- Use RbNaCl for HMAC if available with fallback to OpenSSL [\#149](https://github.com/jwt/ruby-jwt/pull/149) ([mwpastore](https://github.com/mwpastore))
**Fixed bugs:**
- ruby-jwt::raw\_to\_asn1: Fails for signatures less than byte\_size [\#155](https://github.com/jwt/ruby-jwt/issues/155)
- The leeway parameter is applies to all time based verifications [\#129](https://github.com/jwt/ruby-jwt/issues/129)
- Add options for claim-specific leeway [\#187](https://github.com/jwt/ruby-jwt/pull/187) ([EmilioCristalli](https://github.com/EmilioCristalli))
- Make algorithm option required to verify signature [\#184](https://github.com/jwt/ruby-jwt/pull/184) ([EmilioCristalli](https://github.com/EmilioCristalli))
- Validate audience when payload is a scalar and options is an array [\#183](https://github.com/jwt/ruby-jwt/pull/183) ([steti](https://github.com/steti))
**Closed issues:**
- Different encoded value between servers with same password [\#197](https://github.com/jwt/ruby-jwt/issues/197)
- Signature is different at each run [\#190](https://github.com/jwt/ruby-jwt/issues/190)
- Include custom headers with password [\#189](https://github.com/jwt/ruby-jwt/issues/189)
- can't create token - 'NotImplementedError: Unsupported signing method' [\#186](https://github.com/jwt/ruby-jwt/issues/186)
- Why jwt depends on json \< 2.0 ? [\#179](https://github.com/jwt/ruby-jwt/issues/179)
- Cannot verify JWT at all?? [\#177](https://github.com/jwt/ruby-jwt/issues/177)
- verify\_iss: true is raising JWT::DecodeError instead of JWT::InvalidIssuerError [\#170](https://github.com/jwt/ruby-jwt/issues/170)
**Merged pull requests:**
- Version bump 2.0.0.beta1 [\#199](https://github.com/jwt/ruby-jwt/pull/199) ([excpt](https://github.com/excpt))
- Update CHANGELOG.md and minor fixes [\#198](https://github.com/jwt/ruby-jwt/pull/198) ([excpt](https://github.com/excpt))
- Add Codacy coverage reporter [\#194](https://github.com/jwt/ruby-jwt/pull/194) ([excpt](https://github.com/excpt))
- Add minimum required ruby version to gemspec [\#193](https://github.com/jwt/ruby-jwt/pull/193) ([excpt](https://github.com/excpt))
- Code smell fixes [\#192](https://github.com/jwt/ruby-jwt/pull/192) ([excpt](https://github.com/excpt))
- Version bump to 2.0.0.dev [\#191](https://github.com/jwt/ruby-jwt/pull/191) ([excpt](https://github.com/excpt))
- Basic encode module refactoring \#121 [\#182](https://github.com/jwt/ruby-jwt/pull/182) ([xamenrax](https://github.com/xamenrax))
- Fix travis ci build configuration [\#181](https://github.com/jwt/ruby-jwt/pull/181) ([excpt](https://github.com/excpt))
- Fix travis ci build configuration [\#180](https://github.com/jwt/ruby-jwt/pull/180) ([excpt](https://github.com/excpt))
- Fix typo in README [\#178](https://github.com/jwt/ruby-jwt/pull/178) ([tomeduarte](https://github.com/tomeduarte))
- Fix code style [\#173](https://github.com/jwt/ruby-jwt/pull/173) ([excpt](https://github.com/excpt))
- Fixed a typo in a spec name [\#169](https://github.com/jwt/ruby-jwt/pull/169) ([Mingan](https://github.com/Mingan))
## [v1.5.6](https://github.com/jwt/ruby-jwt/tree/v1.5.6) (2016-09-19)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/v1.5.5...v1.5.6)
**Fixed bugs:**
- Fix missing symbol handling in aud verify code [\#166](https://github.com/jwt/ruby-jwt/pull/166) ([excpt](https://github.com/excpt))
**Merged pull requests:**
- Update changelog [\#168](https://github.com/jwt/ruby-jwt/pull/168) ([excpt](https://github.com/excpt))
- Fix rubocop code smells [\#167](https://github.com/jwt/ruby-jwt/pull/167) ([excpt](https://github.com/excpt))
## [v1.5.5](https://github.com/jwt/ruby-jwt/tree/v1.5.5) (2016-09-16)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/v1.5.4...v1.5.5)
**Implemented enhancements:**
- JWT.decode always raises JWT::ExpiredSignature for tokens created with Time objects passed as the `exp` parameter [\#148](https://github.com/jwt/ruby-jwt/issues/148)
**Fixed bugs:**
- expiration check does not give "Signature has expired" error for the exact time of expiration [\#157](https://github.com/jwt/ruby-jwt/issues/157)
- JTI claim broken? [\#152](https://github.com/jwt/ruby-jwt/issues/152)
- Audience Claim broken? [\#151](https://github.com/jwt/ruby-jwt/issues/151)
- 1.5.3 breaks compatibility with 1.5.2 [\#133](https://github.com/jwt/ruby-jwt/issues/133)
- Version 1.5.3 breaks 1.9.3 compatibility, but not documented as such [\#132](https://github.com/jwt/ruby-jwt/issues/132)
- Fix: exp claim check [\#161](https://github.com/jwt/ruby-jwt/pull/161) ([excpt](https://github.com/excpt))
**Closed issues:**
- Rendering Json Results in JWT::DecodeError [\#162](https://github.com/jwt/ruby-jwt/issues/162)
- PHP Libraries [\#154](https://github.com/jwt/ruby-jwt/issues/154)
- \[security\] Signature verified after expiration/sub/iss checks [\#153](https://github.com/jwt/ruby-jwt/issues/153)
- Is ruby-jwt thread-safe? [\#150](https://github.com/jwt/ruby-jwt/issues/150)
- JWT 1.5.3 [\#143](https://github.com/jwt/ruby-jwt/issues/143)
- gem install v 1.5.3 returns error [\#141](https://github.com/jwt/ruby-jwt/issues/141)
- Adding a CHANGELOG [\#140](https://github.com/jwt/ruby-jwt/issues/140)
**Merged pull requests:**
- Bump version [\#165](https://github.com/jwt/ruby-jwt/pull/165) ([excpt](https://github.com/excpt))
- Improve error message for exp claim in payload [\#164](https://github.com/jwt/ruby-jwt/pull/164) ([excpt](https://github.com/excpt))
- Fix \#151 and code refactoring [\#163](https://github.com/jwt/ruby-jwt/pull/163) ([excpt](https://github.com/excpt))
- Signature validation before claim verification [\#160](https://github.com/jwt/ruby-jwt/pull/160) ([excpt](https://github.com/excpt))
- Create specs for README.md examples [\#159](https://github.com/jwt/ruby-jwt/pull/159) ([excpt](https://github.com/excpt))
- Tiny Readme Improvement [\#156](https://github.com/jwt/ruby-jwt/pull/156) ([b264](https://github.com/b264))
- Added test execution to Rakefile [\#147](https://github.com/jwt/ruby-jwt/pull/147) ([jabbrwcky](https://github.com/jabbrwcky))
- Add more bling bling to the site [\#146](https://github.com/jwt/ruby-jwt/pull/146) ([excpt](https://github.com/excpt))
- Bump version [\#145](https://github.com/jwt/ruby-jwt/pull/145) ([excpt](https://github.com/excpt))
- Add first content and basic layout [\#144](https://github.com/jwt/ruby-jwt/pull/144) ([excpt](https://github.com/excpt))
- Add a changelog file [\#142](https://github.com/jwt/ruby-jwt/pull/142) ([excpt](https://github.com/excpt))
- Return decoded\_segments [\#139](https://github.com/jwt/ruby-jwt/pull/139) ([akostrikov](https://github.com/akostrikov))
## [v1.5.4](https://github.com/jwt/ruby-jwt/tree/v1.5.4) (2016-03-24)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/v1.5.3...v1.5.4)
**Closed issues:**
- 404 at https://rubygems.global.ssl.fastly.net/gems/jwt-1.5.3.gem [\#137](https://github.com/jwt/ruby-jwt/issues/137)
**Merged pull requests:**
- Update README.md [\#138](https://github.com/jwt/ruby-jwt/pull/138) ([excpt](https://github.com/excpt))
- Fix base64url\_decode [\#136](https://github.com/jwt/ruby-jwt/pull/136) ([excpt](https://github.com/excpt))
- Fix ruby 1.9.3 compatibility [\#135](https://github.com/jwt/ruby-jwt/pull/135) ([excpt](https://github.com/excpt))
- iat can be a float value [\#134](https://github.com/jwt/ruby-jwt/pull/134) ([llimllib](https://github.com/llimllib))
## [v1.5.3](https://github.com/jwt/ruby-jwt/tree/v1.5.3) (2016-02-24)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/jwt-1.5.2...v1.5.3)
**Implemented enhancements:**
- Refactor obsolete code for ruby 1.8 support [\#120](https://github.com/jwt/ruby-jwt/issues/120)
- Fix "Rubocop/Metrics/CyclomaticComplexity" issue in lib/jwt.rb [\#106](https://github.com/jwt/ruby-jwt/issues/106)
- Fix "Rubocop/Metrics/CyclomaticComplexity" issue in lib/jwt.rb [\#105](https://github.com/jwt/ruby-jwt/issues/105)
- Allow a proc to be passed for JTI verification [\#126](https://github.com/jwt/ruby-jwt/pull/126) ([yahooguntu](https://github.com/yahooguntu))
- Relax restrictions on "jti" claim verification [\#113](https://github.com/jwt/ruby-jwt/pull/113) ([lwe](https://github.com/lwe))
**Closed issues:**
- Verifications not functioning in latest release [\#128](https://github.com/jwt/ruby-jwt/issues/128)
- Base64 is generating invalid length base64 strings - cross language interop [\#127](https://github.com/jwt/ruby-jwt/issues/127)
- Digest::Digest is deprecated; use Digest [\#119](https://github.com/jwt/ruby-jwt/issues/119)
- verify\_rsa no method 'verify' for class String [\#115](https://github.com/jwt/ruby-jwt/issues/115)
- Add a changelog [\#111](https://github.com/jwt/ruby-jwt/issues/111)
**Merged pull requests:**
- Drop ruby 1.9.3 support [\#131](https://github.com/jwt/ruby-jwt/pull/131) ([excpt](https://github.com/excpt))
- Allow string hash keys in validation configurations [\#130](https://github.com/jwt/ruby-jwt/pull/130) ([tpickett66](https://github.com/tpickett66))
- Add ruby 2.3.0 for travis ci testing [\#123](https://github.com/jwt/ruby-jwt/pull/123) ([excpt](https://github.com/excpt))
- Remove obsolete json code [\#122](https://github.com/jwt/ruby-jwt/pull/122) ([excpt](https://github.com/excpt))
- Add fancy badges to README.md [\#118](https://github.com/jwt/ruby-jwt/pull/118) ([excpt](https://github.com/excpt))
- Refactor decode and verify functionality [\#117](https://github.com/jwt/ruby-jwt/pull/117) ([excpt](https://github.com/excpt))
- Drop echoe dependency for gem releases [\#116](https://github.com/jwt/ruby-jwt/pull/116) ([excpt](https://github.com/excpt))
- Updated readme for iss/aud options [\#114](https://github.com/jwt/ruby-jwt/pull/114) ([ryanmcilmoyl](https://github.com/ryanmcilmoyl))
- Fix error misspelling [\#112](https://github.com/jwt/ruby-jwt/pull/112) ([kat3kasper](https://github.com/kat3kasper))
## [jwt-1.5.2](https://github.com/jwt/ruby-jwt/tree/jwt-1.5.2) (2015-10-27)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/jwt-1.5.1...jwt-1.5.2)
**Implemented enhancements:**
- Must we specify algorithm when calling decode to avoid vulnerabilities? [\#107](https://github.com/jwt/ruby-jwt/issues/107)
- Code review: Rspec test refactoring [\#85](https://github.com/jwt/ruby-jwt/pull/85) ([excpt](https://github.com/excpt))
**Fixed bugs:**
- aud verifies if aud is passed in, :sub does not [\#102](https://github.com/jwt/ruby-jwt/issues/102)
- iat check does not use leeway so nbf could pass, but iat fail [\#83](https://github.com/jwt/ruby-jwt/issues/83)
**Closed issues:**
- Test ticket from Code Climate [\#104](https://github.com/jwt/ruby-jwt/issues/104)
- Test ticket from Code Climate [\#100](https://github.com/jwt/ruby-jwt/issues/100)
- Is it possible to decode the payload without validating the signature? [\#97](https://github.com/jwt/ruby-jwt/issues/97)
- What is audience? [\#96](https://github.com/jwt/ruby-jwt/issues/96)
- Options hash uses both symbols and strings as keys. [\#95](https://github.com/jwt/ruby-jwt/issues/95)
**Merged pull requests:**
- Fix incorrect `iat` examples [\#109](https://github.com/jwt/ruby-jwt/pull/109) ([kjwierenga](https://github.com/kjwierenga))
- Update docs to include instructions for the algorithm parameter. [\#108](https://github.com/jwt/ruby-jwt/pull/108) ([aarongray](https://github.com/aarongray))
- make sure :sub check behaves like :aud check [\#103](https://github.com/jwt/ruby-jwt/pull/103) ([skippy](https://github.com/skippy))
- Change hash syntax [\#101](https://github.com/jwt/ruby-jwt/pull/101) ([excpt](https://github.com/excpt))
- Include LICENSE and README.md in gem [\#99](https://github.com/jwt/ruby-jwt/pull/99) ([bkeepers](https://github.com/bkeepers))
- Remove unused variable in the sample code. [\#98](https://github.com/jwt/ruby-jwt/pull/98) ([hypermkt](https://github.com/hypermkt))
- Fix iat claim example [\#94](https://github.com/jwt/ruby-jwt/pull/94) ([larrylv](https://github.com/larrylv))
- Fix wrong description in README.md [\#93](https://github.com/jwt/ruby-jwt/pull/93) ([larrylv](https://github.com/larrylv))
- JWT and JWA are now RFC. [\#92](https://github.com/jwt/ruby-jwt/pull/92) ([aj-michael](https://github.com/aj-michael))
- Update README.md [\#91](https://github.com/jwt/ruby-jwt/pull/91) ([nsarno](https://github.com/nsarno))
- Fix missing verify parameter in docs [\#90](https://github.com/jwt/ruby-jwt/pull/90) ([ernie](https://github.com/ernie))
- Iat check uses leeway. [\#89](https://github.com/jwt/ruby-jwt/pull/89) ([aj-michael](https://github.com/aj-michael))
- nbf check allows exact time matches. [\#88](https://github.com/jwt/ruby-jwt/pull/88) ([aj-michael](https://github.com/aj-michael))
## [jwt-1.5.1](https://github.com/jwt/ruby-jwt/tree/jwt-1.5.1) (2015-06-22)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/jwt-1.5.0...jwt-1.5.1)
**Implemented enhancements:**
- Fix either README or source code [\#78](https://github.com/jwt/ruby-jwt/issues/78)
- Validate against draft 20 [\#38](https://github.com/jwt/ruby-jwt/issues/38)
**Fixed bugs:**
- ECDSA signature verification fails for valid tokens [\#84](https://github.com/jwt/ruby-jwt/issues/84)
- Shouldn't verification of additional claims, like iss, aud etc. be enforced when in options? [\#81](https://github.com/jwt/ruby-jwt/issues/81)
- Fix either README or source code [\#78](https://github.com/jwt/ruby-jwt/issues/78)
- decode fails with 'none' algorithm and verify [\#75](https://github.com/jwt/ruby-jwt/issues/75)
**Closed issues:**
- Doc mismatch: uninitialized constant JWT::ExpiredSignature [\#79](https://github.com/jwt/ruby-jwt/issues/79)
- TypeError when specifying a wrong algorithm [\#77](https://github.com/jwt/ruby-jwt/issues/77)
- jti verification doesn't prevent replays [\#73](https://github.com/jwt/ruby-jwt/issues/73)
**Merged pull requests:**
- Correctly sign ECDSA JWTs [\#87](https://github.com/jwt/ruby-jwt/pull/87) ([jurriaan](https://github.com/jurriaan))
- fixed results of decoded tokens in readme [\#86](https://github.com/jwt/ruby-jwt/pull/86) ([piscolomo](https://github.com/piscolomo))
- Force verification of "iss" and "aud" claims [\#82](https://github.com/jwt/ruby-jwt/pull/82) ([lwe](https://github.com/lwe))
## [jwt-1.5.0](https://github.com/jwt/ruby-jwt/tree/jwt-1.5.0) (2015-05-09)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/jwt-1.4.1...jwt-1.5.0)
**Implemented enhancements:**
- Needs to support asymmetric key signatures over shared secrets [\#46](https://github.com/jwt/ruby-jwt/issues/46)
- Implement Elliptic Curve Crypto Signatures [\#74](https://github.com/jwt/ruby-jwt/pull/74) ([jtdowney](https://github.com/jtdowney))
- Add an option to verify the signature on decode [\#71](https://github.com/jwt/ruby-jwt/pull/71) ([javawizard](https://github.com/javawizard))
**Closed issues:**
- Check JWT vulnerability [\#76](https://github.com/jwt/ruby-jwt/issues/76)
**Merged pull requests:**
- Fixed some examples to make them copy-pastable [\#72](https://github.com/jwt/ruby-jwt/pull/72) ([jer](https://github.com/jer))
## [jwt-1.4.1](https://github.com/jwt/ruby-jwt/tree/jwt-1.4.1) (2015-03-12)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/jwt-1.4.0...jwt-1.4.1)
**Fixed bugs:**
- jti verification not working per the spec [\#68](https://github.com/jwt/ruby-jwt/issues/68)
- Verify ISS should be off by default [\#66](https://github.com/jwt/ruby-jwt/issues/66)
**Merged pull requests:**
- Fix \#66 \#68 [\#69](https://github.com/jwt/ruby-jwt/pull/69) ([excpt](https://github.com/excpt))
- When throwing errors, mention expected/received values [\#65](https://github.com/jwt/ruby-jwt/pull/65) ([rolodato](https://github.com/rolodato))
## [jwt-1.4.0](https://github.com/jwt/ruby-jwt/tree/jwt-1.4.0) (2015-03-10)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/jwt-1.3.0...jwt-1.4.0)
**Closed issues:**
- The behavior using 'json' differs from 'multi\_json' [\#41](https://github.com/jwt/ruby-jwt/issues/41)
**Merged pull requests:**
- Release 1.4.0 [\#64](https://github.com/jwt/ruby-jwt/pull/64) ([excpt](https://github.com/excpt))
- Update README.md and remove dead code [\#63](https://github.com/jwt/ruby-jwt/pull/63) ([excpt](https://github.com/excpt))
- Add 'iat/ aud/ sub/ jti' support for ruby-jwt [\#62](https://github.com/jwt/ruby-jwt/pull/62) ([ZhangHanDong](https://github.com/ZhangHanDong))
- Add 'iss' support for ruby-jwt [\#61](https://github.com/jwt/ruby-jwt/pull/61) ([ZhangHanDong](https://github.com/ZhangHanDong))
- Clarify .encode API in README [\#60](https://github.com/jwt/ruby-jwt/pull/60) ([jbodah](https://github.com/jbodah))
## [jwt-1.3.0](https://github.com/jwt/ruby-jwt/tree/jwt-1.3.0) (2015-02-24)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/jwt-1.2.1...jwt-1.3.0)
**Closed issues:**
- Signature Verification to Return Verification Error rather than decode error [\#57](https://github.com/jwt/ruby-jwt/issues/57)
- Incorrect readme for leeway [\#55](https://github.com/jwt/ruby-jwt/issues/55)
- What is the reason behind stripping the = in base64 encoding? [\#54](https://github.com/jwt/ruby-jwt/issues/54)
- Preperations for version 2.x [\#50](https://github.com/jwt/ruby-jwt/issues/50)
- Release a new version [\#47](https://github.com/jwt/ruby-jwt/issues/47)
- Catch up for ActiveWhatever 4.1.1 series [\#40](https://github.com/jwt/ruby-jwt/issues/40)
**Merged pull requests:**
- raise verification error for signiture verification [\#58](https://github.com/jwt/ruby-jwt/pull/58) ([punkle](https://github.com/punkle))
- Added support for not before claim verification [\#56](https://github.com/jwt/ruby-jwt/pull/56) ([punkle](https://github.com/punkle))
- Preperations for version 2.x [\#49](https://github.com/jwt/ruby-jwt/pull/49) ([excpt](https://github.com/excpt))
## [jwt-1.2.1](https://github.com/jwt/ruby-jwt/tree/jwt-1.2.1) (2015-01-22)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/jwt-1.2.0...jwt-1.2.1)
**Closed issues:**
- JWT.encode\({"exp": 10}, "secret"\) [\#52](https://github.com/jwt/ruby-jwt/issues/52)
- JWT.encode\({"exp": 10}, "secret"\) [\#51](https://github.com/jwt/ruby-jwt/issues/51)
**Merged pull requests:**
- Accept expiration claims as string [\#53](https://github.com/jwt/ruby-jwt/pull/53) ([yarmand](https://github.com/yarmand))
## [jwt-1.2.0](https://github.com/jwt/ruby-jwt/tree/jwt-1.2.0) (2014-11-24)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/jwt-0.1.13...jwt-1.2.0)
**Closed issues:**
- set token to expire [\#42](https://github.com/jwt/ruby-jwt/issues/42)
**Merged pull requests:**
- Added support for `exp` claim [\#45](https://github.com/jwt/ruby-jwt/pull/45) ([zshannon](https://github.com/zshannon))
- rspec 3 breaks passing tests [\#44](https://github.com/jwt/ruby-jwt/pull/44) ([zshannon](https://github.com/zshannon))
## [jwt-0.1.13](https://github.com/jwt/ruby-jwt/tree/jwt-0.1.13) (2014-05-08)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/jwt-1.0.0...jwt-0.1.13)
**Closed issues:**
- Semantic versioning [\#37](https://github.com/jwt/ruby-jwt/issues/37)
- Update gem to get latest changes [\#36](https://github.com/jwt/ruby-jwt/issues/36)
## [jwt-1.0.0](https://github.com/jwt/ruby-jwt/tree/jwt-1.0.0) (2014-05-07)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/jwt-0.1.11...jwt-1.0.0)
**Closed issues:**
- API request - JWT::decoded\_header\(\) [\#26](https://github.com/jwt/ruby-jwt/issues/26)
**Merged pull requests:**
- return header along with playload after decoding [\#35](https://github.com/jwt/ruby-jwt/pull/35) ([sawyerzhang](https://github.com/sawyerzhang))
- Raise JWT::DecodeError on nil token [\#34](https://github.com/jwt/ruby-jwt/pull/34) ([tjmw](https://github.com/tjmw))
- Make MultiJson optional for Ruby 1.9+ [\#33](https://github.com/jwt/ruby-jwt/pull/33) ([petergoldstein](https://github.com/petergoldstein))
- Allow access to header and payload without signature verification [\#32](https://github.com/jwt/ruby-jwt/pull/32) ([petergoldstein](https://github.com/petergoldstein))
- Update specs to use RSpec 3.0.x syntax [\#31](https://github.com/jwt/ruby-jwt/pull/31) ([petergoldstein](https://github.com/petergoldstein))
- Travis - Add Ruby 2.0.0, 2.1.0, Rubinius [\#30](https://github.com/jwt/ruby-jwt/pull/30) ([petergoldstein](https://github.com/petergoldstein))
## [jwt-0.1.11](https://github.com/jwt/ruby-jwt/tree/jwt-0.1.11) (2014-01-17)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/jwt-0.1.10...jwt-0.1.11)
**Closed issues:**
- url safe encode and decode [\#28](https://github.com/jwt/ruby-jwt/issues/28)
- Release [\#27](https://github.com/jwt/ruby-jwt/issues/27)
**Merged pull requests:**
- fixed urlsafe base64 encoding [\#29](https://github.com/jwt/ruby-jwt/pull/29) ([tobscher](https://github.com/tobscher))
## [jwt-0.1.10](https://github.com/jwt/ruby-jwt/tree/jwt-0.1.10) (2014-01-10)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/jwt-0.1.8...jwt-0.1.10)
**Closed issues:**
- change to signature of JWT.decode method [\#14](https://github.com/jwt/ruby-jwt/issues/14)
**Merged pull requests:**
- Fix warning: assigned but unused variable - e [\#25](https://github.com/jwt/ruby-jwt/pull/25) ([sferik](https://github.com/sferik))
- Echoe doesn't define a license= method [\#24](https://github.com/jwt/ruby-jwt/pull/24) ([sferik](https://github.com/sferik))
- Use OpenSSL::Digest instead of deprecated OpenSSL::Digest::Digest [\#23](https://github.com/jwt/ruby-jwt/pull/23) ([JuanitoFatas](https://github.com/JuanitoFatas))
- Handle some invalid JWTs [\#22](https://github.com/jwt/ruby-jwt/pull/22) ([steved](https://github.com/steved))
- Add MIT license to gemspec [\#21](https://github.com/jwt/ruby-jwt/pull/21) ([nycvotes-dev](https://github.com/nycvotes-dev))
- Tweaks and improvements [\#20](https://github.com/jwt/ruby-jwt/pull/20) ([threedaymonk](https://github.com/threedaymonk))
- Don't leave errors in OpenSSL.errors when there is a decoding error. [\#19](https://github.com/jwt/ruby-jwt/pull/19) ([lowellk](https://github.com/lowellk))
## [jwt-0.1.8](https://github.com/jwt/ruby-jwt/tree/jwt-0.1.8) (2013-03-14)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/jwt-0.1.7...jwt-0.1.8)
**Merged pull requests:**
- Contrib and update [\#18](https://github.com/jwt/ruby-jwt/pull/18) ([threedaymonk](https://github.com/threedaymonk))
- Verify if verify is truthy \(not just true\) [\#17](https://github.com/jwt/ruby-jwt/pull/17) ([threedaymonk](https://github.com/threedaymonk))
## [jwt-0.1.7](https://github.com/jwt/ruby-jwt/tree/jwt-0.1.7) (2013-03-07)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/jwt-0.1.6...jwt-0.1.7)
**Merged pull requests:**
- Catch MultiJson::LoadError and reraise as JWT::DecodeError [\#16](https://github.com/jwt/ruby-jwt/pull/16) ([rwygand](https://github.com/rwygand))
## [jwt-0.1.6](https://github.com/jwt/ruby-jwt/tree/jwt-0.1.6) (2013-03-05)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/jwt-0.1.5...jwt-0.1.6)
**Merged pull requests:**
- Fixes a theoretical timing attack [\#15](https://github.com/jwt/ruby-jwt/pull/15) ([mgates](https://github.com/mgates))
- Use StandardError as parent for DecodeError [\#13](https://github.com/jwt/ruby-jwt/pull/13) ([Oscil8](https://github.com/Oscil8))
## [jwt-0.1.5](https://github.com/jwt/ruby-jwt/tree/jwt-0.1.5) (2012-07-20)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/jwt-0.1.4...jwt-0.1.5)
**Closed issues:**
- Unable to specify signature header fields [\#7](https://github.com/jwt/ruby-jwt/issues/7)
**Merged pull requests:**
- MultiJson dependency uses ~\> but should be \>= [\#12](https://github.com/jwt/ruby-jwt/pull/12) ([sporkmonger](https://github.com/sporkmonger))
- Oops. :-\) [\#11](https://github.com/jwt/ruby-jwt/pull/11) ([sporkmonger](https://github.com/sporkmonger))
- Fix issue with signature verification in JRuby [\#10](https://github.com/jwt/ruby-jwt/pull/10) ([sporkmonger](https://github.com/sporkmonger))
- Depend on MultiJson [\#9](https://github.com/jwt/ruby-jwt/pull/9) ([lautis](https://github.com/lautis))
- Allow for custom headers on encode and decode [\#8](https://github.com/jwt/ruby-jwt/pull/8) ([dgrijalva](https://github.com/dgrijalva))
- Missing development dependency for echoe gem. [\#6](https://github.com/jwt/ruby-jwt/pull/6) ([sporkmonger](https://github.com/sporkmonger))
## [jwt-0.1.4](https://github.com/jwt/ruby-jwt/tree/jwt-0.1.4) (2011-11-11)
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/jwt-0.1.3...jwt-0.1.4)
**Merged pull requests:**
- Fix for RSA verification [\#5](https://github.com/jwt/ruby-jwt/pull/5) ([jordan-brough](https://github.com/jordan-brough))
## [jwt-0.1.3](https://github.com/jwt/ruby-jwt/tree/jwt-0.1.3) (2011-06-30)
**Closed issues:**
- signatures calculated incorrectly \(hexdigest instead of digest\) [\#1](https://github.com/jwt/ruby-jwt/issues/1)
**Merged pull requests:**
- Bumped a version and added a .gemspec using rake build\_gemspec [\#3](https://github.com/jwt/ruby-jwt/pull/3) ([zhitomirskiyi](https://github.com/zhitomirskiyi))
- Added RSA support [\#2](https://github.com/jwt/ruby-jwt/pull/2) ([zhitomirskiyi](https://github.com/zhitomirskiyi))
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*

3
debian/gems-compat/jwt-2.1.0/Gemfile vendored Normal file
View file

@ -0,0 +1,3 @@
source 'https://rubygems.org'
gemspec

7
debian/gems-compat/jwt-2.1.0/LICENSE vendored Normal file
View file

@ -0,0 +1,7 @@
Copyright (c) 2011 Jeff Lindsay
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

8
debian/gems-compat/jwt-2.1.0/Manifest vendored Normal file
View file

@ -0,0 +1,8 @@
Rakefile
README.md
LICENSE
lib/jwt.rb
lib/jwt/json.rb
spec/spec_helper.rb
spec/jwt_spec.rb
Manifest

478
debian/gems-compat/jwt-2.1.0/README.md vendored Normal file
View file

@ -0,0 +1,478 @@
# JWT
[![Gem Version](https://badge.fury.io/rb/jwt.svg)](https://badge.fury.io/rb/jwt)
[![Build Status](https://travis-ci.org/jwt/ruby-jwt.svg)](https://travis-ci.org/jwt/ruby-jwt)
[![Code Climate](https://codeclimate.com/github/jwt/ruby-jwt/badges/gpa.svg)](https://codeclimate.com/github/jwt/ruby-jwt)
[![Test Coverage](https://codeclimate.com/github/jwt/ruby-jwt/badges/coverage.svg)](https://codeclimate.com/github/jwt/ruby-jwt/coverage)
[![Issue Count](https://codeclimate.com/github/jwt/ruby-jwt/badges/issue_count.svg)](https://codeclimate.com/github/jwt/ruby-jwt)
A pure ruby implementation of the [RFC 7519 OAuth JSON Web Token (JWT)](https://tools.ietf.org/html/rfc7519) standard.
If you have further questions related to development or usage, join us: [ruby-jwt google group](https://groups.google.com/forum/#!forum/ruby-jwt).
## Announcements
* Ruby 1.9.3 support was dropped at December 31st, 2016.
* Version 1.5.3 yanked. See: [#132](https://github.com/jwt/ruby-jwt/issues/132) and [#133](https://github.com/jwt/ruby-jwt/issues/133)
## Installing
### Using Rubygems:
```bash
sudo gem install jwt
```
### Using Bundler:
Add the following to your Gemfile
```
gem 'jwt'
```
And run `bundle install`
## Algorithms and Usage
The JWT spec supports NONE, HMAC, RSASSA, ECDSA and RSASSA-PSS algorithms for cryptographic signing. Currently the jwt gem supports NONE, HMAC, RSASSA and ECDSA. If you are using cryptographic signing, you need to specify the algorithm in the options hash whenever you call JWT.decode to ensure that an attacker [cannot bypass the algorithm verification step](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/).
See: [ JSON Web Algorithms (JWA) 3.1. "alg" (Algorithm) Header Parameter Values for JWS](https://tools.ietf.org/html/rfc7518#section-3.1)
**NONE**
* none - unsigned token
```ruby
require 'jwt'
payload = {:data => 'test'}
# IMPORTANT: set nil as password parameter
token = JWT.encode payload, nil, 'none'
# eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJkYXRhIjoidGVzdCJ9.
puts token
# Set password to nil and validation to false otherwise this won't work
decoded_token = JWT.decode token, nil, false
# Array
# [
# {"data"=>"test"}, # payload
# {"alg"=>"none"} # header
# ]
puts decoded_token
```
**HMAC**
* HS256 - HMAC using SHA-256 hash algorithm
* HS512256 - HMAC using SHA-512-256 hash algorithm (only available with RbNaCl; see note below)
* HS384 - HMAC using SHA-384 hash algorithm
* HS512 - HMAC using SHA-512 hash algorithm
```ruby
hmac_secret = 'my$ecretK3y'
token = JWT.encode payload, hmac_secret, 'HS256'
# eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.ZxW8go9hz3ETCSfxFxpwSkYg_602gOPKearsf6DsxgY
puts token
decoded_token = JWT.decode token, hmac_secret, true, { :algorithm => 'HS256' }
# Array
# [
# {"data"=>"test"}, # payload
# {"alg"=>"HS256"} # header
# ]
puts decoded_token
```
Note: If [RbNaCl](https://github.com/cryptosphere/rbnacl) is loadable, ruby-jwt will use it for HMAC-SHA256, HMAC-SHA512-256, and HMAC-SHA512. RbNaCl enforces a maximum key size of 32 bytes for these algorithms.
[RbNaCl](https://github.com/cryptosphere/rbnacl) requires
[libsodium](https://github.com/jedisct1/libsodium), it can be installed
on MacOS with `brew install libsodium`.
**RSA**
* RS256 - RSA using SHA-256 hash algorithm
* RS384 - RSA using SHA-384 hash algorithm
* RS512 - RSA using SHA-512 hash algorithm
```ruby
rsa_private = OpenSSL::PKey::RSA.generate 2048
rsa_public = rsa_private.public_key
token = JWT.encode payload, rsa_private, 'RS256'
# eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ0ZXN0IjoiZGF0YSJ9.c2FynXNyi6_PeKxrDGxfS3OLwQ8lTDbWBWdq7oMviCy2ZfFpzvW2E_odCWJrbLof-eplHCsKzW7MGAntHMALXgclm_Cs9i2Exi6BZHzpr9suYkrhIjwqV1tCgMBCQpdeMwIq6SyKVjgH3L51ivIt0-GDDPDH1Rcut3jRQzp3Q35bg3tcI2iVg7t3Msvl9QrxXAdYNFiS5KXH22aJZ8X_O2HgqVYBXfSB1ygTYUmKTIIyLbntPQ7R22rFko1knGWOgQCoYXwbtpuKRZVFrxX958L2gUWgb4jEQNf3fhOtkBm1mJpj-7BGst00o8g_3P2zHy-3aKgpPo1XlKQGjRrrxA
puts token
decoded_token = JWT.decode token, rsa_public, true, { :algorithm => 'RS256' }
# Array
# [
# {"data"=>"test"}, # payload
# {"alg"=>"RS256"} # header
# ]
puts decoded_token
```
**ECDSA**
* ES256 - ECDSA using P-256 and SHA-256
* ES384 - ECDSA using P-384 and SHA-384
* ES512 - ECDSA using P-521 and SHA-512
```ruby
ecdsa_key = OpenSSL::PKey::EC.new 'prime256v1'
ecdsa_key.generate_key
ecdsa_public = OpenSSL::PKey::EC.new ecdsa_key
ecdsa_public.private_key = nil
token = JWT.encode payload, ecdsa_key, 'ES256'
# eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJ0ZXN0IjoiZGF0YSJ9.MEQCIAtShrxRwP1L9SapqaT4f7hajDJH4t_rfm-YlZcNDsBNAiB64M4-JRfyS8nRMlywtQ9lHbvvec9U54KznzOe1YxTyA
puts token
decoded_token = JWT.decode token, ecdsa_public, true, { :algorithm => 'ES256' }
# Array
# [
# {"test"=>"data"}, # payload
# {"alg"=>"ES256"} # header
# ]
puts decoded_token
```
**EDDSA**
In order to use this algorithm you need to add the `RbNaCl` gem to you `Gemfile`.
```ruby
gem 'rbnacl'
```
For more detailed installation instruction check the official [repository](https://github.com/cryptosphere/rbnacl) on GitHub.
* ED25519
```ruby
private_key = RbNaCl::Signatures::Ed25519::SigningKey.new("abcdefghijklmnopqrstuvwxyzABCDEF")
public_key = private_key.verify_key
token = JWT.encode payload, private_key, 'ED25519'
# eyJhbGciOiJFRDI1NTE5In0.eyJ0ZXN0IjoiZGF0YSJ9.-Ki0vxVOlsPXovPsYRT_9OXrLSgQd4RDAgCLY_PLmcP4q32RYy-yUUmX82ycegdekR9wo26me1wOzjmSU5nTCQ
puts token
decoded_token = JWT.decode token, public_key, true, {:algorithm => 'ED25519' }
# Array
# [
# {"test"=>"data"}, # payload
# {"alg"=>"ED25519"} # header
# ]
```
**RSASSA-PSS**
Not implemented.
## Support for reserved claim names
JSON Web Token defines some reserved claim names and defines how they should be
used. JWT supports these reserved claim names:
- 'exp' (Expiration Time) Claim
- 'nbf' (Not Before Time) Claim
- 'iss' (Issuer) Claim
- 'aud' (Audience) Claim
- 'jti' (JWT ID) Claim
- 'iat' (Issued At) Claim
- 'sub' (Subject) Claim
## Add custom header fields
Ruby-jwt gem supports custom [header fields] (https://tools.ietf.org/html/rfc7519#section-5)
To add custom header fields you need to pass `header_fields` parameter
```ruby
token = JWT.encode payload, key, algorithm='HS256', header_fields={}
```
**Example:**
```ruby
require 'jwt'
payload = {:data => 'test'}
# IMPORTANT: set nil as password parameter
token = JWT.encode payload, nil, 'none', { :typ => "JWT" }
# eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJkYXRhIjoidGVzdCJ9.
puts token
# Set password to nil and validation to false otherwise this won't work
decoded_token = JWT.decode token, nil, false
# Array
# [
# {"data"=>"test"}, # payload
# {"typ"=>"JWT", "alg"=>"none"} # header
# ]
puts decoded_token
```
### Expiration Time Claim
From [Oauth JSON Web Token 4.1.4. "exp" (Expiration Time) Claim](https://tools.ietf.org/html/rfc7519#section-4.1.4):
> The `exp` (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing. The processing of the `exp` claim requires that the current date/time MUST be before the expiration date/time listed in the `exp` claim. Implementers MAY provide for some small `leeway`, usually no more than a few minutes, to account for clock skew. Its value MUST be a number containing a ***NumericDate*** value. Use of this claim is OPTIONAL.
**Handle Expiration Claim**
```ruby
exp = Time.now.to_i + 4 * 3600
exp_payload = { :data => 'data', :exp => exp }
token = JWT.encode exp_payload, hmac_secret, 'HS256'
begin
decoded_token = JWT.decode token, hmac_secret, true, { :algorithm => 'HS256' }
rescue JWT::ExpiredSignature
# Handle expired token, e.g. logout user or deny access
end
```
**Adding Leeway**
```ruby
exp = Time.now.to_i - 10
leeway = 30 # seconds
exp_payload = { :data => 'data', :exp => exp }
# build expired token
token = JWT.encode exp_payload, hmac_secret, 'HS256'
begin
# add leeway to ensure the token is still accepted
decoded_token = JWT.decode token, hmac_secret, true, { :exp_leeway => leeway, :algorithm => 'HS256' }
rescue JWT::ExpiredSignature
# Handle expired token, e.g. logout user or deny access
end
```
### Not Before Time Claim
From [Oauth JSON Web Token 4.1.5. "nbf" (Not Before) Claim](https://tools.ietf.org/html/rfc7519#section-4.1.5):
> The `nbf` (not before) claim identifies the time before which the JWT MUST NOT be accepted for processing. The processing of the `nbf` claim requires that the current date/time MUST be after or equal to the not-before date/time listed in the `nbf` claim. Implementers MAY provide for some small `leeway`, usually no more than a few minutes, to account for clock skew. Its value MUST be a number containing a ***NumericDate*** value. Use of this claim is OPTIONAL.
**Handle Not Before Claim**
```ruby
nbf = Time.now.to_i - 3600
nbf_payload = { :data => 'data', :nbf => nbf }
token = JWT.encode nbf_payload, hmac_secret, 'HS256'
begin
decoded_token = JWT.decode token, hmac_secret, true, { :algorithm => 'HS256' }
rescue JWT::ImmatureSignature
# Handle invalid token, e.g. logout user or deny access
end
```
**Adding Leeway**
```ruby
nbf = Time.now.to_i + 10
leeway = 30
nbf_payload = { :data => 'data', :nbf => nbf }
# build expired token
token = JWT.encode nbf_payload, hmac_secret, 'HS256'
begin
# add leeway to ensure the token is valid
decoded_token = JWT.decode token, hmac_secret, true, { :nbf_leeway => leeway, :algorithm => 'HS256' }
rescue JWT::ImmatureSignature
# Handle invalid token, e.g. logout user or deny access
end
```
### Issuer Claim
From [Oauth JSON Web Token 4.1.1. "iss" (Issuer) Claim](https://tools.ietf.org/html/rfc7519#section-4.1.1):
> The `iss` (issuer) claim identifies the principal that issued the JWT. The processing of this claim is generally application specific. The `iss` value is a case-sensitive string containing a ***StringOrURI*** value. Use of this claim is OPTIONAL.
You can pass multiple allowed issuers as an Array, verification will pass if one of them matches the `iss` value in the payload.
```ruby
iss = 'My Awesome Company Inc. or https://my.awesome.website/'
iss_payload = { :data => 'data', :iss => iss }
token = JWT.encode iss_payload, hmac_secret, 'HS256'
begin
# Add iss to the validation to check if the token has been manipulated
decoded_token = JWT.decode token, hmac_secret, true, { :iss => iss, :verify_iss => true, :algorithm => 'HS256' }
rescue JWT::InvalidIssuerError
# Handle invalid token, e.g. logout user or deny access
end
```
### Audience Claim
From [Oauth JSON Web Token 4.1.3. "aud" (Audience) Claim](https://tools.ietf.org/html/rfc7519#section-4.1.3):
> The `aud` (audience) claim identifies the recipients that the JWT is intended for. Each principal intended to process the JWT MUST identify itself with a value in the audience claim. If the principal processing the claim does not identify itself with a value in the `aud` claim when this claim is present, then the JWT MUST be rejected. In the general case, the `aud` value is an array of case-sensitive strings, each containing a ***StringOrURI*** value. In the special case when the JWT has one audience, the `aud` value MAY be a single case-sensitive string containing a ***StringOrURI*** value. The interpretation of audience values is generally application specific. Use of this claim is OPTIONAL.
```ruby
aud = ['Young', 'Old']
aud_payload = { :data => 'data', :aud => aud }
token = JWT.encode aud_payload, hmac_secret, 'HS256'
begin
# Add aud to the validation to check if the token has been manipulated
decoded_token = JWT.decode token, hmac_secret, true, { :aud => aud, :verify_aud => true, :algorithm => 'HS256' }
rescue JWT::InvalidAudError
# Handle invalid token, e.g. logout user or deny access
puts 'Audience Error'
end
```
### JWT ID Claim
From [Oauth JSON Web Token 4.1.7. "jti" (JWT ID) Claim](https://tools.ietf.org/html/rfc7519#section-4.1.7):
> The `jti` (JWT ID) claim provides a unique identifier for the JWT. The identifier value MUST be assigned in a manner that ensures that there is a negligible probability that the same value will be accidentally assigned to a different data object; if the application uses multiple issuers, collisions MUST be prevented among values produced by different issuers as well. The `jti` claim can be used to prevent the JWT from being replayed. The `jti` value is a case-sensitive string. Use of this claim is OPTIONAL.
```ruby
# Use the secret and iat to create a unique key per request to prevent replay attacks
jti_raw = [hmac_secret, iat].join(':').to_s
jti = Digest::MD5.hexdigest(jti_raw)
jti_payload = { :data => 'data', :iat => iat, :jti => jti }
token = JWT.encode jti_payload, hmac_secret, 'HS256'
begin
# If :verify_jti is true, validation will pass if a JTI is present
#decoded_token = JWT.decode token, hmac_secret, true, { :verify_jti => true, :algorithm => 'HS256' }
# Alternatively, pass a proc with your own code to check if the JTI has already been used
decoded_token = JWT.decode token, hmac_secret, true, { :verify_jti => proc { |jti| my_validation_method(jti) }, :algorithm => 'HS256' }
rescue JWT::InvalidJtiError
# Handle invalid token, e.g. logout user or deny access
puts 'Error'
end
```
### Issued At Claim
From [Oauth JSON Web Token 4.1.6. "iat" (Issued At) Claim](https://tools.ietf.org/html/rfc7519#section-4.1.6):
> The `iat` (issued at) claim identifies the time at which the JWT was issued. This claim can be used to determine the age of the JWT. Its value MUST be a number containing a ***NumericDate*** value. Use of this claim is OPTIONAL.
**Handle Issued At Claim**
```ruby
iat = Time.now.to_i
iat_payload = { :data => 'data', :iat => iat }
token = JWT.encode iat_payload, hmac_secret, 'HS256'
begin
# Add iat to the validation to check if the token has been manipulated
decoded_token = JWT.decode token, hmac_secret, true, { :verify_iat => true, :algorithm => 'HS256' }
rescue JWT::InvalidIatError
# Handle invalid token, e.g. logout user or deny access
end
```
**Adding Leeway**
```ruby
iat = Time.now.to_i + 10
leeway = 30 # seconds
iat_payload = { :data => 'data', :iat => iat }
# build token issued in the future
token = JWT.encode iat_payload, hmac_secret, 'HS256'
begin
# add leeway to ensure the token is accepted
decoded_token = JWT.decode token, hmac_secret, true, { :iat_leeway => leeway, :verify_iat => true, :algorithm => 'HS256' }
rescue JWT::InvalidIatError
# Handle invalid token, e.g. logout user or deny access
end
```
### Subject Claim
From [Oauth JSON Web Token 4.1.2. "sub" (Subject) Claim](https://tools.ietf.org/html/rfc7519#section-4.1.2):
> The `sub` (subject) claim identifies the principal that is the subject of the JWT. The Claims in a JWT are normally statements about the subject. The subject value MUST either be scoped to be locally unique in the context of the issuer or be globally unique. The processing of this claim is generally application specific. The sub value is a case-sensitive string containing a ***StringOrURI*** value. Use of this claim is OPTIONAL.
```ruby
sub = 'Subject'
sub_payload = { :data => 'data', :sub => sub }
token = JWT.encode sub_payload, hmac_secret, 'HS256'
begin
# Add sub to the validation to check if the token has been manipulated
decoded_token = JWT.decode token, hmac_secret, true, { 'sub' => sub, :verify_sub => true, :algorithm => 'HS256' }
rescue JWT::InvalidSubError
# Handle invalid token, e.g. logout user or deny access
end
```
# Development and Tests
We depend on [Bundler](http://rubygems.org/gems/bundler) for defining gemspec and performing releases to rubygems.org, which can be done with
```bash
rake release
```
The tests are written with rspec. Given you have installed the dependencies via bundler, you can run tests with
```bash
bundle exec rspec
```
**If you want a release cut with your PR, please include a version bump according to [Semantic Versioning](http://semver.org/)**
## Contributors
* Jordan Brough <github.jordanb@xoxy.net>
* Ilya Zhitomirskiy <ilya@joindiaspora.com>
* Daniel Grippi <daniel@joindiaspora.com>
* Jeff Lindsay <progrium@gmail.com>
* Bob Aman <bob@sporkmonger.com>
* Micah Gates <github@mgates.com>
* Rob Wygand <rob@wygand.com>
* Ariel Salomon (Oscil8)
* Paul Battley <pbattley@gmail.com>
* Zane Shannon [@zshannon](https://github.com/zshannon)
* Brian Fletcher [@punkle](https://github.com/punkle)
* Alex [@ZhangHanDong](https://github.com/ZhangHanDong)
* John Downey [@jtdowney](https://github.com/jtdowney)
* Adam Greene [@skippy](https://github.com/skippy)
* Tim Rudat [@excpt](https://github.com/excpt) <timrudat@gmail.com> - Maintainer
## License
MIT
Copyright (c) 2011 Jeff Lindsay
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

11
debian/gems-compat/jwt-2.1.0/Rakefile vendored Normal file
View file

@ -0,0 +1,11 @@
require 'bundler/gem_tasks'
begin
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:test)
task default: :test
rescue LoadError
puts 'RSpec rake tasks not available. Please run "bundle install" to install missing dependencies.'
end

63
debian/gems-compat/jwt-2.1.0/lib/jwt.rb vendored Normal file
View file

@ -0,0 +1,63 @@
# frozen_string_literal: true
require 'base64'
require 'jwt/decode'
require 'jwt/default_options'
require 'jwt/encode'
require 'jwt/error'
require 'jwt/signature'
require 'jwt/verify'
# JSON Web Token implementation
#
# Should be up to date with the latest spec:
# https://tools.ietf.org/html/rfc7519
module JWT
include JWT::DefaultOptions
module_function
def encode(payload, key, algorithm = 'HS256', header_fields = {})
encoder = Encode.new payload, key, algorithm, header_fields
encoder.segments
end
def decode(jwt, key = nil, verify = true, custom_options = {}, &keyfinder)
raise(JWT::DecodeError, 'Nil JSON web token') unless jwt
merged_options = DEFAULT_OPTIONS.merge(custom_options)
decoder = Decode.new jwt, verify
header, payload, signature, signing_input = decoder.decode_segments
decode_verify_signature(key, header, payload, signature, signing_input, merged_options, &keyfinder) if verify
Verify.verify_claims(payload, merged_options) if verify
raise(JWT::DecodeError, 'Not enough or too many segments') unless header && payload
[payload, header]
end
def decode_verify_signature(key, header, payload, signature, signing_input, options, &keyfinder)
algo, key = signature_algorithm_and_key(header, payload, key, &keyfinder)
raise(JWT::IncorrectAlgorithm, 'An algorithm must be specified') if allowed_algorithms(options).empty?
raise(JWT::IncorrectAlgorithm, 'Expected a different algorithm') unless allowed_algorithms(options).include?(algo)
Signature.verify(algo, key, signing_input, signature)
end
def signature_algorithm_and_key(header, payload, key, &keyfinder)
key = (keyfinder.arity == 2 ? yield(header, payload) : yield(header)) if keyfinder
raise JWT::DecodeError, 'No verification key available' unless key
[header['alg'], key]
end
def allowed_algorithms(options)
if options.key?(:algorithm)
[options[:algorithm]]
else
options[:algorithms] || []
end
end
end

View file

@ -0,0 +1,35 @@
module JWT
module Algos
module Ecdsa
module_function
SUPPORTED = %(ES256 ES384 ES512).freeze
NAMED_CURVES = {
'prime256v1' => 'ES256',
'secp384r1' => 'ES384',
'secp521r1' => 'ES512'
}.freeze
def sign(to_sign)
algorithm, msg, key = to_sign.values
key_algorithm = NAMED_CURVES[key.group.curve_name]
if algorithm != key_algorithm
raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{key_algorithm} signing key was provided"
end
digest = OpenSSL::Digest.new(algorithm.sub('ES', 'sha'))
SecurityUtils.asn1_to_raw(key.dsa_sign_asn1(digest.digest(msg)), key)
end
def verify(to_verify)
algorithm, public_key, signing_input, signature = to_verify.values
key_algorithm = NAMED_CURVES[public_key.group.curve_name]
if algorithm != key_algorithm
raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{key_algorithm} verification key was provided"
end
digest = OpenSSL::Digest.new(algorithm.sub('ES', 'sha'))
public_key.dsa_verify_asn1(digest.digest(signing_input), SecurityUtils.raw_to_asn1(signature, public_key))
end
end
end
end

View file

@ -0,0 +1,23 @@
module JWT
module Algos
module Eddsa
module_function
SUPPORTED = %w[ED25519].freeze
def sign(to_sign)
algorithm, msg, key = to_sign.values
raise EncodeError, "Key given is a #{key.class} but has to be an RbNaCl::Signatures::Ed25519::SigningKey" if key.class != RbNaCl::Signatures::Ed25519::SigningKey
raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{key.primitive} signing key was provided" if algorithm.downcase.to_sym != key.primitive
key.sign(msg)
end
def verify(to_verify)
algorithm, public_key, signing_input, signature = to_verify.values
raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{public_key.primitive} verification key was provided" if algorithm.downcase.to_sym != public_key.primitive
raise DecodeError, "key given is a #{public_key.class} but has to be a RbNaCl::Signatures::Ed25519::VerifyKey" if public_key.class != RbNaCl::Signatures::Ed25519::VerifyKey
public_key.verify(signature, signing_input)
end
end
end
end

View file

@ -0,0 +1,33 @@
module JWT
module Algos
module Hmac
module_function
SUPPORTED = %w[HS256 HS512256 HS384 HS512].freeze
def sign(to_sign)
algorithm, msg, key = to_sign.values
authenticator, padded_key = SecurityUtils.rbnacl_fixup(algorithm, key)
if authenticator && padded_key
authenticator.auth(padded_key, msg.encode('binary'))
else
OpenSSL::HMAC.digest(OpenSSL::Digest.new(algorithm.sub('HS', 'sha')), key, msg)
end
end
def verify(to_verify)
algorithm, public_key, signing_input, signature = to_verify.values
authenticator, padded_key = SecurityUtils.rbnacl_fixup(algorithm, public_key)
if authenticator && padded_key
begin
authenticator.verify(padded_key, signature.encode('binary'), signing_input.encode('binary'))
rescue RbNaCl::BadAuthenticatorError
false
end
else
SecurityUtils.secure_compare(signature, sign(JWT::Signature::ToSign.new(algorithm, signing_input, public_key)))
end
end
end
end
end

View file

@ -0,0 +1,19 @@
module JWT
module Algos
module Rsa
module_function
SUPPORTED = %w[RS256 RS384 RS512].freeze
def sign(to_sign)
algorithm, msg, key = to_sign.values
raise EncodeError, "The given key is a #{key.class}. It has to be an OpenSSL::PKey::RSA instance." if key.class == String
key.sign(OpenSSL::Digest.new(algorithm.sub('RS', 'sha')), msg)
end
def verify(to_verify)
SecurityUtils.verify_rsa(to_verify.algorithm, to_verify.public_key, to_verify.signing_input, to_verify.signature)
end
end
end
end

View file

@ -0,0 +1,16 @@
module JWT
module Algos
module Unsupported
module_function
SUPPORTED = Object.new.tap { |object| object.define_singleton_method(:include?) { |*| true } }
def verify(*)
raise JWT::VerificationError, 'Algorithm not supported'
end
def sign(*)
raise NotImplementedError, 'Unsupported signing method'
end
end
end
end

View file

@ -0,0 +1,49 @@
# frozen_string_literal: true
require 'json'
# JWT::Decode module
module JWT
# Decoding logic for JWT
class Decode
attr_reader :header, :payload, :signature
def self.base64url_decode(str)
str += '=' * (4 - str.length.modulo(4))
Base64.decode64(str.tr('-_', '+/'))
end
def initialize(jwt, verify)
@jwt = jwt
@verify = verify
@header = ''
@payload = ''
@signature = ''
end
def decode_segments
header_segment, payload_segment, crypto_segment = raw_segments
@header, @payload = decode_header_and_payload(header_segment, payload_segment)
@signature = Decode.base64url_decode(crypto_segment.to_s) if @verify
signing_input = [header_segment, payload_segment].join('.')
[@header, @payload, @signature, signing_input]
end
private
def raw_segments
segments = @jwt.split('.')
required_num_segments = @verify ? [3] : [2, 3]
raise(JWT::DecodeError, 'Not enough or too many segments') unless required_num_segments.include? segments.length
segments
end
def decode_header_and_payload(header_segment, payload_segment)
header = JSON.parse(Decode.base64url_decode(header_segment))
payload = JSON.parse(Decode.base64url_decode(payload_segment))
[header, payload]
rescue JSON::ParserError
raise JWT::DecodeError, 'Invalid segment encoding'
end
end
end

View file

@ -0,0 +1,15 @@
module JWT
module DefaultOptions
DEFAULT_OPTIONS = {
verify_expiration: true,
verify_not_before: true,
verify_iss: false,
verify_iat: false,
verify_jti: false,
verify_aud: false,
verify_sub: false,
leeway: 0,
algorithms: ['HS256']
}.freeze
end
end

View file

@ -0,0 +1,51 @@
# frozen_string_literal: true
require 'json'
# JWT::Encode module
module JWT
# Encoding logic for JWT
class Encode
attr_reader :payload, :key, :algorithm, :header_fields, :segments
def self.base64url_encode(str)
Base64.encode64(str).tr('+/', '-_').gsub(/[\n=]/, '')
end
def initialize(payload, key, algorithm, header_fields)
@payload = payload
@key = key
@algorithm = algorithm
@header_fields = header_fields
@segments = encode_segments
end
private
def encoded_header
header = { 'alg' => @algorithm }.merge(@header_fields)
Encode.base64url_encode(JSON.generate(header))
end
def encoded_payload
raise InvalidPayload, 'exp claim must be an integer' if @payload && @payload.is_a?(Hash) && @payload.key?('exp') && !@payload['exp'].is_a?(Integer)
Encode.base64url_encode(JSON.generate(@payload))
end
def encoded_signature(signing_input)
if @algorithm == 'none'
''
else
signature = JWT::Signature.sign(@algorithm, signing_input, @key)
Encode.base64url_encode(signature)
end
end
def encode_segments
header = encoded_header
payload = encoded_payload
signature = encoded_signature([header, payload].join('.'))
[header, payload, signature].join('.')
end
end
end

View file

@ -0,0 +1,16 @@
# frozen_string_literal: true
module JWT
class EncodeError < StandardError; end
class DecodeError < StandardError; end
class VerificationError < DecodeError; end
class ExpiredSignature < DecodeError; end
class IncorrectAlgorithm < DecodeError; end
class ImmatureSignature < DecodeError; end
class InvalidIssuerError < DecodeError; end
class InvalidIatError < DecodeError; end
class InvalidAudError < DecodeError; end
class InvalidSubError < DecodeError; end
class InvalidJtiError < DecodeError; end
class InvalidPayload < DecodeError; end
end

View file

@ -0,0 +1,51 @@
module JWT
# Collection of security methods
#
# @see: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/security_utils.rb
module SecurityUtils
module_function
def secure_compare(left, right)
left_bytesize = left.bytesize
return false unless left_bytesize == right.bytesize
unpacked_left = left.unpack "C#{left_bytesize}"
result = 0
right.each_byte { |byte| result |= byte ^ unpacked_left.shift }
result.zero?
end
def verify_rsa(algorithm, public_key, signing_input, signature)
public_key.verify(OpenSSL::Digest.new(algorithm.sub('RS', 'sha')), signature, signing_input)
end
def asn1_to_raw(signature, public_key)
byte_size = (public_key.group.degree + 7) / 8
OpenSSL::ASN1.decode(signature).value.map { |value| value.value.to_s(2).rjust(byte_size, "\x00") }.join
end
def raw_to_asn1(signature, private_key)
byte_size = (private_key.group.degree + 7) / 8
sig_bytes = signature[0..(byte_size - 1)]
sig_char = signature[byte_size..-1] || ''
OpenSSL::ASN1::Sequence.new([sig_bytes, sig_char].map { |int| OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(int, 2)) }).to_der
end
def rbnacl_fixup(algorithm, key)
algorithm = algorithm.sub('HS', 'SHA').to_sym
return [] unless defined?(RbNaCl) && RbNaCl::HMAC.constants(false).include?(algorithm)
authenticator = RbNaCl::HMAC.const_get(algorithm)
# Fall back to OpenSSL for keys larger than 32 bytes.
return [] if key.bytesize > authenticator.key_bytes
[
authenticator,
key.bytes.fill(0, key.bytesize...authenticator.key_bytes).pack('C*')
]
end
end
end

View file

@ -0,0 +1,50 @@
# frozen_string_literal: true
require 'jwt/security_utils'
require 'openssl'
require 'jwt/algos/hmac'
require 'jwt/algos/eddsa'
require 'jwt/algos/ecdsa'
require 'jwt/algos/rsa'
require 'jwt/algos/unsupported'
begin
require 'rbnacl'
rescue LoadError
raise if defined?(RbNaCl)
end
# JWT::Signature module
module JWT
# Signature logic for JWT
module Signature
extend self
ALGOS = [
Algos::Hmac,
Algos::Ecdsa,
Algos::Rsa,
Algos::Eddsa,
Algos::Unsupported
].freeze
ToSign = Struct.new(:algorithm, :msg, :key)
ToVerify = Struct.new(:algorithm, :public_key, :signing_input, :signature)
def sign(algorithm, msg, key)
algo = ALGOS.find do |alg|
alg.const_get(:SUPPORTED).include? algorithm
end
algo.sign ToSign.new(algorithm, msg, key)
end
def verify(algorithm, key, signing_input, signature)
algo = ALGOS.find do |alg|
alg.const_get(:SUPPORTED).include? algorithm
end
verified = algo.verify(ToVerify.new(algorithm, key, signing_input, signature))
raise(JWT::VerificationError, 'Signature verification raised') unless verified
rescue OpenSSL::PKey::PKeyError
raise JWT::VerificationError, 'Signature verification raised'
ensure
OpenSSL.errors.clear
end
end
end

View file

@ -0,0 +1,102 @@
# frozen_string_literal: true
require 'jwt/error'
module JWT
# JWT verify methods
class Verify
DEFAULTS = {
leeway: 0
}.freeze
class << self
%w[verify_aud verify_expiration verify_iat verify_iss verify_jti verify_not_before verify_sub].each do |method_name|
define_method method_name do |payload, options|
new(payload, options).send(method_name)
end
end
def verify_claims(payload, options)
options.each do |key, val|
next unless key.to_s =~ /verify/
Verify.send(key, payload, options) if val
end
end
end
def initialize(payload, options)
@payload = payload
@options = DEFAULTS.merge(options)
end
def verify_aud
return unless (options_aud = @options[:aud])
aud = @payload['aud']
raise(JWT::InvalidAudError, "Invalid audience. Expected #{options_aud}, received #{aud || '<none>'}") if ([*aud] & [*options_aud]).empty?
end
def verify_expiration
return unless @payload.include?('exp')
raise(JWT::ExpiredSignature, 'Signature has expired') if @payload['exp'].to_i <= (Time.now.to_i - exp_leeway)
end
def verify_iat
return unless @payload.include?('iat')
iat = @payload['iat']
raise(JWT::InvalidIatError, 'Invalid iat') if !iat.is_a?(Numeric) || iat.to_f > (Time.now.to_f + iat_leeway)
end
def verify_iss
return unless (options_iss = @options[:iss])
iss = @payload['iss']
return if Array(options_iss).map(&:to_s).include?(iss.to_s)
raise(JWT::InvalidIssuerError, "Invalid issuer. Expected #{options_iss}, received #{iss || '<none>'}")
end
def verify_jti
options_verify_jti = @options[:verify_jti]
jti = @payload['jti']
if options_verify_jti.respond_to?(:call)
verified = options_verify_jti.arity == 2 ? options_verify_jti.call(jti, @payload) : options_verify_jti.call(jti)
raise(JWT::InvalidJtiError, 'Invalid jti') unless verified
elsif jti.to_s.strip.empty?
raise(JWT::InvalidJtiError, 'Missing jti')
end
end
def verify_not_before
return unless @payload.include?('nbf')
raise(JWT::ImmatureSignature, 'Signature nbf has not been reached') if @payload['nbf'].to_i > (Time.now.to_i + nbf_leeway)
end
def verify_sub
return unless (options_sub = @options[:sub])
sub = @payload['sub']
raise(JWT::InvalidSubError, "Invalid subject. Expected #{options_sub}, received #{sub || '<none>'}") unless sub.to_s == options_sub.to_s
end
private
def global_leeway
@options[:leeway]
end
def exp_leeway
@options[:exp_leeway] || global_leeway
end
def iat_leeway
@options[:iat_leeway] || global_leeway
end
def nbf_leeway
@options[:nbf_leeway] || global_leeway
end
end
end

View file

@ -0,0 +1,24 @@
# encoding: utf-8
# frozen_string_literal: true
# Moments version builder module
module JWT
def self.gem_version
Gem::Version.new VERSION::STRING
end
# Moments version builder module
module VERSION
# major version
MAJOR = 2
# minor version
MINOR = 1
# tiny version
TINY = 0
# alpha, beta, etc. tag
PRE = nil
# Build version string
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
end
end

View file

@ -0,0 +1,31 @@
lib = File.expand_path('../lib/', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'jwt/version'
Gem::Specification.new do |spec|
spec.name = 'jwt'
spec.version = JWT.gem_version
spec.authors = [
'Tim Rudat'
]
spec.email = 'timrudat@gmail.com'
spec.summary = 'JSON Web Token implementation in Ruby'
spec.description = 'A pure ruby implementation of the RFC 7519 OAuth JSON Web Token (JWT) standard.'
spec.homepage = 'http://github.com/jwt/ruby-jwt'
spec.license = 'MIT'
spec.required_ruby_version = '>= 2.1'
spec.files = `git ls-files -z`.split("\x0")
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = %w[lib]
spec.add_development_dependency 'bundler'
spec.add_development_dependency 'rake'
spec.add_development_dependency 'rspec'
spec.add_development_dependency 'simplecov'
spec.add_development_dependency 'simplecov-json'
spec.add_development_dependency 'codeclimate-test-reporter'
spec.add_development_dependency 'codacy-coverage'
spec.add_development_dependency 'rbnacl'
end

View file

@ -0,0 +1,8 @@
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIJmVse5uPfj6B4TcXrUAvf9/8pJh+KrKKYLNcmOnp/vPoAoGCCqGSM49
AwEHoUQDQgAEAr+WbDE5VtIDGhtYMxvEc6cMsDBc/DX1wuhIMu8dQzOLSt0tpqK9
MVfXbVfrKdayVFgoWzs8MilcYq0QIhKx/w==
-----END EC PRIVATE KEY-----

View file

@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAr+WbDE5VtIDGhtYMxvEc6cMsDBc
/DX1wuhIMu8dQzOLSt0tpqK9MVfXbVfrKdayVFgoWzs8MilcYq0QIhKx/w==
-----END PUBLIC KEY-----

View file

@ -0,0 +1,8 @@
-----BEGIN EC PARAMETERS-----
BgUrgQQACg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEICfA4AaomONdmPTzeyrx5U/jugYXTERyb5U3ETTv7Hx7oAcGBSuBBAAK
oUQDQgAEPmuXZT3jpJnEMVPOW6RMsmxeGLOCE1PN6fwvUwOsxv7YnyoQ5/bpo64n
+Jp4slSl1aUNoCBF2oz9bS0iyBo3jg==
-----END EC PRIVATE KEY-----

View file

@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEPmuXZT3jpJnEMVPOW6RMsmxeGLOCE1PN
6fwvUwOsxv7YnyoQ5/bpo64n+Jp4slSl1aUNoCBF2oz9bS0iyBo3jg==
-----END PUBLIC KEY-----

View file

@ -0,0 +1,9 @@
-----BEGIN EC PARAMETERS-----
BgUrgQQAIg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MIGkAgEBBDDxOljqUKw9YNhkluSJIBAYO1YXcNtS+vckd5hpTZ5toxsOlwbmyrnU
Tn+D5Xma1m2gBwYFK4EEACKhZANiAASQwYTiRvXu1hMHceSosMs/8uf50sJI3jvK
kdSkvuRAPxSzhtrUvCQDnVsThFq4aOdZZY1qh2ErJGtzmrx+pEsJvJnvfOTG3NGU
KRalek+LQfVqAUSvDMKlxdkz2e67tso=
-----END EC PRIVATE KEY-----

View file

@ -0,0 +1,5 @@
-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEkMGE4kb17tYTB3HkqLDLP/Ln+dLCSN47
ypHUpL7kQD8Us4ba1LwkA51bE4RauGjnWWWNaodhKyRrc5q8fqRLCbyZ73zkxtzR
lCkWpXpPi0H1agFErwzCpcXZM9nuu7bK
-----END PUBLIC KEY-----

View file

@ -0,0 +1,9 @@
-----BEGIN EC PARAMETERS-----
BgUrgQQAIg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MIGkAgEBBDAfZW47dSKnC5JkSVOk1ERxCIi/IJ1p1WBnVGx4hnrNHy+dxtaZJaF+
YLInFQ/QbYegBwYFK4EEACKhZANiAAQwXkx4BFBGLXbzl5yVrfxK7er8hSi38iDE
K2+7cdrR137Wn5JUnL4WTwXTzkyUgfBOL3sHNozwfgU03GD/EOUEKqzsIJiz2cbP
bFALd4hS+8T4szDLVC9Jl1W6k0CAtmM=
-----END EC PRIVATE KEY-----

View file

@ -0,0 +1,5 @@
-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEMF5MeARQRi1285ecla38Su3q/IUot/Ig
xCtvu3Ha0dd+1p+SVJy+Fk8F085MlIHwTi97BzaM8H4FNNxg/xDlBCqs7CCYs9nG
z2xQC3eIUvvE+LMwy1QvSZdVupNAgLZj
-----END PUBLIC KEY-----

View file

@ -0,0 +1,10 @@
-----BEGIN EC PARAMETERS-----
BgUrgQQAIw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MIHcAgEBBEIB0/+ffxEj7j62xvGaB5pvzk888e412ESO/EK/K0QlS9dSF8+Rj1rG
zqpRB8fvDnoe8xdmkW/W5GKzojMyv7YQYumgBwYFK4EEACOhgYkDgYYABAEw74Yw
aTbPY6TtWmxx6LJDzCX2nKWCPnKdZcEH9Ncu8g5RjRBRq2yacja3OoS6nA2YeDng
reBJxZr376P6Ns6XcQFWDA6K/MCTrEBCsPxXZNxd8KR9vMGWhgNtWRrcKzwJfQkr
suyehZkbbYyFnAWyARKHZuV7VUXmeEmRS/f93MPqVA==
-----END EC PRIVATE KEY-----

View file

@ -0,0 +1,6 @@
-----BEGIN PUBLIC KEY-----
MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBMO+GMGk2z2Ok7VpsceiyQ8wl9pyl
gj5ynWXBB/TXLvIOUY0QUatsmnI2tzqEupwNmHg54K3gScWa9++j+jbOl3EBVgwO
ivzAk6xAQrD8V2TcXfCkfbzBloYDbVka3Cs8CX0JK7LsnoWZG22MhZwFsgESh2bl
e1VF5nhJkUv3/dzD6lQ=
-----END PUBLIC KEY-----

View file

@ -0,0 +1,10 @@
-----BEGIN EC PARAMETERS-----
BgUrgQQAIw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MIHbAgEBBEG/KbA2oCbiCT6L3V8XSz2WKBy0XhGvIFbl/ZkXIXnkYt+1B7wViSVo
KCHuMFsi6xU/5nE1EuDG2UsQJmKeAMkIOKAHBgUrgQQAI6GBiQOBhgAEAG0TFWe5
cZ5DZIyfuysrCoQySTNxd+aT8sPIxsx7mW6YBTsuO6rEgxyegd2Auy4xtikxpzKv
soMXR02999Aaus2jAAt/wxrhhr41BDP4MV0b6Zngb72hna0pcGqit5OyU8AbOJUZ
+rdyowRGsOY+aPbOyVhdNcsEdxYC8GdIyCQLBC1H
-----END EC PRIVATE KEY-----

View file

@ -0,0 +1,6 @@
-----BEGIN PUBLIC KEY-----
MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAbRMVZ7lxnkNkjJ+7KysKhDJJM3F3
5pPyw8jGzHuZbpgFOy47qsSDHJ6B3YC7LjG2KTGnMq+ygxdHTb330Bq6zaMAC3/D
GuGGvjUEM/gxXRvpmeBvvaGdrSlwaqK3k7JTwBs4lRn6t3KjBEaw5j5o9s7JWF01
ywR3FgLwZ0jIJAsELUc=
-----END PUBLIC KEY-----

View file

@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDO/ahgFDvniFoQ1dm+MdnkBi+Ts5W9AtQNgw4ZHIdPnqEzSgW7
0opKEu8hnlLqsIyU2BC2op/xOanipdbXObuFlA6bth1cYRI+YJlR3BbPGOIL6YbJ
ud9m0gIsBlCDLm4e/E45ZS+emudISP7/SF7zxvxZlnr1z7HTm7nIIVBvuQIDAQAB
AoGBAMzFQAccvU6GI6O4C5sOsiHUxMh3xtCftaxQVGgfQvVPVuXoeteep1Q0ewFl
IV4vnkO5pH8pTtVTWG9x5KIy6QCql4qvr2jkOm4mo9uogrpNklvBl2lN4Lxubj0N
mGRXaM3hckZl8+JT6uzfBfjy+pd8AOigJGPQCOZn4gmANW7pAkEA82Nh4wpj6ZRU
NBiBq3ONZuH4xJm59MI2FWRJsGUFUYdSaFwyKKim52/13d8iUb7v9utWQFRatCXz
Lqw9fQyVrwJBANm3dBOVxpUPrYEQsG0q2rdP+u6U3woylxwtQgJxImZKZmmJlPr8
9v23rhydvCe1ERPYe7EjF4RGWVPN3KLdExcCQDdzNfL3BApMS97OkoRQQC/nXbjU
2SPlN1MqVQuGCG8pqGG0V40h11y1CkvxMS10ldEojq77SOrwFnZUsXGS82sCQQC6
XdO7QCaxSq5XIRYlHN4EtS40NLOIYy3/LK6osHel4GIyTVd+UjSLk0QzssJxqwln
V5TqWQO0cxPcLQiFUYEZAkEA2G84ilb9QXOgbNyoE1VifNk49hhodbSskLb86uwY
Vgtzq1ZsqoPBCasr4WRiXt270n+mo5dNYRlZwiUn9lH78Q==
-----END RSA PRIVATE KEY-----

View file

@ -0,0 +1,6 @@
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDO/ahgFDvniFoQ1dm+MdnkBi+T
s5W9AtQNgw4ZHIdPnqEzSgW70opKEu8hnlLqsIyU2BC2op/xOanipdbXObuFlA6b
th1cYRI+YJlR3BbPGOIL6YbJud9m0gIsBlCDLm4e/E45ZS+emudISP7/SF7zxvxZ
lnr1z7HTm7nIIVBvuQIDAQAB
-----END PUBLIC KEY-----

View file

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA4GzZTLU48c4WbyvHi+QKrB71x+T0eq5hqDbQqnlYjhD1Ika7
io1iplsdJWJuyxfYbUkb2Ol0fj4koZ/GS6lgCZr4+8UHbr1qf0Eu5HZSpszs2YxY
8U5RHnrpw67co7hlgAR9HbyNf5XIYgLV9ldHH/eazwnc3F/hgNsV0xjScVilejgo
cJ4zcsyymvW8t42lteM7bI867ZuJhGop/V+Y0HFyrMsPoQyLuCUpr6ulOfrkr7ZO
dhAIG8r1HcjOp/AUjM15vfXcbUZjkM/VloifX1YitU3upMGJ8/DpFGffMOImrn5r
6BT494V8rRyN2qvQoAkLJpqZ0avLxwiR2lgVQQIDAQABAoIBAEH0Ozgr2fxWEInD
V/VooypKPvjr9F1JejGxSkmPN9MocKIOH3dsbZ1uEXa3ItBUxan4XlK06SNgp+tH
xULfF/Y6sQlsse59hBq50Uoa69dRShn1AP6JgZVvkduMPBNxUYL5zrs6emsQXb9Q
DglDRQfEAJ7vyxSIqQDxYcyT8uSUF70dqFe+E9B2VE3D6ccHc98k41pJrAFAUFH1
wwvDhfyYr7/Ultut9wzpZvU1meF3Vna3GOUHfxrG6wu1G+WIWHGjouzThsc1qiVI
BtMCJxuCt5fOXRbU4STbMqhB6sZHiOh6J/dZU6JwRYt+IS8FB6kCNFSEWZWQledJ
XqtYSQECgYEA9nmnFTRj3fTBq9zMXfCRujkSy6X2bOb39ftNXzHFuc+I6xmv/3Bs
P9tDdjueP/SnCb7i/9hXkpEIcxjrjiqgcvD2ym1hE4q+odMzRAXYMdnmzI34SVZE
U5hYJcYsXNKrTTleba7QgqdORmyJ9FwqLO40udvmrZMY223XDwgRkOkCgYEA6RkO
5wjjrWWp/G1YN3KXZTS1m2/eGrUThohXKAfAjbWWiouNLW2msXrxEWsPRL6xKiHu
X9cwZwzi3MstAgk+bphUGUVUkGKNDjWHJA25tDYjbPtkd6xbL4eCHsKpNL3HNYr9
N0CIvgn7qjaHRBem0iK7T6keY4axaSVddEwYapkCgYEA13K5qaB1F4Smcpt8DTWH
vPe8xUUaZlFzOJLmLCsuwmB2N8Ppg2j7RspcaxJsH021YaB5ftjWm+ipMSr8ZPY/
8JlPsNzxuYpTXtNmAbT2KYVm6THEch61dTk6/DIBf1YrpUJbl5by7vJeStL/uBmE
SGgksL5XIyzs0opuLdaIvFkCgYAyBLWE8AxjFfCvAQuwAj/ocLITo6KmWnrRIIqL
RXaVMgUWv7FQsTnW1cnK8g05tC2yG8vZ9wQk6Mf5lwOWb0NdWgSZ0528ydj41pWk
L+nMeN2LMjqxz2NVxJ8wWJcUgTCxFZ0WcRumo9/D+6V1ABpE9zz4cBLcSnfhVypB
nV6T6QKBgQCSZNCQ9HPxjAgYcsqc5sjNwuN1GHQZSav3Tye3k6zHENe1lsteT9K8
xciGIuhybKZBvB4yImIIHCtnH+AS+mHAGqHarjNDMfvjOq0dMibPx4+bkIiHdBIH
Xz+j5kmntvFiUnzr0Z/Tcqo+r8FvyCo1YWgwqGP8XoFrswD7gy7cZw==
-----END RSA PRIVATE KEY-----

View file

@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4GzZTLU48c4WbyvHi+QK
rB71x+T0eq5hqDbQqnlYjhD1Ika7io1iplsdJWJuyxfYbUkb2Ol0fj4koZ/GS6lg
CZr4+8UHbr1qf0Eu5HZSpszs2YxY8U5RHnrpw67co7hlgAR9HbyNf5XIYgLV9ldH
H/eazwnc3F/hgNsV0xjScVilejgocJ4zcsyymvW8t42lteM7bI867ZuJhGop/V+Y
0HFyrMsPoQyLuCUpr6ulOfrkr7ZOdhAIG8r1HcjOp/AUjM15vfXcbUZjkM/Vloif
X1YitU3upMGJ8/DpFGffMOImrn5r6BT494V8rRyN2qvQoAkLJpqZ0avLxwiR2lgV
QQIDAQAB
-----END PUBLIC KEY-----

View file

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAzHAVGaW9j4l3/b4ngcjjoIoIcnsQEWOMqErb5VhLZMGIq1gE
O5qxPDAwooKsNotzcAOB3ZyLn7p5D+dmOrNUYkYWgYITNGeSifrnVqQugd5Fh1L8
K7zOGltUo2UtjbN4uJ56tzxBMZp2wejs2/Qu0eu0xZK3To+YkDcWOk92rmNgmUSQ
C/kNyIOj+yBvOo3wTk6HvbhoIarCgJ6Lay1v/hMLyQLzwRY/Qfty1FTIDyTv2dch
47FsfkZ1KAL+MbUnHuCBPzGxRjXa8Iy9Z7YGxrYasUt1b0um64bscxoIiCu8yLL8
jlg01Rwrjr/MTwKRhwXlMp8B7HTonwtaG6arJwIDAQABAoIBAGFR4dmJusl/qW1T
fj8cQLAFxaupxaZhe24J5NAyzgEy2Dqo9ariIwkB78UM66ozjEqAgOvcP+NTw5m8
kD/VapA1yTTxlO7XdzzUAhiOo80S4IphCMZRZNPLMmluGtdf3lIUr1pXBrn0TCBX
H5o9jaREzpNXGof9d6T/dEdh2J9+uE/p1xE5GSxQfaPheZzCG7636La/DcArg/UR
+TusPqp62BEmk96pE/KKJRmEeH+WnPfSh6sMpLxi3hkEU7AynpliGT6Z6xV4csBI
S/rdpkcj5DWpbnQzkwdrnL2Q+POEq/vlx5/NlezvtQPNLvQWDyY4yBCoMKGb3EbX
xrxP7MECgYEA/kwe4P0Mqk+087IyhjDBGPfcMt8gfYc9nzNfIYSWdSwuSag/hqHq
I4GwHQzUV9ix3iM6w5hin10yAzWxCYZg9hquV+lSvNNpGB76FX6oOqwuAhyQMRwv
eW+VUyfFXeJugwL5JuIaNTvwPpQVDHYtELLifie+uzJ5HC6dhg/XchcCgYEAzc5/
+IXjOlExd/mBgFk/5Y87ifA0ZOgbaJXifYgU0aNSgz1piHxU3n2p4jJ9lSdwwCl2
Fb5EN7666t20PL5QcXJ5ZdaTRLzRlYiqTWzfYHBgttbB1Jl3Ed9GsKuzRgaRqGFC
ANJSqZlKG0NZ3keRtuKdFwq+IVOnsQr9g0TZiXECgYEAqUgtCiMKCloTIGMQpSnR
cXiWWjsUmturls4Q1vQ3YHrvuVLKLyqb/dT4Uu5WcMAs765OESThCit0/pQAbVHK
PCpYwubskAzAGjGM00BEZwJ1gixXhIm5xMIWCowgI7Z3ULlq+IptXeCvtkjHlksZ
BtO+WLLGkkEwRCV38WWcSzMCgYA/Xxqgl/mD94RYAQgTUWgPc69Nph08BQyLg7ue
E8z1UGkT6FEaqc4oRGGPOSTaTK63PQ0TXOb8k0pTD7l0CtYSWMFwzkXCoLGYbeCi
vqd5tqDRLAe7QxYa9rl5pSUqptMrGeeNATZa6sya4H5Hp5oCyny8n54z/OJh7ZRq
W0TwwQKBgQDDP7ksm2pcqadaVAmODdOlaDHbaEcxp8wN7YVz0lM3UpJth96ukbj7
S39eJhXYWOn6oJQb/lN9fGOYqjg3y6IchGZDp67ATvWYvn/NY0R7mt4K4oHx5TuN
rSQlP3WmOGv8Kemw892uRfW/jZyBEHhsfS213WDttVPn9F635GdNWw==
-----END RSA PRIVATE KEY-----

View file

@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzHAVGaW9j4l3/b4ngcjj
oIoIcnsQEWOMqErb5VhLZMGIq1gEO5qxPDAwooKsNotzcAOB3ZyLn7p5D+dmOrNU
YkYWgYITNGeSifrnVqQugd5Fh1L8K7zOGltUo2UtjbN4uJ56tzxBMZp2wejs2/Qu
0eu0xZK3To+YkDcWOk92rmNgmUSQC/kNyIOj+yBvOo3wTk6HvbhoIarCgJ6Lay1v
/hMLyQLzwRY/Qfty1FTIDyTv2dch47FsfkZ1KAL+MbUnHuCBPzGxRjXa8Iy9Z7YG
xrYasUt1b0um64bscxoIiCu8yLL8jlg01Rwrjr/MTwKRhwXlMp8B7HTonwtaG6ar
JwIDAQAB
-----END PUBLIC KEY-----

View file

@ -0,0 +1,51 @@
-----BEGIN RSA PRIVATE KEY-----
MIIJJwIBAAKCAgEAqETmgWBi5rCmb7euJplA/9xs65+bncc9Yvs5zjyycXSW82Jf
RuyguGm0OvA2wog24dR4N2kT/87DcGtp5JqJWADVFNr+2V2r6i57/OMLruRpn3p2
r95dmo0COE+BxPFl7XEBT8JbH57ZtpgcB3/xkS14nLOWFf96hrXPlXJC+VMVKVZm
A8k2LRh42vT5wUf4U0Doy/p7yFNSFFa6Q8wwe4TBy/z/f+rhFD1w8rxlYjallee/
ocm7bjZCwbJGMm7orLViqWfsFX3O35PeoJ5h/7uJ7iRwvTFERkTdwWP/0BeKBeIt
BR3YFc2mut+V9W+WKRkMSL6Crc+oVSx3p8aB7j9SZFzQiRtes4BYETpX1xl2mgIq
5hvsFbLw7ESrlIodiwUMTrSIid2DQ6q80kv1zXPr4+Id6L0sJLxPCaXnTmNtasSw
yedJJYxLjwhHJwtzFAeaq18H3O791YKhjAJ6YxK3zJ59jTE6Pkvqjq183f2PGHVR
vgSN7aCmI6MBUUB5wDP2K8zX2sh40/uPDVSd6ei1vl3DpPk+h8iExx6AzbohfqZ+
5RUUNx127L3MaQvOVC5TxV+R99gwKW++wzcVuO3m2KqVUj+K1uYBy3KBCUMBbckp
EWGbN++jcdV5oJX6fsC66nOmKlntYwCL/pRww+oLsbzF8J3dxeDbKNF9JDsCAwEA
AQKCAgBJF8TZJjlP5CQoGy227pNhkSpvH6HFY6qyuFZf09XfmrmHd4/Tiy41bRUx
FO90iR7t8hFWYHqjf/k9eCtDdi164MGukYJqgVoQG6kYLLgCfI21DMlJk9otLFtu
gnroRcP05EWhk9dpYONJgcGLMHSKj6n4x7nGTHe41HkbfcrB6ukiT7l4o4q5BAxb
cFadMtoXr/ZvxJrIZgkddJ7snGHjBcP5DCkgM7MZy6aoilWv1/UNrOF9MdgNA9zz
rrD3b136x7/XvqC6pS+bxuvJ8YK4R4qeu42NYT07GOcK/pk8lz0JWTodIt2eevqV
6lGFj7c2mv7PCpJRVgbVGL/RTVVap/+jbcRVLdnYKsII/dANG7iXnfwRgkLWet5D
OOsPuvIuyiSaJIwcdRE3SSO+tZhKLt+gh/oLxBPw5Ex0FwsVTtYn3Q/X3EAx+Wph
eFcRr3TVkDg0MfdWWkgk16DvYB5cWc29coTaH1g+2juadNHbtVAigwJorKc6sxH3
QGsW0WQJ8ZRZgJkSUuu3nr7QD3ZrgHptONQAh1RWGnIWi6OlMfaPdMo+SDnnL5SG
mpOPjWadDc1XvMFnKQYMYB5GWU/ZNmnZmDLyg1Pc0Y+qRUc0s83nZFHN60KnUrSz
0MZDspSFtr0fMx0b2/EB4EbuXd3QjQURF6P6HtWBu6oFnzu1AQKCAQEA2R9BKJgJ
vNP+DUu8NBzwmi0cKlAiaxt+w90i5DWq1XWPKgi+RVLkaQSJqHoYQVNgEwL/cWxp
s2r3GCMNIdOrGdcm8dX/6UYFpRaFcViTycVEA7cwZOMppgqr2Q+ZYX42K7HObUVL
JGvdEWWWfSsynUGsrG87DC1gl94ANxCdqkZdbW5d3X0w5v7M/1tlrmAeskZSZpeT
8BwwM6REb0U/B4/i8TLtLi/PGmMTOIxW41uKS/S6kq/gwyv+jNNO0ljhPt25iSbV
K5ZHS4YuPKLl0tZMaOkPco9s6t4ES/Y317zQoTzUkAAkkFO4QPzRZL0ESqVBNR0h
Ao7FLmFZzFHpoQKCAQEAxmZBn0UrJLXkD7bw66y4RwzjQYmxLlkEl3uvjrvVSuL1
mAHDW58aGIpFFZ8QSTtNewIBQYNifp/cdFHAagqtl/iMGEegaOpJAKu/ykrkfZUp
7mYDNng4ZWpypeKaGMAQoNzZiUpF+BDnqbeb/kgYu6sNlh9gRHR79rgAuZQxZ/1B
tE8WcUFi4CnTq2QLqX4LwMuZHWXAJQoMoW3K5av+J544lIM6GdMJuIONtBBkKVQD
ErrJ0bqYeykrFS6pKl/NBCZLGo5xFFRiYEdZ1GlA3uW3EGKppz6PS7194+x5UVts
xZPUfkgdFjWCczkl4JDoWfaNn5sgXtiVbGh1n3gYWwKCAQB7vHEg1kyuXU4qe5/d
PyTraIvlnVeQHNJIgy0QS3l5Pw8A0IzG6y+anehpqHNMP1zAWPQEytkOVAZPriIc
xgl7p37dUa0PX0V2SPhxmR5YXeCeEXc197PTmb9H67jos8nhauqOoW/qaMJK2M9D
tCubLUNf3eAT14R16CHNP93qnUE/TSeXQ3JsIofne0neb47u4F6zcuzvaNEbjSEn
HJqID7sw5GoA6WQo0I+yqWAXICMXmHf/gtYfxGHEFeSUwexULH5BKG1R8sncw7J0
Ag3h8xkGrNON4SkcTLy8Iay/eS6YxRcKndo4mk2mU65tr77TX4xi3Z/jWkQLY5WO
eJwhAoIBABO17wkSxyGDjJ/fDfpsE3bDmgRV2KuBHoqqOBvXH26sM7ghXLZKjT4o
5ooqXmTYJm91GIjYs71exnkr8hDW9L4nbEuxOgeSVyRg69H+NMshOaQ8sE8GDJxO
wgsnAyY4Vq6UomwYW/E0RL/AxRezM/nZGaVzgo3qgLJXP4MwbOQm7hMq1FD2LQuW
PDhH3Ty+kA5ca97W0Asd/3k+Pi0pNDvdZUOj8e7E369cKoTcKAdPGGsQ8aILhsCd
q3EUTKwwDl8+KrH9utBJPejQzeTjfBVo/xH6q145QeVFcy9ku/zQN3M9p5vQMEuX
j1lBMTkpTFw7uYBE2idyHw5BJoZsWQcCggEADfZTChqnOncItSflzGoaAACrr4/x
KyT/4A+cPMCs11JN9J+EWsCezya2o1l/NF7YPcBR4qjCmFMEiq5GxH5fGLQp0aa7
V13mHA8XBQ25OW2K7BGJhMHdbuvTnl6jsOfC4+t7P2bUAYxoP6/ncxTzZ5OlBN5k
aMv9firWl1kSKK75ww9DWn6j0rQ4dBetwX45EMcs+iKIdydg0fmJxR2EJ+uQsCFy
xcWBEDqV7qLUi6UrAPL3v/DXUv9wKcKOTbKw/aNE8+YTWMUO330GCJ5cVU1eTL5t
UrcNKOJkFIj7jJUCzv6vcy++hMJEbNXnnTVRnky6e9C2vwzMl33njntapg==
-----END RSA PRIVATE KEY-----

View file

@ -0,0 +1,14 @@
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqETmgWBi5rCmb7euJplA
/9xs65+bncc9Yvs5zjyycXSW82JfRuyguGm0OvA2wog24dR4N2kT/87DcGtp5JqJ
WADVFNr+2V2r6i57/OMLruRpn3p2r95dmo0COE+BxPFl7XEBT8JbH57ZtpgcB3/x
kS14nLOWFf96hrXPlXJC+VMVKVZmA8k2LRh42vT5wUf4U0Doy/p7yFNSFFa6Q8ww
e4TBy/z/f+rhFD1w8rxlYjallee/ocm7bjZCwbJGMm7orLViqWfsFX3O35PeoJ5h
/7uJ7iRwvTFERkTdwWP/0BeKBeItBR3YFc2mut+V9W+WKRkMSL6Crc+oVSx3p8aB
7j9SZFzQiRtes4BYETpX1xl2mgIq5hvsFbLw7ESrlIodiwUMTrSIid2DQ6q80kv1
zXPr4+Id6L0sJLxPCaXnTmNtasSwyedJJYxLjwhHJwtzFAeaq18H3O791YKhjAJ6
YxK3zJ59jTE6Pkvqjq183f2PGHVRvgSN7aCmI6MBUUB5wDP2K8zX2sh40/uPDVSd
6ei1vl3DpPk+h8iExx6AzbohfqZ+5RUUNx127L3MaQvOVC5TxV+R99gwKW++wzcV
uO3m2KqVUj+K1uYBy3KBCUMBbckpEWGbN++jcdV5oJX6fsC66nOmKlntYwCL/pRw
w+oLsbzF8J3dxeDbKNF9JDsCAwEAAQ==
-----END PUBLIC KEY-----

View file

@ -0,0 +1,202 @@
# frozen_string_literal: true
require_relative '../spec_helper'
require 'jwt'
describe 'README.md code test' do
context 'algorithm usage' do
let(:payload) { { data: 'test' } }
it 'NONE' do
token = JWT.encode payload, nil, 'none'
decoded_token = JWT.decode token, nil, false
expect(token).to eq 'eyJhbGciOiJub25lIn0.eyJkYXRhIjoidGVzdCJ9.'
expect(decoded_token).to eq [
{ 'data' => 'test' },
{ 'alg' => 'none' }
]
end
it 'HMAC' do
token = JWT.encode payload, 'my$ecretK3y', 'HS256'
decoded_token = JWT.decode token, 'my$ecretK3y', false
expect(token).to eq 'eyJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.pNIWIL34Jo13LViZAJACzK6Yf0qnvT_BuwOxiMCPE-Y'
expect(decoded_token).to eq [
{ 'data' => 'test' },
{ 'alg' => 'HS256' }
]
end
it 'RSA' do
rsa_private = OpenSSL::PKey::RSA.generate 2048
rsa_public = rsa_private.public_key
token = JWT.encode payload, rsa_private, 'RS256'
decoded_token = JWT.decode token, rsa_public, true, algorithm: 'RS256'
expect(decoded_token).to eq [
{ 'data' => 'test' },
{ 'alg' => 'RS256' }
]
end
it 'ECDSA' do
ecdsa_key = OpenSSL::PKey::EC.new 'prime256v1'
ecdsa_key.generate_key
ecdsa_public = OpenSSL::PKey::EC.new ecdsa_key
ecdsa_public.private_key = nil
token = JWT.encode payload, ecdsa_key, 'ES256'
decoded_token = JWT.decode token, ecdsa_public, true, algorithm: 'ES256'
expect(decoded_token).to eq [
{ 'data' => 'test' },
{ 'alg' => 'ES256' }
]
end
end
context 'claims' do
let(:hmac_secret) { 'MyP4ssW0rD' }
context 'exp' do
it 'without leeway' do
exp = Time.now.to_i + 4 * 3600
exp_payload = { data: 'data', exp: exp }
token = JWT.encode exp_payload, hmac_secret, 'HS256'
expect do
JWT.decode token, hmac_secret, true, algorithm: 'HS256'
end.not_to raise_error
end
it 'with leeway' do
exp = Time.now.to_i - 10
leeway = 30 # seconds
exp_payload = { data: 'data', exp: exp }
token = JWT.encode exp_payload, hmac_secret, 'HS256'
expect do
JWT.decode token, hmac_secret, true, leeway: leeway, algorithm: 'HS256'
end.not_to raise_error
end
end
context 'nbf' do
it 'without leeway' do
nbf = Time.now.to_i - 3600
nbf_payload = { data: 'data', nbf: nbf }
token = JWT.encode nbf_payload, hmac_secret, 'HS256'
expect do
JWT.decode token, hmac_secret, true, algorithm: 'HS256'
end.not_to raise_error
end
it 'with leeway' do
nbf = Time.now.to_i + 10
leeway = 30
nbf_payload = { data: 'data', nbf: nbf }
token = JWT.encode nbf_payload, hmac_secret, 'HS256'
expect do
JWT.decode token, hmac_secret, true, leeway: leeway, algorithm: 'HS256'
end.not_to raise_error
end
end
it 'iss' do
iss = 'My Awesome Company Inc. or https://my.awesome.website/'
iss_payload = { data: 'data', iss: iss }
token = JWT.encode iss_payload, hmac_secret, 'HS256'
expect do
JWT.decode token, hmac_secret, true, iss: iss, algorithm: 'HS256'
end.not_to raise_error
end
context 'aud' do
it 'array' do
aud = %w[Young Old]
aud_payload = { data: 'data', aud: aud }
token = JWT.encode aud_payload, hmac_secret, 'HS256'
expect do
JWT.decode token, hmac_secret, true, aud: %w[Old Young], verify_aud: true, algorithm: 'HS256'
end.not_to raise_error
end
it 'string' do
expect do
end.not_to raise_error
end
end
it 'jti' do
iat = Time.now.to_i
hmac_secret = 'test'
jti_raw = [hmac_secret, iat].join(':').to_s
jti = Digest::MD5.hexdigest(jti_raw)
jti_payload = { data: 'data', iat: iat, jti: jti }
token = JWT.encode jti_payload, hmac_secret, 'HS256'
expect do
JWT.decode token, hmac_secret, true, verify_jti: true, algorithm: 'HS256'
end.not_to raise_error
end
context 'iat' do
it 'without leeway' do
iat = Time.now.to_i
iat_payload = { data: 'data', iat: iat }
token = JWT.encode iat_payload, hmac_secret, 'HS256'
expect do
JWT.decode token, hmac_secret, true, verify_iat: true, algorithm: 'HS256'
end.not_to raise_error
end
it 'with leeway' do
iat = Time.now.to_i - 7
iat_payload = { data: 'data', iat: iat, leeway: 10 }
token = JWT.encode iat_payload, hmac_secret, 'HS256'
expect do
JWT.decode token, hmac_secret, true, verify_iat: true, algorithm: 'HS256'
end.not_to raise_error
end
end
context 'custom header fields' do
it 'with custom field' do
payload = { data: 'test' }
token = JWT.encode payload, nil, 'none', typ: 'JWT'
_, header = JWT.decode token, nil, false
expect(header['typ']).to eq 'JWT'
end
end
it 'sub' do
sub = 'Subject'
sub_payload = { data: 'data', sub: sub }
token = JWT.encode sub_payload, hmac_secret, 'HS256'
expect do
JWT.decode token, hmac_secret, true, 'sub' => sub, :verify_sub => true, :algorithm => 'HS256'
end.not_to raise_error
end
end
end

View file

@ -0,0 +1,232 @@
# frozen_string_literal: true
require 'spec_helper'
require 'jwt/verify'
module JWT
RSpec.describe Verify do
let(:base_payload) { { 'user_id' => 'some@user.tld' } }
let(:options) { { leeway: 0 } }
context '.verify_aud(payload, options)' do
let(:scalar_aud) { 'ruby-jwt-aud' }
let(:array_aud) { %w[ruby-jwt-aud test-aud ruby-ruby-ruby] }
let(:scalar_payload) { base_payload.merge('aud' => scalar_aud) }
let(:array_payload) { base_payload.merge('aud' => array_aud) }
it 'must raise JWT::InvalidAudError when the singular audience does not match' do
expect do
Verify.verify_aud(scalar_payload, options.merge(aud: 'no-match'))
end.to raise_error JWT::InvalidAudError
end
it 'must raise JWT::InvalidAudError when the payload has an array and none match the supplied value' do
expect do
Verify.verify_aud(array_payload, options.merge(aud: 'no-match'))
end.to raise_error JWT::InvalidAudError
end
it 'must allow a matching singular audience to pass' do
Verify.verify_aud(scalar_payload, options.merge(aud: scalar_aud))
end
it 'must allow an array with any value matching the one in the options' do
Verify.verify_aud(array_payload, options.merge(aud: array_aud.first))
end
it 'must allow an array with any value matching any value in the options array' do
Verify.verify_aud(array_payload, options.merge(aud: array_aud))
end
it 'must allow a singular audience payload matching any value in the options array' do
Verify.verify_aud(scalar_payload, options.merge(aud: array_aud))
end
end
context '.verify_expiration(payload, options)' do
let(:payload) { base_payload.merge('exp' => (Time.now.to_i - 5)) }
it 'must raise JWT::ExpiredSignature when the token has expired' do
expect do
Verify.verify_expiration(payload, options)
end.to raise_error JWT::ExpiredSignature
end
it 'must allow some leeway in the expiration when global leeway is configured' do
Verify.verify_expiration(payload, options.merge(leeway: 10))
end
it 'must allow some leeway in the expiration when exp_leeway is configured' do
Verify.verify_expiration(payload, options.merge(exp_leeway: 10))
end
it 'must be expired if the exp claim equals the current time' do
payload['exp'] = Time.now.to_i
expect do
Verify.verify_expiration(payload, options)
end.to raise_error JWT::ExpiredSignature
end
context 'when leeway is not specified' do
let(:options) { {} }
it 'used a default leeway of 0' do
expect do
Verify.verify_expiration(payload, options)
end.to raise_error JWT::ExpiredSignature
end
end
end
context '.verify_iat(payload, options)' do
let(:iat) { Time.now.to_f }
let(:payload) { base_payload.merge('iat' => iat) }
it 'must allow a valid iat' do
Verify.verify_iat(payload, options)
end
it 'must allow configured leeway' do
Verify.verify_iat(payload.merge('iat' => (iat + 60)), options.merge(leeway: 70))
end
it 'must allow configured iat_leeway' do
Verify.verify_iat(payload.merge('iat' => (iat + 60)), options.merge(iat_leeway: 70))
end
it 'must properly handle integer times' do
Verify.verify_iat(payload.merge('iat' => Time.now.to_i), options)
end
it 'must raise JWT::InvalidIatError when the iat value is not Numeric' do
expect do
Verify.verify_iat(payload.merge('iat' => 'not a number'), options)
end.to raise_error JWT::InvalidIatError
end
it 'must raise JWT::InvalidIatError when the iat value is in the future' do
expect do
Verify.verify_iat(payload.merge('iat' => (iat + 120)), options)
end.to raise_error JWT::InvalidIatError
end
end
context '.verify_iss(payload, options)' do
let(:iss) { 'ruby-jwt-gem' }
let(:payload) { base_payload.merge('iss' => iss) }
let(:invalid_token) { JWT.encode base_payload, payload[:secret] }
context 'when iss is a String' do
it 'must raise JWT::InvalidIssuerError when the configured issuer does not match the payload issuer' do
expect do
Verify.verify_iss(payload, options.merge(iss: 'mismatched-issuer'))
end.to raise_error JWT::InvalidIssuerError
end
it 'must raise JWT::InvalidIssuerError when the payload does not include an issuer' do
expect do
Verify.verify_iss(base_payload, options.merge(iss: iss))
end.to raise_error(JWT::InvalidIssuerError, /received <none>/)
end
it 'must allow a matching issuer to pass' do
Verify.verify_iss(payload, options.merge(iss: iss))
end
end
context 'when iss is an Array' do
it 'must raise JWT::InvalidIssuerError when no matching issuers in array' do
expect do
Verify.verify_iss(payload, options.merge(iss: %w[first second]))
end.to raise_error JWT::InvalidIssuerError
end
it 'must raise JWT::InvalidIssuerError when the payload does not include an issuer' do
expect do
Verify.verify_iss(base_payload, options.merge(iss: %w[first second]))
end.to raise_error(JWT::InvalidIssuerError, /received <none>/)
end
it 'must allow an array with matching issuer to pass' do
Verify.verify_iss(payload, options.merge(iss: ['first', iss, 'third']))
end
end
end
context '.verify_jti(payload, options)' do
let(:payload) { base_payload.merge('jti' => 'some-random-uuid-or-whatever') }
it 'must allow any jti when the verfy_jti key in the options is truthy but not a proc' do
Verify.verify_jti(payload, options.merge(verify_jti: true))
end
it 'must raise JWT::InvalidJtiError when the jti is missing' do
expect do
Verify.verify_jti(base_payload, options)
end.to raise_error JWT::InvalidJtiError, /missing/i
end
it 'must raise JWT::InvalidJtiError when the jti is an empty string' do
expect do
Verify.verify_jti(base_payload.merge('jti' => ' '), options)
end.to raise_error JWT::InvalidJtiError, /missing/i
end
it 'must raise JWT::InvalidJtiError when verify_jti proc returns false' do
expect do
Verify.verify_jti(payload, options.merge(verify_jti: ->(_jti) { false }))
end.to raise_error JWT::InvalidJtiError, /invalid/i
end
it 'true proc should not raise JWT::InvalidJtiError' do
Verify.verify_jti(payload, options.merge(verify_jti: ->(_jti) { true }))
end
it 'it should not throw arguement error with 2 args' do
expect do
Verify.verify_jti(payload, options.merge(verify_jti: ->(_jti, pl) {
true
}))
end.to_not raise_error
end
it 'should have payload as second param in proc' do
Verify.verify_jti(payload, options.merge(verify_jti: ->(_jti, pl) {
expect(pl).to eq(payload)
}))
end
end
context '.verify_not_before(payload, options)' do
let(:payload) { base_payload.merge('nbf' => (Time.now.to_i + 5)) }
it 'must raise JWT::ImmatureSignature when the nbf in the payload is in the future' do
expect do
Verify.verify_not_before(payload, options)
end.to raise_error JWT::ImmatureSignature
end
it 'must allow some leeway in the token age when global leeway is configured' do
Verify.verify_not_before(payload, options.merge(leeway: 10))
end
it 'must allow some leeway in the token age when nbf_leeway is configured' do
Verify.verify_not_before(payload, options.merge(nbf_leeway: 10))
end
end
context '.verify_sub(payload, options)' do
let(:sub) { 'ruby jwt subject' }
it 'must raise JWT::InvalidSubError when the subjects do not match' do
expect do
Verify.verify_sub(base_payload.merge('sub' => 'not-a-match'), options.merge(sub: sub))
end.to raise_error JWT::InvalidSubError
end
it 'must allow a matching sub' do
Verify.verify_sub(base_payload.merge('sub' => sub), options.merge(sub: sub))
end
end
end
end

View file

@ -0,0 +1,315 @@
require 'spec_helper'
require 'jwt'
require 'jwt/encode'
require 'jwt/decode'
describe JWT do
let(:payload) { { 'user_id' => 'some@user.tld' } }
let :data do
{
:secret => 'My$ecretK3y',
:rsa_private => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'rsa-2048-private.pem'))),
:rsa_public => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'rsa-2048-public.pem'))),
:wrong_rsa_private => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'rsa-2048-wrong-public.pem'))),
:wrong_rsa_public => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'rsa-2048-wrong-public.pem'))),
'ES256_private' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec256-private.pem'))),
'ES256_public' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec256-public.pem'))),
'ES384_private' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec384-private.pem'))),
'ES384_public' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec384-public.pem'))),
'ES512_private' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec512-private.pem'))),
'ES512_public' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec512-public.pem'))),
'ED25519_private' => RbNaCl::Signatures::Ed25519::SigningKey.new('abcdefghijklmnopqrstuvwxyzABCDEF'),
'ED25519_public' => RbNaCl::Signatures::Ed25519::SigningKey.new('abcdefghijklmnopqrstuvwxyzABCDEF').verify_key,
'NONE' => 'eyJhbGciOiJub25lIn0.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.',
'HS256' => 'eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.kWOVtIOpWcG7JnyJG0qOkTDbOy636XrrQhMm_8JrRQ8',
'HS512256' => 'eyJhbGciOiJIUzUxMjI1NiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.Ds_4ibvf7z4QOBoKntEjDfthy3WJ-3rKMspTEcHE2bA',
'HS384' => 'eyJhbGciOiJIUzM4NCJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.VuV4j4A1HKhWxCNzEcwc9qVF3frrEu-BRLzvYPkbWO0LENRGy5dOiBQ34remM3XH',
'HS512' => 'eyJhbGciOiJIUzUxMiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.8zNtCBTJIZTHpZ-BkhR-6sZY1K85Nm5YCKqV3AxRdsBJDt_RR-REH2db4T3Y0uQwNknhrCnZGvhNHrvhDwV1kA',
'RS256' => 'eyJhbGciOiJSUzI1NiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.eSXvWP4GViiwUALj_-qTxU68I1oM0XjgDsCZBBUri2Ghh9d75QkVDoZ_v872GaqunN5A5xcnBK0-cOq-CR6OwibgJWfOt69GNzw5RrOfQ2mz3QI3NYEq080nF69h8BeqkiaXhI24Q51joEgfa9aj5Y-oitLAmtDPYTm7vTcdGufd6AwD3_3jajKBwkh0LPSeMtbe_5EyS94nFoEF9OQuhJYjUmp7agsBVa8FFEjVw5jEgVqkvERSj5hSY4nEiCAomdVxIKBfykyi0d12cgjhI7mBFwWkPku8XIPGZ7N8vpiSLdM68BnUqIK5qR7NAhtvT7iyLFgOqhZNUQ6Ret5VpQ',
'RS384' => 'eyJhbGciOiJSUzM4NCJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.Sfgk56moPghtsjaP4so6tOy3I553mgwX-5gByMC6dX8lpeWgsxSeAd_K8IyO7u4lwYOL0DSftnqO1HEOuN1AKyBbDvaTXz3u2xNA2x4NYLdW4AZA6ritbYcKLO5BHTXw5ueMbtA1jjGXP0zI_aK2iJTMBmB8SCF88RYBUH01Tyf4PlLj98pGL-v3prZd6kZkIeRJ3326h04hslcB5HQKmgeBk24QNLIoIC-CD329HPjJ7TtGx01lj-ehTBnwVbBGzYFAyoalV5KgvL_MDOfWPr1OYHnR5s_Fm6_3Vg4u6lBljvHOrmv4Nfx7d8HLgbo8CwH4qn1wm6VQCtuDd-uhRg',
'RS512' => 'eyJhbGciOiJSUzUxMiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.LIIAUEuCkGNdpYguOO5LoW4rZ7ED2POJrB0pmEAAchyTdIK4HKh1jcLxc6KyGwZv40njCgub3y72q6vcQTn7oD0zWFCVQRIDW1911Ii2hRNHuigiPUnrnZh1OQ6z65VZRU6GKs8omoBGU9vrClBU0ODqYE16KxYmE_0n4Xw2h3D_L1LF0IAOtDWKBRDa3QHwZRM9sHsHNsBuD5ye9KzDYN1YALXj64LBfA-DoCKfpVAm9NkRPOyzjR2X2C3TomOSJgqWIVHJucudKDDAZyEbO4RA5pI-UFYy1370p9bRajvtDyoBuLDCzoSkMyQ4L2DnLhx5CbWcnD7Cd3GUmnjjTA',
'ES256' => '',
'ES384' => '',
'ES512' => ''
}
end
after(:each) do
expect(OpenSSL.errors).to be_empty
end
context 'alg: NONE' do
let(:alg) { 'none' }
it 'should generate a valid token' do
token = JWT.encode payload, nil, alg
expect(token).to eq data['NONE']
end
it 'should decode a valid token' do
jwt_payload, header = JWT.decode data['NONE'], nil, false
expect(header['alg']).to eq alg
expect(jwt_payload).to eq payload
end
it 'should display a better error message if payload exp is_a?(Time)' do
payload['exp'] = Time.now
expect do
JWT.encode payload, nil, alg
end.to raise_error JWT::InvalidPayload
end
it 'should display a better error message if payload exp is not an Integer' do
payload['exp'] = Time.now.to_i.to_s
expect do
JWT.encode payload, nil, alg
end.to raise_error JWT::InvalidPayload
end
end
%w[HS256 HS512256 HS384 HS512].each do |alg|
context "alg: #{alg}" do
it 'should generate a valid token' do
token = JWT.encode payload, data[:secret], alg
expect(token).to eq data[alg]
end
it 'should decode a valid token' do
jwt_payload, header = JWT.decode data[alg], data[:secret], true, algorithm: alg
expect(header['alg']).to eq alg
expect(jwt_payload).to eq payload
end
it 'wrong secret should raise JWT::DecodeError' do
expect do
JWT.decode data[alg], 'wrong_secret', true, algorithm: alg
end.to raise_error JWT::VerificationError
end
it 'wrong secret and verify = false should not raise JWT::DecodeError' do
expect do
JWT.decode data[alg], 'wrong_secret', false
end.not_to raise_error
end
end
end
%w[RS256 RS384 RS512].each do |alg|
context "alg: #{alg}" do
it 'should generate a valid token' do
token = JWT.encode payload, data[:rsa_private], alg
expect(token).to eq data[alg]
end
it 'should decode a valid token' do
jwt_payload, header = JWT.decode data[alg], data[:rsa_public], true, algorithm: alg
expect(header['alg']).to eq alg
expect(jwt_payload).to eq payload
end
it 'wrong key should raise JWT::DecodeError' do
key = OpenSSL::PKey.read File.read(File.join(CERT_PATH, 'rsa-2048-wrong-public.pem'))
expect do
JWT.decode data[alg], key, true, algorithm: alg
end.to raise_error JWT::DecodeError
end
it 'wrong key and verify = false should not raise JWT::DecodeError' do
key = OpenSSL::PKey.read File.read(File.join(CERT_PATH, 'rsa-2048-wrong-public.pem'))
expect do
JWT.decode data[alg], key, false
end.not_to raise_error
end
end
end
%w[ED25519].each do |alg|
context "alg: #{alg}" do
before(:each) do
data[alg] = JWT.encode payload, data["#{alg}_private"], alg
end
let(:wrong_key) { OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec256-wrong-public.pem'))) }
it 'should generate a valid token' do
jwt_payload, header = JWT.decode data[alg], data["#{alg}_public"], true, algorithm: alg
expect(header['alg']).to eq alg
expect(jwt_payload).to eq payload
end
it 'should decode a valid token' do
jwt_payload, header = JWT.decode data[alg], data["#{alg}_public"], true, algorithm: alg
expect(header['alg']).to eq alg
expect(jwt_payload).to eq payload
end
it 'wrong key should raise JWT::DecodeError' do
expect do
JWT.decode data[alg], wrong_key
end.to raise_error JWT::DecodeError
end
it 'wrong key and verify = false should not raise JWT::DecodeError' do
expect do
JWT.decode data[alg], wrong_key, false
end.not_to raise_error
end
end
end
%w[ES256 ES384 ES512].each do |alg|
context "alg: #{alg}" do
before(:each) do
data[alg] = JWT.encode payload, data["#{alg}_private"], alg
end
let(:wrong_key) { OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec256-wrong-public.pem'))) }
it 'should generate a valid token' do
jwt_payload, header = JWT.decode data[alg], data["#{alg}_public"], true, algorithm: alg
expect(header['alg']).to eq alg
expect(jwt_payload).to eq payload
end
it 'should decode a valid token' do
jwt_payload, header = JWT.decode data[alg], data["#{alg}_public"], true, algorithm: alg
expect(header['alg']).to eq alg
expect(jwt_payload).to eq payload
end
it 'wrong key should raise JWT::DecodeError' do
expect do
JWT.decode data[alg], wrong_key
end.to raise_error JWT::DecodeError
end
it 'wrong key and verify = false should not raise JWT::DecodeError' do
expect do
JWT.decode data[alg], wrong_key, false
end.not_to raise_error
end
end
end
context 'Invalid' do
it 'algorithm should raise NotImplementedError' do
expect do
JWT.encode payload, 'secret', 'HS255'
end.to raise_error NotImplementedError
end
it 'ECDSA curve_name should raise JWT::IncorrectAlgorithm' do
key = OpenSSL::PKey::EC.new 'secp256k1'
key.generate_key
expect do
JWT.encode payload, key, 'ES256'
end.to raise_error JWT::IncorrectAlgorithm
token = JWT.encode payload, data['ES256_private'], 'ES256'
key.private_key = nil
expect do
JWT.decode token, key
end.to raise_error JWT::IncorrectAlgorithm
end
end
context 'Verify' do
context 'algorithm' do
it 'should raise JWT::IncorrectAlgorithm on mismatch' do
token = JWT.encode payload, data[:secret], 'HS256'
expect do
JWT.decode token, data[:secret], true, algorithm: 'HS384'
end.to raise_error JWT::IncorrectAlgorithm
expect do
JWT.decode token, data[:secret], true, algorithm: 'HS256'
end.not_to raise_error
end
it 'should raise JWT::IncorrectAlgorithm when algorithms array does not contain algorithm' do
token = JWT.encode payload, data[:secret], 'HS512'
expect do
JWT.decode token, data[:secret], true, algorithms: ['HS384']
end.to raise_error JWT::IncorrectAlgorithm
expect do
JWT.decode token, data[:secret], true, algorithms: ['HS512', 'HS384']
end.not_to raise_error
end
context 'no algorithm provided' do
it 'should use the default decode algorithm' do
token = JWT.encode payload, data[:rsa_public].to_s
jwt_payload, header = JWT.decode token, data[:rsa_public].to_s
expect(header['alg']).to eq 'HS256'
expect(jwt_payload).to eq payload
end
end
end
context 'issuer claim' do
let(:iss) { 'ruby-jwt-gem' }
let(:invalid_token) { JWT.encode payload, data[:secret] }
let :token do
iss_payload = payload.merge(iss: iss)
JWT.encode iss_payload, data[:secret]
end
it 'if verify_iss is set to false (default option) should not raise JWT::InvalidIssuerError' do
expect do
JWT.decode token, data[:secret], true, iss: iss, algorithm: 'HS256'
end.not_to raise_error
end
end
end
context 'Base64' do
it 'urlsafe replace + / with - _' do
allow(Base64).to receive(:encode64) { 'string+with/non+url-safe/characters_' }
expect(JWT::Encode.base64url_encode('foo')).to eq('string-with_non-url-safe_characters_')
end
end
it 'should not verify token even if the payload has claims' do
head = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9'
load = 'eyJ1c2VyX2lkIjo1NCwiZXhwIjoxNTA0MzkwODA0fQ'
sign = 'Skpi6FfYMbZ-DwW9ocyRIosNMdPMAIWRLYxRO68GTQk'
expect do
JWT.decode([head, load, sign].join('.'), '', false)
end.not_to raise_error
end
it 'should not raise InvalidPayload exception if payload is an array' do
expect do
JWT.encode(['my', 'payload'], 'secret')
end.not_to raise_error
end
it 'should encode string payloads' do
expect do
JWT.encode 'Hello World', 'secret'
end.not_to raise_error
end
end

View file

@ -0,0 +1,28 @@
require 'rspec'
require 'simplecov'
require 'simplecov-json'
require 'codeclimate-test-reporter'
require 'codacy-coverage'
Codacy::Reporter.start
SimpleCov.configure do
root File.join(File.dirname(__FILE__), '..')
project_name 'Ruby JWT - Ruby JSON Web Token implementation'
add_filter 'spec'
end
SimpleCov.start if ENV['COVERAGE']
CERT_PATH = File.join(File.dirname(__FILE__), 'fixtures', 'certs')
RSpec.configure do |config|
config.expect_with :rspec do |c|
c.syntax = %i[should expect]
end
config.run_all_when_everything_filtered = true
config.filter_run :focus
config.order = 'random'
end