rack-jwt 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e20bf24155aaeda649c643bde660ed334b5e081d
4
- data.tar.gz: 125bff003cd0fc9f3d2ec2feb7fd7d1fa01438bc
3
+ metadata.gz: 2cdc1b0bd5715e4d4d5e8cd04822d0e6825b089f
4
+ data.tar.gz: 2397aac243a1d587e109f46942cecdaaccb9b5cd
5
5
  SHA512:
6
- metadata.gz: 8ebece61f89d84ae0b61e82a3631a556a09597bbc2e6265eb9beacc6ef958859ceb2f7ab6bcdabf407ee36e97160396ce7db80da7791d611860329560f5c77b7
7
- data.tar.gz: 85107621925d5e21c2a8d7d275b429622155a596a49cad78520dcb93f80ba7104ac6e84f4a627095fbb685f74eee28680fc242f7ed91c883c76faa937a69d7b5
6
+ metadata.gz: 1ccae31dc0d69b94d0da8243276c532b2793dbae1563da3b328a163d9f03f5284abb58f60a193b8e421591ca9f9ff0e2b1b6bac9dcd80a0954525b6ffd25d371
7
+ data.tar.gz: 03b28fa23d5d00bce804435ff76c6e1dd4f873f6c5d49bf8830ee5295ad747d90e5dbfba7fcb371d34f58968534fb7725e1545272ec82a48f78b582808f62019
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ rvm:
2
+ - 1.9.3
3
+ - 2.0.0
4
+ - 2.2.0
data/README.md CHANGED
@@ -1,4 +1,8 @@
1
- # Rack::Jwt
1
+ # Rack::JWT
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/rack-jwt.svg)](http://badge.fury.io/rb/rack-jwt)
4
+ [![Build Status](https://travis-ci.org/eigenbart/rack-jwt.svg)](https://travis-ci.org/eigenbart/rack-jwt)
5
+ [![Code Climate](https://codeclimate.com/github/eigenbart/rack-jwt/badges/gpa.svg)](https://codeclimate.com/github/eigenbart/rack-jwt)
2
6
 
3
7
  This gem provides JSON Web Token (JWT) based authentication.
4
8
 
data/Rakefile CHANGED
@@ -1,2 +1,9 @@
1
1
  require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
2
3
 
4
+ desc "Run RSpec"
5
+ RSpec::Core::RakeTask.new do |t|
6
+ t.verbose = false
7
+ end
8
+
9
+ task :default => :spec
data/lib/rack/jwt/auth.rb CHANGED
@@ -10,57 +10,49 @@ module Rack
10
10
  end
11
11
 
12
12
  def call(env)
13
- if @exclude.include? env["PATH_INFO"]
13
+ if @exclude.include? env['PATH_INFO']
14
14
  @app.call(env)
15
- elsif env["HTTP_AUTHORIZATION"]
16
- begin
17
- if env["HTTP_AUTHORIZATION"].split(" ").first != 'Bearer'
18
- invalid_auth_header
19
- else
20
- token = env["HTTP_AUTHORIZATION"].split(" ")[-1]
21
- decoded_token = Token.decode(token, @secret)
22
- env["jwt.header"] = decoded_token.last
23
- env["jwt.payload"] = decoded_token.first
24
- @app.call(env)
25
- end
26
- rescue
27
- unauthorized
28
- end
29
15
  else
30
- no_auth_header
16
+ check_jwt_token(env)
31
17
  end
32
18
  end
33
19
 
34
20
  private
35
21
 
36
- def unauthorized
37
- body = { error: "Invalid JWT token" }.to_json
38
- headers = {
39
- 'Content-Type' => 'application/json',
40
- 'Content-Length' => body.bytesize.to_s
41
- }
42
-
43
- return [401, headers, [body]]
22
+ def check_jwt_token(env)
23
+ if valid_header?(env)
24
+ begin
25
+ token = env['HTTP_AUTHORIZATION'].split(' ')[-1]
26
+ decoded_token = Token.decode(token, @secret)
27
+ env['jwt.header'] = decoded_token.last
28
+ env['jwt.payload'] = decoded_token.first
29
+ @app.call(env)
30
+ rescue
31
+ return_error('Invalid JWT token')
32
+ end
33
+ else
34
+ return_jwt_header_error(env)
35
+ end
44
36
  end
45
37
 
46
- def no_auth_header
47
- body = { error: "Missing Authorization header" }.to_json
48
- headers = {
49
- 'Content-Type' => 'application/json',
50
- 'Content-Length' => body.bytesize.to_s
51
- }
38
+ def return_jwt_header_error(env)
39
+ if env['HTTP_AUTHORIZATION'].nil?
40
+ return_error('Missing Authorization header')
41
+ elsif env['HTTP_AUTHORIZATION'].split(' ').first != 'Bearer'
42
+ return_error('Invalid Authorization header format')
43
+ end
44
+ end
52
45
 
53
- return [401, headers, [body]]
46
+ def valid_header?(env)
47
+ env['HTTP_AUTHORIZATION'] =~ /\ABearer \S*\.\S*\.\S*\z/
54
48
  end
55
49
 
56
- def invalid_auth_header
57
- body = { error: "Invalid Authorization header format" }.to_json
58
- headers = {
59
- 'Content-Type' => 'application/json',
60
- 'Content-Length' => body.bytesize.to_s
61
- }
50
+ def return_error(message)
51
+ body = { error: message }.to_json
52
+ headers = { 'Content-Type' => 'application/json',
53
+ 'Content-Length' => body.bytesize.to_s }
62
54
 
63
- return [401, headers, [body]]
55
+ [401, headers, [body]]
64
56
  end
65
57
  end
66
58
  end
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  module Jwt
3
- VERSION = "0.1.0"
3
+ VERSION = "0.1.1"
4
4
  end
5
5
  end
data/rack-jwt.gemspec CHANGED
@@ -17,9 +17,10 @@ Gem::Specification.new do |spec|
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
+ spec.required_ruby_version = '>= 1.9.3'
20
21
 
21
- spec.add_development_dependency "bundler", "~> 1.7"
22
- spec.add_development_dependency "rake", "~> 10.0"
22
+ spec.add_development_dependency 'bundler', '~> 1.7'
23
+ spec.add_development_dependency 'rake', '~> 10.0.0'
23
24
  spec.add_development_dependency 'rack-test', '~> 0.6.3'
24
25
  spec.add_development_dependency 'rspec', '~> 3.2.0'
25
26
 
data/spec/auth_spec.rb CHANGED
@@ -5,64 +5,107 @@ describe Rack::JWT::Auth do
5
5
 
6
6
  let(:issuer) { Rack::JWT::Token }
7
7
  let(:secret) { 'foo' }
8
+ let(:body) {{ 'foo' => 'bar' }}
8
9
 
9
10
  let(:app) do
10
- main_app = lambda { |env| [200, env, ['Hello']] }
11
- Rack::JWT::Auth.new(main_app, {secret: secret})
11
+ main_app = lambda { |env| [200, env, [body.to_json]] }
12
+ Rack::JWT::Auth.new(main_app, { secret: secret })
12
13
  end
13
14
 
14
- it 'raises an exception if no secret if provided' do
15
- expect{ Rack::JWT::Auth.new(main_app, {}) }.to raise_error
15
+ before do
16
+ get('/', {}, headers)
16
17
  end
17
18
 
18
- it 'returns 200 ok if the request is authenticated' do
19
- token = issuer.encode({ iss: 1 }, secret)
20
- get('/', {}, {'HTTP_AUTHORIZATION' => 'Bearer #{token}'})
19
+ context 'when no secret provided' do
20
+ let(:headers) { {} }
21
21
 
22
- expect(last_response.status).to eq 200
23
- expect(last_response.body).to eq 'Hello'
22
+ it 'raises an exception' do
23
+ expect{ Rack::JWT::Auth.new(main_app, {}) }.to raise_error
24
+ end
25
+ end
26
+
27
+ context 'when no authorization header provided' do
28
+ let(:headers) { {} }
29
+
30
+ subject { JSON.parse(last_response.body) }
24
31
 
25
- payload = last_response.header['jwt.payload']
32
+ it 'returns 401 status code' do
33
+ expect(last_response.status).to eq(401)
34
+ end
26
35
 
27
- expect(payload['iss']).to eql(1)
36
+ it 'returns an error message' do
37
+ expect(subject['error']).to eq('Missing Authorization header')
38
+ end
28
39
  end
29
40
 
30
- it 'returns 401 if the authorization header is missing' do
31
- get('/')
41
+ context 'when authorzation header does not contain the schema' do
42
+ let(:token) { issuer.encode({ iss: 1 }, secret) }
43
+ let(:headers) {{ 'HTTP_AUTHORIZATION' => token }}
32
44
 
33
- jsonResponse = JSON.parse(last_response.body)
45
+ subject { JSON.parse(last_response.body) }
34
46
 
35
- expect(last_response.status).to eql(401)
36
- expect(jsonResponse['error']).to eql('Missing Authorization header')
47
+ it 'returns 401 status code' do
48
+ expect(last_response.status).to eq(401)
49
+ end
50
+
51
+ it 'returns an error message' do
52
+ expect(subject['error']).to eq('Invalid Authorization header format')
53
+ end
37
54
  end
38
55
 
39
- it 'returns 401 if the authorization header signature is invalid' do
40
- token = issuer.encode({ iss: 1 }, 'invalid secret')
41
- get('/', {}, {'HTTP_AUTHORIZATION' => 'Bearer #{token}'})
56
+ context 'when authorization header contains an invalid schema' do
57
+ let(:token) { issuer.encode({ iss: 1 }, secret) }
58
+ let(:headers) {{ 'HTTP_AUTHORIZATION' => "WrongScheme #{token}" }}
59
+
60
+ subject { JSON.parse(last_response.body) }
42
61
 
43
- jsonResponse = JSON.parse(last_response.body)
62
+ it 'returns 401 status code' do
63
+ expect(last_response.status).to eq(401)
64
+ end
44
65
 
45
- expect(last_response.status).to eql(401)
46
- expect(jsonResponse['error']).to eql('Invalid JWT token')
66
+ it 'returns an error message' do
67
+ expect(subject['error']).to eq('Invalid Authorization header format')
68
+ end
47
69
  end
48
70
 
49
- it 'returns 401 if the header format is not Authorization: Bearer [token]' do
50
- token = issuer.encode({ iss: 1 }, secret)
51
- get('/', {}, {'HTTP_AUTHORIZATION' => '#{token}'})
71
+ context 'when token signature is invalid' do
72
+ let(:token) { issuer.encode({ iss: 1 }, 'invalid secret') }
73
+ let(:headers) {{ 'HTTP_AUTHORIZATION' => "Bearer #{token}" }}
52
74
 
53
- jsonResponse = JSON.parse(last_response.body)
75
+ subject { JSON.parse(last_response.body) }
54
76
 
55
- expect(last_response.status).to eql(401)
56
- expect(jsonResponse['error']).to eql('Invalid Authorization header format')
77
+ it 'returns 401 status code' do
78
+ expect(last_response.status).to eq(401)
79
+ end
80
+
81
+ it 'returns an error message' do
82
+ expect(subject['error']).to eq('Invalid JWT token')
83
+ end
57
84
  end
58
85
 
59
- it 'returns 401 if authorization scheme is not Bearer' do
60
- token = issuer.encode({ iss: 1 }, secret)
61
- get('/', {}, {'HTTP_AUTHORIZATION' => 'WrongScheme #{token}'})
86
+ context 'when token is valid' do
87
+ let(:token) { issuer.encode({ iss: 1 }, secret) }
88
+ let(:headers) {{ 'HTTP_AUTHORIZATION' => "Bearer #{token}" }}
89
+
90
+ subject { JSON.parse(last_response.body) }
91
+
92
+ it 'returns 200 status code' do
93
+ expect(last_response.status).to eq(200)
94
+ end
95
+
96
+ it 'process the request' do
97
+ expect(subject).to eq(body)
98
+ end
62
99
 
63
- jsonResponse = JSON.parse(last_response.body)
100
+ it 'adds the token payload to the request' do
101
+ payload = last_response.header['jwt.payload']
102
+ expect(payload['iss']).to eq(1)
103
+ end
64
104
 
65
- expect(last_response.status).to eql(401)
66
- expect(jsonResponse['error']).to eql('Invalid Authorization header format')
105
+ it 'adds the token header to the request' do
106
+ header = last_response.header['jwt.header']
107
+ expect(header['alg']).to eq('HS256')
108
+ expect(header['typ']).to eq('JWT')
109
+ end
67
110
  end
68
111
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-jwt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mr. Eigenbart
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-06 00:00:00.000000000 Z
11
+ date: 2015-02-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: 10.0.0
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: 10.0.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rack-test
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -103,6 +103,7 @@ extra_rdoc_files: []
103
103
  files:
104
104
  - ".gitignore"
105
105
  - ".rspec"
106
+ - ".travis.yml"
106
107
  - Gemfile
107
108
  - LICENSE.txt
108
109
  - README.md
@@ -126,7 +127,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
126
127
  requirements:
127
128
  - - ">="
128
129
  - !ruby/object:Gem::Version
129
- version: '0'
130
+ version: 1.9.3
130
131
  required_rubygems_version: !ruby/object:Gem::Requirement
131
132
  requirements:
132
133
  - - ">="