henlo 0.1.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 +7 -0
- data/Rakefile +15 -0
- data/lib/generators/henlo/install_generator.rb +17 -0
- data/lib/generators/henlo/migrations_generator.rb +33 -0
- data/lib/generators/templates/henlo_initializer.rb +23 -0
- data/lib/generators/templates/migrations/add_jti_column.rb +16 -0
- data/lib/generators/templates/migrations/create_blacklisted_tokens.rb.erb +21 -0
- data/lib/henlo.rb +46 -0
- data/lib/henlo/authenticable.rb +90 -0
- data/lib/henlo/helpers/util.rb +17 -0
- data/lib/henlo/identifiable.rb +26 -0
- data/lib/henlo/refreshable.rb +33 -0
- data/lib/henlo/revocable.rb +28 -0
- data/lib/henlo/version.rb +3 -0
- metadata +156 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 51d705728f88bb4c77b243d887d05f729d2a2019
|
4
|
+
data.tar.gz: 968ea1f50cecc17d754fe04617e117a02e6d9c88
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e30c6ffaf47154ffe110b3218d7a4ad7f972ddc1a4d5b6b27940342cd23dd7a98d0bc8ae96fa6a1476d0c215ecbd149a0588662609e4bd41715f4a27de96b6d4
|
7
|
+
data.tar.gz: 19986364a62c80e02052f7cdbbbc98043a54ba37351afff6d616275cfa69d53fb05641c92226db268f1bc513527c559466236123d7079d940cccaa41a4aa9dc5
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'bundler/setup'
|
5
|
+
rescue LoadError
|
6
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
7
|
+
end
|
8
|
+
|
9
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
10
|
+
load 'rails/tasks/engine.rake'
|
11
|
+
|
12
|
+
|
13
|
+
Bundler::GemHelper.install_tasks
|
14
|
+
|
15
|
+
task default: :test
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
|
3
|
+
module Henlo
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path("../../templates", __FILE__)
|
7
|
+
desc "Installs Henlo."
|
8
|
+
|
9
|
+
def copy_initializer
|
10
|
+
template "henlo_initializer.rb", "config/initializers/henlo.rb"
|
11
|
+
|
12
|
+
puts "Installation complete."
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rails/generators/active_record'
|
2
|
+
|
3
|
+
module Henlo
|
4
|
+
module Generators
|
5
|
+
class MigrationsGenerator < ActiveRecord::Generators::Base
|
6
|
+
source_root File.expand_path("../../templates", __FILE__)
|
7
|
+
desc "Generates the necessary migration for the model"
|
8
|
+
argument :table_name, type: :string, default: "User"
|
9
|
+
|
10
|
+
|
11
|
+
def create_migrations
|
12
|
+
puts "Generating migrations for model #{table_name}.downcase"
|
13
|
+
migration_template "migrations/add_jti_column.rb", "db/migrate/add_jti_column_to_#{table_name.downcase.pluralize}.rb"
|
14
|
+
migration_template 'migrations/create_blacklisted_tokens.rb.erb', 'db/migrate/create_blacklisted_tokens.rb'
|
15
|
+
end
|
16
|
+
|
17
|
+
def migration_data
|
18
|
+
<<RUBY
|
19
|
+
t.string :refresh_token_jti
|
20
|
+
t.boolean :blacklist_check, default: false
|
21
|
+
RUBY
|
22
|
+
end
|
23
|
+
|
24
|
+
def migration_index_data
|
25
|
+
<<RUBY
|
26
|
+
add_index "#{table_name.downcase.pluralize.to_sym}", :blacklist_check
|
27
|
+
add_index "#{table_name.downcase.pluralize.to_sym}", :refresh_token_jti
|
28
|
+
RUBY
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
Henlo.setup do |config|
|
2
|
+
|
3
|
+
## All expiration claims use seconds as unit
|
4
|
+
|
5
|
+
## Refresh token expiration claim
|
6
|
+
## ----------------
|
7
|
+
##
|
8
|
+
## How long before a refresh token is expired. If nil is provided, token will
|
9
|
+
## last forever.
|
10
|
+
##
|
11
|
+
## Default is 15 days
|
12
|
+
# config.refresh_token_lifetime = 15 * 86400
|
13
|
+
|
14
|
+
## Id token expiration claim
|
15
|
+
## ----------------
|
16
|
+
##
|
17
|
+
## How long before an id token is expired. If nil is provided, token will
|
18
|
+
## last forever.
|
19
|
+
## This value is provided in seconds
|
20
|
+
## Default is 15 minutes
|
21
|
+
# config.id_token_lifetime = 60 * 15
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<%
|
2
|
+
parent_class = ActiveRecord::Migration
|
3
|
+
parent_class = parent_class[parent_class.current_version] if Rails::VERSION::MAJOR >= 5
|
4
|
+
-%>
|
5
|
+
class AddJtiColumnTo<%= table_name.camelize %>s < <%= parent_class.to_s %>
|
6
|
+
def self.up
|
7
|
+
change_table(:<%= table_name.downcase.pluralize %>) do |t|
|
8
|
+
<%= migration_data %>
|
9
|
+
end
|
10
|
+
<%= migration_index_data%>
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
raise ActiveRecord::IrreversibleMigration
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<%
|
2
|
+
parent_class = ActiveRecord::Migration
|
3
|
+
parent_class = parent_class[parent_class.current_version] if Rails::VERSION::MAJOR >= 5
|
4
|
+
-%>
|
5
|
+
class CreateBlacklistedTokens < <%= parent_class.to_s %>
|
6
|
+
def self.up
|
7
|
+
create_table :blacklisted_tokens do |t|
|
8
|
+
t.string :token_jti
|
9
|
+
<%- if Rails::VERSION::MAJOR >= 5 -%>
|
10
|
+
t.integer :exp_in_unix
|
11
|
+
t.timestamps
|
12
|
+
<%- else -%>
|
13
|
+
t.timestamps null: false
|
14
|
+
<%- end -%>
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.down
|
19
|
+
drop_table :blacklisted_tokens
|
20
|
+
end
|
21
|
+
end
|
data/lib/henlo.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require "henlo/version"
|
2
|
+
require "henlo/refreshable"
|
3
|
+
require "henlo/identifiable"
|
4
|
+
require "henlo/authenticable"
|
5
|
+
require "henlo/revocable"
|
6
|
+
require "knock"
|
7
|
+
|
8
|
+
#
|
9
|
+
## Defines default initializing values and main method for generating tokens
|
10
|
+
module Henlo
|
11
|
+
|
12
|
+
#
|
13
|
+
## Generates refresh and access tokens when method is called, allows the passing in of
|
14
|
+
## additional key value pairs to be encoded in the jwt payload
|
15
|
+
## Returns the jwt identifier of the refresh token, as well as the expiry time in unix
|
16
|
+
## seconds of the id token.
|
17
|
+
def self.generate_henlos(options={})
|
18
|
+
claim = options || nil
|
19
|
+
refresh_token_and_jti = Refreshable.generate_refreshable(options)
|
20
|
+
id_token_and_exp = Identifiable.generate_identifiable(options)
|
21
|
+
tokens = Hash[
|
22
|
+
id_token: id_token_and_exp[:token],
|
23
|
+
refresh_token: refresh_token_and_jti[:token]
|
24
|
+
]
|
25
|
+
henlos = Hash[
|
26
|
+
tokens: tokens,
|
27
|
+
jti: refresh_token_and_jti[:jti],
|
28
|
+
exp: id_token_and_exp[:exp]
|
29
|
+
]
|
30
|
+
end
|
31
|
+
|
32
|
+
mattr_accessor :refresh_token_lifetime
|
33
|
+
self.refresh_token_lifetime = 15 * 86400
|
34
|
+
|
35
|
+
mattr_accessor :id_token_lifetime
|
36
|
+
self.id_token_lifetime = 60 * 15
|
37
|
+
|
38
|
+
# Default way to setup Henlo. Run `rails generate henlo:install` to create
|
39
|
+
## a fresh initializer with all configuration values.
|
40
|
+
def self.setup
|
41
|
+
yield self
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
end
|
46
|
+
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require "henlo/helpers/util"
|
2
|
+
require 'active_record/errors'
|
3
|
+
#
|
4
|
+
## Module
|
5
|
+
module Henlo::Authenticable
|
6
|
+
|
7
|
+
#
|
8
|
+
## Retrieve the token type from the jwt payload
|
9
|
+
def self.parse_token_type(token, options={})
|
10
|
+
claim = Knock::AuthToken.new(token: token, verify_options: options).payload
|
11
|
+
claim["type"]
|
12
|
+
end
|
13
|
+
|
14
|
+
#
|
15
|
+
## Match the token jwt identifier with what is stored in the database for the resource,
|
16
|
+
## a lack of match indicates suspicious activities
|
17
|
+
def self.jti_match?(payload, resource)
|
18
|
+
payload["jti"] === resource.refresh_token_jti
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
## Check the resource to see if it has been flagged for blacklist check
|
23
|
+
def self.it_suspicious?(resource)
|
24
|
+
resource.blacklist_check?
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
## Check the blacklisted tokens table to see whether the token's jwt identifier has been
|
29
|
+
## blacklisted
|
30
|
+
def self.it_not_fren?(resource)
|
31
|
+
BlacklistedToken.where(token_jti: resource.refresh_token_jti).first
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
## Parse the resource as identified by the id encoded in the jwt with the key "sub"
|
36
|
+
def self.parse_resource(payload, model)
|
37
|
+
resource = model.capitalize.constantize.where(id: payload["sub"]).first
|
38
|
+
if resource.nil?
|
39
|
+
raise ActiveRecord::RecordNotFound
|
40
|
+
end
|
41
|
+
resource
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
## Authenticates resource by first determining the treatment based on the type of token.
|
46
|
+
## Requests with valid id tokens will be processed.
|
47
|
+
## Requests with refresh tokens will be checked for 1) whether the resource has been flagged
|
48
|
+
## for blacklist check and if yes, 2) whether the token's jwt identifier has been flaglisted.
|
49
|
+
## If neither 1) nor 2) is established, the token will be checked for a match of the jwt identifier
|
50
|
+
## The resource is returned if all these checks are passed.
|
51
|
+
def self.it_me?(token, model)
|
52
|
+
type = parse_token_type(token)
|
53
|
+
payload = Knock::AuthToken.new(token: token).payload
|
54
|
+
resource = parse_resource(payload, model)
|
55
|
+
case type
|
56
|
+
when "id"
|
57
|
+
resource
|
58
|
+
when "refresh"
|
59
|
+
if it_suspicious?(resource) && it_not_fren?(resource)
|
60
|
+
nil
|
61
|
+
else
|
62
|
+
if jti_match?(payload, resource)
|
63
|
+
resource
|
64
|
+
else
|
65
|
+
Henlo::Revocable.token_blockt(payload, resource)
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
else
|
70
|
+
nil
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
## This method is to be called before `it_me?` is called, so that expired tokens are treated before
|
76
|
+
## the authentication begins. Requests made with expired id tokens are rejected with an error.
|
77
|
+
## Requests made with expired refresh tokens are then processed with "reauthentication_strategy.
|
78
|
+
## This method is passed as an argument to `it_expired` by the app. You can define how
|
79
|
+
## users are reauthenticated in your own app.
|
80
|
+
def self.it_expired(reauthenticate_strategy, token, model)
|
81
|
+
token = Knock::AuthToken.new(token: token, verify_options: {verify_expiration: false}).token
|
82
|
+
claim = Knock::AuthToken.new(token: token, verify_options: {verify_expiration: false}).payload
|
83
|
+
resource = parse_resource(claim, model)
|
84
|
+
if claim["type"] == "id"
|
85
|
+
raise ActionController::InvalidAuthenticityToken
|
86
|
+
else
|
87
|
+
reauthenticate_strategy
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
## Helper methods
|
4
|
+
module Henlo
|
5
|
+
module Helpers
|
6
|
+
module Util
|
7
|
+
|
8
|
+
#
|
9
|
+
## Generates a random string in the format of "a5391f26-1136-46f3-a3d3-ea4e1e558f06"
|
10
|
+
## to use as a unique jwt identifier.
|
11
|
+
def self.generate_jti
|
12
|
+
SecureRandom.uuid
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "henlo/helpers/util"
|
2
|
+
|
3
|
+
#
|
4
|
+
## Generates id token. The id token is used to identify and authenticate the user before
|
5
|
+
## responding to a request
|
6
|
+
module Henlo::Identifiable
|
7
|
+
|
8
|
+
# Generates id token and returns both the token, with the optional payload encoded, and the
|
9
|
+
## token expiry time in unix seconds
|
10
|
+
def self.generate_identifiable(options={})
|
11
|
+
claim = options || nil
|
12
|
+
|
13
|
+
claim.merge!({
|
14
|
+
exp: Time.now.utc.to_i + Henlo.id_token_lifetime,
|
15
|
+
jti: Henlo::Helpers::Util.generate_jti,
|
16
|
+
type: "id"
|
17
|
+
})
|
18
|
+
|
19
|
+
Hash[
|
20
|
+
token: Knock::AuthToken.new(payload: claim).token,
|
21
|
+
exp: claim[:exp]
|
22
|
+
]
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "henlo/helpers/util"
|
2
|
+
|
3
|
+
#
|
4
|
+
## Module for generating refresh tokens
|
5
|
+
|
6
|
+
module Henlo::Refreshable
|
7
|
+
|
8
|
+
#
|
9
|
+
## Generate refreshable token with a unix time for expiry, the type of token
|
10
|
+
## and the jwt identifier (a random string) encoded in the payload in addition to
|
11
|
+
## whatever was passed as payload when `generate_henlos` was called
|
12
|
+
def self.generate_refreshable(options={})
|
13
|
+
claim = options || nil
|
14
|
+
|
15
|
+
claim.merge!({
|
16
|
+
exp: Time.now.utc.to_i + Henlo.refresh_token_lifetime,
|
17
|
+
jti: Henlo::Helpers::Util.generate_jti,
|
18
|
+
type: "refresh"
|
19
|
+
})
|
20
|
+
|
21
|
+
Hash[
|
22
|
+
token: Knock::AuthToken.new(payload: claim).token,
|
23
|
+
jti: claim[:jti]
|
24
|
+
]
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
## Store jwt identifier in the app's database, in the table of the resource
|
29
|
+
def self.store_jti(resource, jti)
|
30
|
+
resource.update_attribute(:refresh_token_jti, jti)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#
|
2
|
+
## Module allows the blacklist of tokens as identified by the jti (jwt identifier)
|
3
|
+
## Blacklisted refresh tokens cannot be used to generate new id tokens
|
4
|
+
module Henlo::Revocable
|
5
|
+
|
6
|
+
#
|
7
|
+
## Method called when the identifier as encoded in the token payload does not match what was stored in the database
|
8
|
+
## or when the revoke token route is called by the user in cases of breach such as device loss
|
9
|
+
## the token is blacklisted and the resource is flagged as needing blacklist checks
|
10
|
+
def self.token_blockt(payload, resource)
|
11
|
+
resource.blacklist_check == true
|
12
|
+
resource.save!
|
13
|
+
|
14
|
+
blacklisted_token = BlacklistedToken.create(
|
15
|
+
token_jti: payload["jti"],
|
16
|
+
exp_in_unix: payload["exp"]
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
## Call this period in a scheduled task to clean expired tokens from the database
|
22
|
+
def self.token_rekt
|
23
|
+
BlacklistedToken.each do |token|
|
24
|
+
token.destroy unless Time.now.utc < token.exp_in_unix
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: henlo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- nombiezinja
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-01-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: jwt
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.5'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.5'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: knock
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.1.1
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.1.1
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.15'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.15'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rdoc
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: Based on the Knock gem, offers options to further customize secure authentication
|
112
|
+
practices
|
113
|
+
email:
|
114
|
+
- tianyizhang1987@gmail.com
|
115
|
+
executables: []
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- Rakefile
|
120
|
+
- lib/generators/henlo/install_generator.rb
|
121
|
+
- lib/generators/henlo/migrations_generator.rb
|
122
|
+
- lib/generators/templates/henlo_initializer.rb
|
123
|
+
- lib/generators/templates/migrations/add_jti_column.rb
|
124
|
+
- lib/generators/templates/migrations/create_blacklisted_tokens.rb.erb
|
125
|
+
- lib/henlo.rb
|
126
|
+
- lib/henlo/authenticable.rb
|
127
|
+
- lib/henlo/helpers/util.rb
|
128
|
+
- lib/henlo/identifiable.rb
|
129
|
+
- lib/henlo/refreshable.rb
|
130
|
+
- lib/henlo/revocable.rb
|
131
|
+
- lib/henlo/version.rb
|
132
|
+
homepage: https://github.com/nombiezinja/henlo
|
133
|
+
licenses:
|
134
|
+
- MIT
|
135
|
+
metadata: {}
|
136
|
+
post_install_message:
|
137
|
+
rdoc_options: []
|
138
|
+
require_paths:
|
139
|
+
- lib
|
140
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - ">="
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
requirements: []
|
151
|
+
rubyforge_project:
|
152
|
+
rubygems_version: 2.4.0
|
153
|
+
signing_key:
|
154
|
+
specification_version: 4
|
155
|
+
summary: JWT based authentication with access and id tokens
|
156
|
+
test_files: []
|