toktok 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.editorconfig +3 -0
- data/Makefile +5 -0
- data/README.md +24 -12
- data/lib/toktok.rb +26 -3
- data/lib/toktok/configuration.rb +4 -2
- data/lib/toktok/token.rb +27 -6
- data/lib/toktok/version.rb +1 -1
- data/toktok.gemspec +2 -0
- metadata +31 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 36cfc1bad83de1c2e52e5d88aacb87736494dba2
|
4
|
+
data.tar.gz: b2c0cd4d24b8c645914bef1c330339f4e21b3de8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 165c1721d1a581d28eb3f85a3c07a75bb7e1cc812cc23a6a8f553340337d9bca66702b4ce153a591f44ca805a24c1cbd65d413a1ee508f3adf5e0d8c9cb3dd80
|
7
|
+
data.tar.gz: 77001d5cad59b16980ab0e7adab15272de0ca1e993e6049f45afa300c70e904c68491d3041064fc74b49db8a5ce01f720dedc5f18ca70fdf6c2f5cc6751a269d
|
data/.editorconfig
CHANGED
data/Makefile
ADDED
data/README.md
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
[](https://travis-ci.org/guzart/toktok)
|
4
4
|
[](https://codecov.io/gh/guzart/toktok)
|
5
5
|
[](https://codeclimate.com/github/guzart/toktok)
|
6
|
+
[](https://badge.fury.io/rb/toktok)
|
6
7
|
|
7
8
|
|
8
9
|
JWT Authentication for Ruby
|
@@ -30,38 +31,49 @@ TODO: Improve
|
|
30
31
|
**Configuration**
|
31
32
|
|
32
33
|
```ruby
|
34
|
+
# 'none' | 'HS256' | 'RS256' | 'ES256'
|
33
35
|
Toktok.algorithm = 'HS256'
|
34
|
-
|
36
|
+
|
37
|
+
# REQUIRED unless algorithm = 'none'
|
38
|
+
Toktok.secret_key = ENV['TOKTOK_SECRET_KEY']
|
39
|
+
|
40
|
+
# OPTIONAL – in seconds
|
41
|
+
Toktok.lifetime = nil
|
35
42
|
```
|
36
43
|
|
37
44
|
**Encode/Decode**
|
38
45
|
|
39
46
|
```ruby
|
40
|
-
token = Toktok::Token.new(identity: 'guzart')
|
47
|
+
token = Toktok::Token.new(identity: 'guzart', payload: { message: 'Hola' })
|
41
48
|
puts token.jwt # 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1...'
|
42
49
|
|
43
50
|
token = Toktok::Token.new(jwt: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1...')
|
44
51
|
puts token.identity # 'guzart'
|
45
|
-
puts token.payload # { sub: 'guzart' }
|
52
|
+
puts token.payload # { sub: 'guzart', message: 'Hola' }
|
46
53
|
```
|
47
54
|
|
48
|
-
##
|
49
|
-
|
50
|
-
TODO: list public api
|
55
|
+
## Claims
|
51
56
|
|
52
|
-
###
|
57
|
+
### Subject Claim
|
53
58
|
|
54
|
-
|
59
|
+
Toktok uses the required `identity` argument as the payload `sub` attribute defined
|
60
|
+
by the [JWT Subject Claim](https://tools.ietf.org/html/rfc7519#section-4.1.2).
|
55
61
|
|
56
|
-
|
62
|
+
### Expiration Time Claim
|
57
63
|
|
58
|
-
|
64
|
+
Toktok automatically calculates the token expiration using the `Toktok.lifetime` configuration
|
65
|
+
value and sets the `exp` attribute defined by the
|
66
|
+
[JWT Expiration Time Claim](https://tools.ietf.org/html/rfc7519#section-4.1.4)
|
59
67
|
|
60
68
|
## Development
|
61
69
|
|
62
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests.
|
70
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests.
|
71
|
+
You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
63
72
|
|
64
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version,
|
73
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version,
|
74
|
+
update the version number in `version.rb`, and then run `bundle exec rake release`, which will create
|
75
|
+
a git tag for the version, push git commits and tags, and push the `.gem` file to
|
76
|
+
[rubygems.org](https://rubygems.org).
|
65
77
|
|
66
78
|
## Contributing
|
67
79
|
|
data/lib/toktok.rb
CHANGED
@@ -1,21 +1,44 @@
|
|
1
|
-
require 'toktok/version'
|
2
|
-
require 'jwt'
|
3
|
-
|
4
1
|
module Toktok
|
5
2
|
require 'toktok/configuration'
|
6
3
|
require 'toktok/token'
|
4
|
+
require 'toktok/version'
|
7
5
|
|
6
|
+
# Set the algorithm used to encode and decode JWT tokens (default: HS256)
|
7
|
+
#
|
8
|
+
# Acceptable values are:
|
9
|
+
# * none
|
10
|
+
# * HS256, HS384, HS512
|
11
|
+
# * RS256, RS384, RS512
|
12
|
+
# * ES256, ES384, ES512
|
13
|
+
#
|
14
|
+
# @param [String] value the algorithm name
|
15
|
+
# @return [String] the algorithm
|
8
16
|
def self.algorithm=(value)
|
9
17
|
@algorithm = value
|
10
18
|
end
|
11
19
|
|
20
|
+
# Set the lifetime in seconds before a token expires (default: nil)
|
21
|
+
#
|
22
|
+
# @param [Integer, nil] value the number of seconds before a token expires
|
23
|
+
# @return [Integer, nil] the lifetime
|
24
|
+
def self.lifetime=(value)
|
25
|
+
@lifetime = value
|
26
|
+
end
|
27
|
+
|
28
|
+
# Set the secret key that will be used to encode and decode JWT tokens
|
29
|
+
# @param [String] value the secret key
|
30
|
+
# @return [String] the secret key
|
12
31
|
def self.secret_key=(value)
|
13
32
|
@secret_key = value
|
14
33
|
end
|
15
34
|
|
35
|
+
# Gets a Toktok::Configuration instance using the module values.
|
36
|
+
#
|
37
|
+
# @return [Toktok::Configuration] the configuration
|
16
38
|
def self.config
|
17
39
|
::Toktok::Configuration.new(
|
18
40
|
algorithm: @algorithm,
|
41
|
+
lifetime: @lifetime,
|
19
42
|
secret_key: @secret_key
|
20
43
|
)
|
21
44
|
end
|
data/lib/toktok/configuration.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
module Toktok
|
2
2
|
class Configuration
|
3
|
-
attr_reader :algorithm, :secret_key
|
3
|
+
attr_reader :algorithm, :lifetime, :secret_key
|
4
4
|
|
5
|
+
# Error raised when an algorithm is given but the secret_key is missing.
|
5
6
|
SecretKeyMissingError = Class.new(StandardError)
|
6
7
|
|
7
|
-
def initialize(algorithm: nil, secret_key: nil)
|
8
|
+
def initialize(algorithm: nil, lifetime: nil, secret_key: nil)
|
8
9
|
@algorithm = algorithm || 'HS256'
|
10
|
+
@lifetime = lifetime
|
9
11
|
@secret_key = secret_key
|
10
12
|
|
11
13
|
if algorithm != 'none' && (secret_key || '') == ''
|
data/lib/toktok/token.rb
CHANGED
@@ -1,27 +1,31 @@
|
|
1
|
+
require 'jwt'
|
2
|
+
|
1
3
|
module Toktok
|
2
4
|
InvalidIdentity = Class.new(StandardError)
|
5
|
+
InvalidSignature = Class.new(StandardError)
|
3
6
|
|
4
7
|
class Token
|
5
8
|
attr_reader :config, :jwt, :payload
|
6
9
|
|
7
|
-
def initialize(identity: nil, jwt: nil)
|
10
|
+
def initialize(identity: nil, jwt: nil, payload: nil)
|
8
11
|
@config = Toktok.config
|
9
12
|
@payload = {}
|
10
13
|
if jwt
|
11
14
|
initialize_decode(jwt, identity)
|
12
15
|
else
|
13
|
-
initialize_encode(identity)
|
16
|
+
initialize_encode(identity, payload)
|
14
17
|
end
|
15
18
|
end
|
16
19
|
|
17
20
|
def identity
|
18
|
-
payload[
|
21
|
+
payload[:sub]
|
19
22
|
end
|
20
23
|
|
21
24
|
private
|
22
25
|
|
23
|
-
def initialize_encode(identity)
|
24
|
-
|
26
|
+
def initialize_encode(identity, extra)
|
27
|
+
prepare_payload(identity, extra)
|
28
|
+
normalize_payload
|
25
29
|
@jwt = JWT.encode(payload, config.secret_key, config.algorithm)
|
26
30
|
end
|
27
31
|
|
@@ -29,10 +33,12 @@ module Toktok
|
|
29
33
|
@jwt = jwt
|
30
34
|
options = decode_options(identity)
|
31
35
|
decoded_token = JWT.decode(jwt, config.secret_key, algorithm?, options)
|
32
|
-
@payload = decoded_token[0]
|
36
|
+
@payload = symbolize_keys(decoded_token[0])
|
33
37
|
@header = decoded_token[1]
|
34
38
|
rescue JWT::InvalidSubError
|
35
39
|
raise InvalidIdentity, "Invalid identity. Expected #{identity}"
|
40
|
+
rescue JWT::VerificationError
|
41
|
+
raise InvalidSignature, 'Invalid or manipulated signature'
|
36
42
|
end
|
37
43
|
|
38
44
|
def decode_options(identity)
|
@@ -44,5 +50,20 @@ module Toktok
|
|
44
50
|
def algorithm?
|
45
51
|
config.algorithm != 'none'
|
46
52
|
end
|
53
|
+
|
54
|
+
def prepare_payload(identity, extra = nil)
|
55
|
+
@payload.merge!(symbolize_keys(extra)) if extra
|
56
|
+
@payload[:sub] = identity
|
57
|
+
@payload[:exp] = Time.now.to_i + config.lifetime if config.lifetime.to_i > 0
|
58
|
+
end
|
59
|
+
|
60
|
+
# Guarantee the order in which the keys are inserted
|
61
|
+
def normalize_payload
|
62
|
+
@payload = Hash[payload.keys.sort.map { |k| [k, payload[k]] }]
|
63
|
+
end
|
64
|
+
|
65
|
+
def symbolize_keys(hash)
|
66
|
+
Hash[hash.map { |k, v| [k.to_sym, v] }]
|
67
|
+
end
|
47
68
|
end
|
48
69
|
end
|
data/lib/toktok/version.rb
CHANGED
data/toktok.gemspec
CHANGED
@@ -34,4 +34,6 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.add_development_dependency 'rake', '~> 10.0'
|
35
35
|
spec.add_development_dependency 'reek', '~> 4.5'
|
36
36
|
spec.add_development_dependency 'rspec', '~> 3.5'
|
37
|
+
spec.add_development_dependency 'timecop', '~> 0.8'
|
38
|
+
spec.add_development_dependency 'yard', '~> 0.9'
|
37
39
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: toktok
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arturo Guzman
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-03-
|
11
|
+
date: 2017-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jwt
|
@@ -136,6 +136,34 @@ dependencies:
|
|
136
136
|
- - "~>"
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '3.5'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: timecop
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0.8'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0.8'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: yard
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0.9'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0.9'
|
139
167
|
description: |
|
140
168
|
Simplify JWT token encoding and decoding for Ruby. Use a configuration initializer to standardize the use
|
141
169
|
of JWT encoding/decoding accross your library. Simplifies the use of JWT Claims.
|
@@ -154,6 +182,7 @@ files:
|
|
154
182
|
- Gemfile
|
155
183
|
- Guardfile
|
156
184
|
- LICENSE.txt
|
185
|
+
- Makefile
|
157
186
|
- README.md
|
158
187
|
- Rakefile
|
159
188
|
- bin/console
|