-
Notifications
You must be signed in to change notification settings - Fork 376
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #49 from excpt/master
Preperations for version 2.x
- Loading branch information
Showing
20 changed files
with
601 additions
and
441 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
/.idea | ||
/coverage | ||
/tmp | ||
*.iml | ||
jwt.gemspec | ||
pkg | ||
Gemfile.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
--color |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,14 @@ | ||
sudo: false | ||
language: ruby | ||
rvm: | ||
- 1.8.7 | ||
- 1.9.2 | ||
- 1.9.3 | ||
- 2.0.0 | ||
- 2.1.0 | ||
- jruby | ||
- rbx | ||
- ree | ||
script: "bundle exec rake test" | ||
- 2.1.5 | ||
- 2.2.0 | ||
script: "bundle exec rspec" | ||
before_install: | ||
- gem update --system | ||
- gem --version | ||
before_script: | ||
- bin/prepare-test.sh |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,13 @@ | ||
source "https://rubygems.org" | ||
source 'https://rubygems.org' | ||
|
||
gem 'json', '>= 1.2.4' | ||
gem 'multi_json', '~> 1.0', :platforms => :ruby_18 | ||
gem 'jruby-openssl', :platforms => :jruby | ||
|
||
gem 'rubysl', '~> 2.0', :platforms => :rbx | ||
gem 'json' | ||
|
||
group :development do | ||
gem 'echoe', '>= 4.6.3' | ||
end | ||
|
||
group :test, :development do | ||
gem 'rake' | ||
gem 'rspec', '~> 3' | ||
gem 'rspec' | ||
gem 'codeclimate-test-reporter', require: false | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,21 @@ | ||
# JWT | ||
A Ruby implementation of [JSON Web Token draft 06](http://self-issued.info/docs/draft-jones-json-web-token-06.html). | ||
|
||
## Installing | ||
|
||
sudo gem install jwt | ||
|
||
## Usage | ||
# WARNING: This is the 2.x branch of ruby-jwt, currently under heavy development | ||
|
||
JWT.encode({"some" => "payload"}, "secret") | ||
# JWT | ||
|
||
Note the resulting JWT will not be encrypted, but verifiable with a secret key. | ||
[![Build Status](https://travis-ci.org/excpt/ruby-jwt.svg?branch=refactoring)](https://travis-ci.org/excpt/ruby-jwt) | ||
[![Codeship Status for excpt/moments](https://codeship.com/projects/f94b6890-6dc3-0132-8f82-52110d7a425c/status?branch=master)](https://codeship.com/projects/54274) | ||
[![Code Climate](https://codeclimate.com/github/excpt/ruby-jwt/badges/gpa.svg)](https://codeclimate.com/github/excpt/ruby-jwt) | ||
[![Test Coverage](https://codeclimate.com/github/excpt/ruby-jwt/badges/coverage.svg)](https://codeclimate.com/github/excpt/ruby-jwt) | ||
|
||
JWT.decode("someJWTstring", "secret") | ||
## Goal | ||
|
||
If the secret is wrong, it will raise a `JWT::DecodeError` telling you as such. You can still get at the payload by setting the verify argument to false. | ||
The goal is to implement the complete JWT spec including the underlying specs JWS, JWA, JWK and JWE. | ||
|
||
JWT.decode("someJWTstring", nil, false) | ||
* [JSON Web Token (JWT)](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32) | ||
* [JSON Web Signature (JWS)](https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-39) | ||
* [JSON Web Encryption (JWE)](https://tools.ietf.org/html/draft-ietf-jose-json-web-encryption-39) | ||
* [JSON Web Key (JWK)](https://tools.ietf.org/html/draft-ietf-jose-json-web-key-39) | ||
* [JSON Web Algorithms (JWA)](https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-39) | ||
|
||
## Algorithms | ||
|
||
|
@@ -33,16 +33,50 @@ The JWT spec supports several algorithms for cryptographic signing. This library | |
* RS384 - RSA using SHA-384 hash algorithm | ||
* RS512 - RSA using SHA-512 hash algorithm | ||
|
||
**NONE** | ||
|
||
* NONE - No signature | ||
|
||
## Installing | ||
|
||
```bash | ||
sudo gem install jwt | ||
``` | ||
|
||
## Usage | ||
|
||
Signing a JSON Web Token. | ||
|
||
```ruby | ||
JWT.encode({some: 'payload'}, 'secret') | ||
``` | ||
|
||
Note: The resulting JWT will not be encrypted, but verifiable with a secret key. | ||
|
||
```ruby | ||
JWT.decode('someJWTstring', 'secret') | ||
``` | ||
|
||
If the secret is wrong, it will raise a `JWT::DecodeError` telling you as such. You can still get at the payload by setting the verify argument to false. | ||
|
||
```ruby | ||
JWT.decode('someJWTstring', nil, false) | ||
``` | ||
|
||
Change the algorithm with by setting it in encode: | ||
|
||
JWT.encode({"some" => "payload"}, "secret", "HS512") | ||
```ruby | ||
JWT.encode({some: 'payload'}, 'secret', 'HS512') | ||
``` | ||
|
||
**Plaintext** | ||
|
||
We also support unsigned plaintext JWTs as introduced by draft 03 by explicitly specifying `nil` as the key and algorithm: | ||
|
||
jwt = JWT.encode({"some" => "payload"}, nil, nil) | ||
JWT.decode(jwt, nil, nil) | ||
```ruby | ||
jwt = JWT.encode({some: 'payload'}, nil, nil) | ||
JWT.decode(jwt, nil, nil) | ||
``` | ||
|
||
## Support for reserved claim names | ||
JSON Web Token defines some reserved claim names and defines how they should be | ||
|
@@ -64,18 +98,21 @@ From [draft 01 of the JWT spec](http://self-issued.info/docs/draft-jones-json-we | |
You pass the expiration time as a UTC UNIX timestamp (an int). For example: | ||
|
||
JWT.encode({"exp": 1371720939}, "secret") | ||
|
||
JWT.encode({"exp": Time.now.to_i()}, "secret") | ||
```ruby | ||
JWT.encode({exp: 1371720939}, 'secret') | ||
JWT.encode({exp: Time.now.to_i()}, 'secret') | ||
``` | ||
|
||
Expiration time is automatically verified in `JWT.decode()` and raises | ||
`JWT::ExpiredSignature` if the expiration time is in the past: | ||
|
||
begin | ||
JWT.decode("JWT_STRING", "secret") | ||
rescue JWT::ExpiredSignature | ||
# Signature has expired | ||
end | ||
```ruby | ||
begin | ||
JWT.decode('JWT_STRING', 'secret') | ||
rescue JWT::ExpiredSignature | ||
# Signature has expired | ||
end | ||
``` | ||
|
||
Expiration time will be compared to the current UTC time (as given by | ||
`Time.now.to_i`), so be sure to use a UTC timestamp or datetime in encoding. | ||
|
@@ -88,21 +125,27 @@ For example, if you have a JWT payload with a expiration time set to 30 seconds | |
after creation but you know that sometimes you will process it after 30 seconds, | ||
you can set a leeway of 10 seconds in order to have some margin: | ||
|
||
jwt_payload = JWT.encode({'exp': Time.now.to_i + 30}, 'secret') | ||
sleep(32) | ||
# jwt_payload is now expired | ||
# But with some leeway, it will still validate | ||
JWT.decode(jwt_payload, 'secret', true, leeway=10) | ||
```ruby | ||
jwt_payload = JWT.encode({exp: Time.now.to_i + 30}, 'secret') | ||
sleep(32) | ||
# jwt_payload is now expired | ||
# But with some leeway, it will still validate | ||
JWT.decode(jwt_payload, 'secret', true, leeway=10) | ||
``` | ||
|
||
## Development and Tests | ||
|
||
We depend on [Echoe](http://rubygems.org/gems/echoe) for defining gemspec and performing releases to rubygems.org, which can be done with | ||
|
||
rake release | ||
```bash | ||
rake release | ||
``` | ||
|
||
The tests are written with rspec. Given you have rake and rspec, you can run tests with | ||
|
||
rake test | ||
```bash | ||
rake test | ||
``` | ||
|
||
**If you want a release cut with your PR, please include a version bump according to [Semantic Versioning](http://semver.org/)** | ||
|
||
|
@@ -118,6 +161,7 @@ The tests are written with rspec. Given you have rake and rspec, you can run tes | |
* Ariel Salomon (Oscil8) | ||
* Paul Battley <[email protected]> | ||
* Zane Shannon [@zshannon](https://github.com/zshannon) | ||
* Tim Rudat <[email protected]> [@excpt](https://github.com/excpt) | ||
|
||
## License | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,16 +2,16 @@ require 'rubygems' | |
require 'rake' | ||
require 'echoe' | ||
|
||
Echoe.new('jwt', '1.2.0') do |p| | ||
p.description = "JSON Web Token implementation in Ruby" | ||
p.url = "http://github.com/progrium/ruby-jwt" | ||
p.author = "Jeff Lindsay" | ||
p.email = "[email protected]" | ||
p.ignore_pattern = ["tmp/*"] | ||
p.development_dependencies = ["echoe >=4.6.3"] | ||
p.licenses = "MIT" | ||
Echoe.new('jwt', '2.0.0.pre') do |p| | ||
p.description = 'JSON Web Token implementation in Ruby' | ||
p.url = 'http://github.com/progrium/ruby-jwt' | ||
p.author = 'Jeff Lindsay' | ||
p.email = '[email protected]' | ||
p.ignore_pattern = ['tmp/*'] | ||
p.development_dependencies = ['echoe >=4.6.3'] | ||
p.licenses = 'MIT' | ||
end | ||
|
||
task :test do | ||
sh "rspec spec/jwt_spec.rb" | ||
sh 'bundle exec rspec' | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#!/bin/sh | ||
|
||
rm -rf tmp/certs/*.pem | ||
|
||
mkdir -p tmp/certs | ||
|
||
# RSA KEYS | ||
openssl genrsa 1024 > tmp/certs/rsa-1024-private.pem | ||
openssl rsa -in tmp/certs/rsa-1024-private.pem -pubout > tmp/certs/rsa-1024-public.pem | ||
openssl genrsa 2048 > tmp/certs/rsa-2048-private.pem | ||
openssl genrsa 2048 > tmp/certs/rsa-2048-wrong-private.pem | ||
openssl rsa -in tmp/certs/rsa-2048-private.pem -pubout > tmp/certs/rsa-2048-public.pem | ||
openssl rsa -in tmp/certs/rsa-2048-wrong-private.pem -pubout > tmp/certs/rsa-2048-wrong-public.pem | ||
openssl genrsa 4096 > tmp/certs/rsa-4096-private.pem | ||
openssl rsa -in tmp/certs/rsa-4096-private.pem -pubout > tmp/certs/rsa-4096-public.pem | ||
|
||
# ECDSA KEYS | ||
openssl ecparam -out tmp/certs/ec256-private.pem -name secp256k1 -genkey | ||
openssl ecparam -out tmp/certs/ec256-wrong-private.pem -name secp256k1 -genkey | ||
openssl ecparam -out tmp/certs/ec384-private.pem -name secp384r1 -genkey | ||
openssl ecparam -out tmp/certs/ec384-wrong-private.pem -name secp384r1 -genkey | ||
openssl ecparam -out tmp/certs/ec512-private.pem -name secp521r1 -genkey | ||
openssl ecparam -out tmp/certs/ec512-wrong-private.pem -name secp521r1 -genkey | ||
openssl ec -in tmp/certs/ec256-private.pem -pubout > tmp/certs/ec256-public.pem | ||
openssl ec -in tmp/certs/ec256-wrong-private.pem -pubout > tmp/certs/ec256-wrong-public.pem | ||
openssl ec -in tmp/certs/ec384-private.pem -pubout > tmp/certs/ec384-public.pem | ||
openssl ec -in tmp/certs/ec384-wrong-private.pem -pubout > tmp/certs/ec384-wrong-public.pem | ||
openssl ec -in tmp/certs/ec512-private.pem -pubout > tmp/certs/ec512-public.pem | ||
openssl ec -in tmp/certs/ec512-wrong-private.pem -pubout > tmp/certs/ec512-wrong-public.pem |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
require 'jwa/hmac' | ||
require 'jwa/none' | ||
require 'jwa/rsassa' | ||
|
||
module JWA | ||
extend self | ||
|
||
# The complete list of signing algorithms defined in the IETF JSON Web Algorithms (JWA) version 38 | ||
# https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-38#section-3.1 | ||
ALGORITHMS = %w(HS256 HS384 HS512 RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512 none) | ||
|
||
# raises if the payload is not a string | ||
class InvalidPayloadFormat < ArgumentError | ||
end | ||
|
||
# raises if a algorithm is called that is not defined in the specs | ||
# Info: all algorithms a case-sensitive | ||
class InvalidAlgorithm < ArgumentError | ||
end | ||
|
||
# raises if a secret or key is required but not provided in order to sign the data | ||
class MissingSecretOrKey < ArgumentError | ||
end | ||
|
||
# raises if a part of code is not implemented | ||
class NotImplemented < ArgumentError | ||
end | ||
|
||
def sign(algorithm, data, secret_or_private_key = '') | ||
algo, bits = validate_algorithm algorithm | ||
validate_data data | ||
|
||
case algo | ||
when 'HS' | ||
JWA::HMAC.new(bits).sign(data, secret_or_private_key) | ||
when 'RS' | ||
JWA::RSASSA.new(bits).sign(data, secret_or_private_key) | ||
when 'none' | ||
JWA::NONE.new.sign() | ||
else | ||
raise JWA::NotImplemented.new("JWA: #{algorithm} is not implemented yet.") | ||
end | ||
end | ||
|
||
def verify(algorithm, data, signature, secret_or_public_key = '') | ||
algo, bits = validate_algorithm algorithm | ||
validate_data data | ||
|
||
case algo | ||
when 'HS' | ||
JWA::HMAC.new(bits).verify(data, signature, secret_or_public_key) | ||
when 'RS' | ||
JWA::RSASSA.new(bits).verify(data, signature, secret_or_public_key) | ||
when 'none' | ||
JWA::NONE.new.verify() | ||
else | ||
raise JWA::NotImplemented.new("JWA: #{algorithm} is not implemented yet.") | ||
end | ||
end | ||
|
||
def validate_algorithm(algorithm) | ||
raise JWA::InvalidAlgorithm.new("JWA: Given algorithm [#{algorithm.to_s}] is not part of the JWS supported algorithms.") unless ALGORITHMS.include? algorithm | ||
|
||
match = algorithm.match(/(HS|RS|ES|PS|none)(\d+)?/) | ||
|
||
[match[1], match[2]] | ||
end | ||
|
||
private :validate_algorithm | ||
|
||
def validate_data(data) | ||
raise JWA::InvalidPayloadFormat.new('JWA: Given data is not a string.') unless data.is_a? String | ||
end | ||
|
||
private :validate_data | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
module JWA | ||
class HMAC | ||
def initialize(bits) | ||
@bits = bits | ||
end | ||
|
||
def sign(data, secret) | ||
validate_secret secret | ||
|
||
signature = OpenSSL::HMAC.digest OpenSSL::Digest.new("sha#{@bits}"), secret, data | ||
|
||
JWT::Base64.encode signature | ||
end | ||
|
||
def verify(data, signature, secret) | ||
signature === sign(data, secret) | ||
end | ||
|
||
def validate_secret(secret) | ||
raise JWA::MissingSecretOrKey.new('JWA: HMAC signing always requires a secret to be set.') if secret.length == 0 | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
module JWA | ||
class NONE | ||
def sign | ||
'' | ||
end | ||
|
||
def verify | ||
true | ||
end | ||
end | ||
end |
Oops, something went wrong.