auth0_rs256_jwt_verifier 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +9 -0
- data/Gemfile +1 -2
- data/README.md +39 -1
- data/auth0_rs256_jwt_verifier.gemspec +26 -20
- data/gemfiles/json-jwt-1.10.gemfile +7 -0
- data/gemfiles/json-jwt-1.7.gemfile +7 -0
- data/lib/auth0_rs256_jwt_verifier/certs_set.rb +2 -0
- data/lib/auth0_rs256_jwt_verifier/exp_verifier.rb +2 -0
- data/lib/auth0_rs256_jwt_verifier/jwk.rb +11 -10
- data/lib/auth0_rs256_jwt_verifier/jwk_set_downloader.rb +15 -14
- data/lib/auth0_rs256_jwt_verifier/jwt_decoder.rb +1 -0
- data/lib/auth0_rs256_jwt_verifier/results.rb +1 -1
- data/lib/auth0_rs256_jwt_verifier/valid_jwk_set.rb +1 -0
- data/test/auth0_rs256_jwt_verifier/exp_verifier_test.rb +19 -0
- data/test/auth0_rs256_jwt_verifier/jwt_decoder_test.rb +1 -1
- data/test/auth0_rs256_jwt_verifier_test.rb +6 -6
- metadata +12 -10
- data/lib/auth0_access_tokens_rs256_verifier.rb +0 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3fb88a4efe73c0b27347ec0cd00883c67b078562795459506eac11c292347fde
|
4
|
+
data.tar.gz: 2419bc74be68cb430969eda6ce87fcfe2049b47b28827fecf03963846533dbc6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 22bb8c0f7f6da4538174141894cf620d037e770b4154c058900d3ed49069f30e053f168fa1cf722830150f252b1a711d2734691b27822290735ca90acce5644e
|
7
|
+
data.tar.gz: f41860a5f7c5ec048fa2c27459183d75abbafe489be8818a6efbfbc476d8c894f8ab0e2814a63f5df6c0b7432e6f057ffb94bf0aab9ea741a7c70cd2ae16e692
|
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,44 @@
|
|
1
|
-
|
1
|
+
[![Build Status](https://travis-ci.org/DroidsOnRoids/auth0_rs256_jwt_verifier.svg?branch=master)](https://travis-ci.org/DroidsOnRoids/auth0_rs256_jwt_verifier)
|
2
|
+
|
3
|
+
# Auth0 JWT (RS256) verification library
|
2
4
|
[Auth0](https://auth0.com) is web service handling users identities which can be easily plugged
|
3
5
|
into your application. It provides [SDKs](https://auth0.com/docs) for many languages which enable you to sign up/in users
|
4
6
|
and returns access token ([JWT](https://jwt.io)) in exchange. Access token can be used then to access your's Web Service.
|
5
7
|
This gem helps you to [verify](https://auth0.com/docs/api-auth/tutorials/verify-access-token#verify-the-signature)
|
6
8
|
such access token which has been signed using the RS256 algorithm.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
Install the `auth0_rs256_jwt_verifier` package from [Rubygems](https://rubygems.org/gems/auth0_rs256_jwt_verifier):
|
12
|
+
|
13
|
+
```bash
|
14
|
+
gem install auth0_rs256_jwt_verifier
|
15
|
+
```
|
16
|
+
|
17
|
+
Install it using [Bundler](https://bundler.io/) specifying it as dependency in your Gemfile:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
gem "auth0_rs256_jwt_verifier"
|
21
|
+
```
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
# Verifier caches RS256 certificates fetched from jwks_uri.
|
27
|
+
# You should initialize it once and reuse for JWTs verification.
|
28
|
+
|
29
|
+
require "auth0_rs256_jwt_verifier"
|
30
|
+
|
31
|
+
AUTH0_JWT_VERIFIER = Auth0RS256JWTVerifier.new(
|
32
|
+
issuer: "ISSUER",
|
33
|
+
audience: "AUDIENCE",
|
34
|
+
jwks_url: "https://YOUR_AUTH0_DOMAIN/.well-known/jwks.json"
|
35
|
+
)
|
36
|
+
|
37
|
+
result = AUTH0_JWT_VERIFIER.verify("JWT_ACCESS_TOKEN_SIGNED_USING_RS256_ALGORITHM").valid?
|
38
|
+
if result.valid?
|
39
|
+
p "Token is valid"
|
40
|
+
p "User id: #{result.user_id}"
|
41
|
+
else
|
42
|
+
p "Token is invalid"
|
43
|
+
end
|
44
|
+
```
|
@@ -1,25 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
Gem::Specification.new do |s|
|
3
|
-
s.name
|
4
|
-
s.version
|
5
|
-
s.date
|
6
|
-
s.summary
|
7
|
-
s.description
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
s.authors
|
16
|
-
s.email
|
17
|
-
s.
|
18
|
-
s.
|
19
|
-
|
20
|
-
s.
|
21
|
-
s.
|
22
|
-
s.
|
3
|
+
s.name = "auth0_rs256_jwt_verifier"
|
4
|
+
s.version = "0.0.2"
|
5
|
+
s.date = "2017-06-12"
|
6
|
+
s.summary = "Auth0 JWT (RS256) verification library"
|
7
|
+
s.description = <<-DESCRIPTION.gsub(/\s+/, " ").strip
|
8
|
+
Auth0 (https://auth0.com) is web service handling users identities which can be easily plugged
|
9
|
+
into your application. It provides SDKs for many languages which enable you to sign up/in users
|
10
|
+
and returns access token (JWT) in exchange. Access token can be used then to access your's Web Service.
|
11
|
+
This gem helps you to verify
|
12
|
+
(https://auth0.com/docs/api-auth/tutorials/verify-access-token#verify-the-signature)
|
13
|
+
such access token which has been signed using the RS256 algorithm.
|
14
|
+
DESCRIPTION
|
15
|
+
s.authors = ["Krzysztof Zielonka"]
|
16
|
+
s.email = "krzysztof.zielonka@droidsonroids.pl"
|
17
|
+
s.license = "MIT"
|
18
|
+
s.homepage = "https://github.com/DroidsOnRoids/auth0_rs256_jwt_verifier"
|
19
|
+
|
20
|
+
s.files = `git ls-files`.split("\n")
|
21
|
+
s.test_files = `git ls-files -- {test}/*`.split("\n")
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
|
24
|
+
s.required_ruby_version = ">= 2.2.0"
|
25
|
+
|
26
|
+
s.add_runtime_dependency "http", ">= 2"
|
27
|
+
s.add_runtime_dependency "json-jwt", ">= 1.7"
|
28
|
+
|
23
29
|
s.add_development_dependency "rake", "~> 12"
|
24
30
|
s.add_development_dependency "minitest", "~> 5"
|
25
31
|
end
|
@@ -9,6 +9,7 @@ class Auth0RS256JWTVerifier
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def find(id)
|
12
|
+
id = String(id)
|
12
13
|
cert = certs.find { |c| c.id == id }
|
13
14
|
raise NotFoundError, "cert #{id} doesn't exist" if cert.nil?
|
14
15
|
cert.cert
|
@@ -28,4 +29,5 @@ class Auth0RS256JWTVerifier
|
|
28
29
|
OpenSSL::X509::Certificate.new(encoded)
|
29
30
|
end
|
30
31
|
end
|
32
|
+
private_constant :CertsSet
|
31
33
|
end
|
@@ -3,6 +3,16 @@ class Auth0RS256JWTVerifier
|
|
3
3
|
class JWK
|
4
4
|
ParseError = Class.new(RuntimeError)
|
5
5
|
|
6
|
+
def initialize(hash)
|
7
|
+
raise ParseError unless hash.is_a?(Hash)
|
8
|
+
%i(Alg Kty Use X5C N E Kid X5T).each do |field_name|
|
9
|
+
field = self.class.const_get(field_name).new(hash[String(field_name).downcase])
|
10
|
+
instance_variable_set("@#{String(field_name).downcase}", field)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :alg, :kty, :use, :x5c, :n, :e, :kid, :x5t
|
15
|
+
|
6
16
|
def inspect
|
7
17
|
"JWK(\n" \
|
8
18
|
"\talg: #{@alg},\n" \
|
@@ -124,15 +134,6 @@ class Auth0RS256JWTVerifier
|
|
124
134
|
@certificates.each { |cert| yield cert }
|
125
135
|
end
|
126
136
|
end
|
127
|
-
|
128
|
-
def initialize(hash)
|
129
|
-
raise ParseError unless hash.is_a?(Hash)
|
130
|
-
%i(Alg Kty Use X5C N E Kid X5T).each do |field_name|
|
131
|
-
field = self.class.const_get(field_name).new(hash[String(field_name).downcase])
|
132
|
-
instance_variable_set("@#{String(field_name).downcase}", field)
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
attr_reader :alg, :kty, :use, :x5c, :n, :e, :kid, :x5t
|
137
137
|
end
|
138
|
+
private_constant :JWK
|
138
139
|
end
|
@@ -3,6 +3,21 @@ class Auth0RS256JWTVerifier
|
|
3
3
|
class JWKSetDownloader
|
4
4
|
InvalidJWKSetError = Class.new(RuntimeError)
|
5
5
|
|
6
|
+
def initialize(http)
|
7
|
+
@http = http
|
8
|
+
end
|
9
|
+
|
10
|
+
def download(url)
|
11
|
+
url = String(url)
|
12
|
+
body = @http.get(url)
|
13
|
+
json = JSON.parse(body)
|
14
|
+
begin
|
15
|
+
JWKSet.new(json)
|
16
|
+
rescue JWKSet::ParseError
|
17
|
+
raise InvalidJWKSetError
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
6
21
|
class JWKSet
|
7
22
|
include Enumerable
|
8
23
|
|
@@ -22,20 +37,6 @@ class Auth0RS256JWTVerifier
|
|
22
37
|
end
|
23
38
|
end
|
24
39
|
private_constant :JWKSet
|
25
|
-
|
26
|
-
def initialize(http)
|
27
|
-
@http = http
|
28
|
-
end
|
29
|
-
|
30
|
-
def download(url)
|
31
|
-
body = @http.get(url)
|
32
|
-
json = JSON.parse(body)
|
33
|
-
begin
|
34
|
-
JWKSet.new(json)
|
35
|
-
rescue JWKSet::ParseError
|
36
|
-
raise InvalidJWKSetError
|
37
|
-
end
|
38
|
-
end
|
39
40
|
end
|
40
41
|
private_constant :JWKSetDownloader
|
41
42
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "test_helper"
|
3
|
+
|
4
|
+
class Auth0RS256JWTVerifier
|
5
|
+
describe ExpVerifier do
|
6
|
+
before :each do
|
7
|
+
@verificator = ExpVerifier.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it "classifies value 0 as expired time" do
|
11
|
+
assert @verificator.expired?(0)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "classifies future time as not expired" do
|
15
|
+
one_hour_from_now = (Time.now + 3600).to_i
|
16
|
+
refute @verificator.expired?(one_hour_from_now)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -7,7 +7,7 @@ class Auth0RS256JWTVerifier
|
|
7
7
|
@decoder = JWTDecoder.new
|
8
8
|
end
|
9
9
|
|
10
|
-
it "should
|
10
|
+
it "should decode simple jwt" do
|
11
11
|
jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImlkMTIzNCJ9." \
|
12
12
|
"eyJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjoiYXVkaWVuY2UiLCJpc3MiO" \
|
13
13
|
"iJpc3N1ZXIifQ.cp374RbcG-q8rTLxSoWtLK7dtn5cBa3_g4riKL9OSt0"
|
@@ -101,16 +101,16 @@ describe Auth0RS256JWTVerifier do
|
|
101
101
|
private
|
102
102
|
|
103
103
|
def http_stub
|
104
|
-
|
104
|
+
http_stub = Object.new
|
105
105
|
jwks = sample_jwks
|
106
|
-
|
107
|
-
|
106
|
+
http_stub.define_singleton_method(:get) { |*_| jwks }
|
107
|
+
http_stub
|
108
108
|
end
|
109
109
|
|
110
110
|
def exp_verifier_stub(expired: false)
|
111
|
-
|
112
|
-
|
113
|
-
|
111
|
+
exp_verifier_stub = Object.new
|
112
|
+
exp_verifier_stub.define_singleton_method(:expired?) { |*_| expired }
|
113
|
+
exp_verifier_stub
|
114
114
|
end
|
115
115
|
|
116
116
|
def sample_jwks
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: auth0_rs256_jwt_verifier
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Krzysztof Zielonka
|
@@ -14,28 +14,28 @@ dependencies:
|
|
14
14
|
name: http
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: json-jwt
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '1.7'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.7'
|
41
41
|
- !ruby/object:Gem::Dependency
|
@@ -79,11 +79,13 @@ extra_rdoc_files: []
|
|
79
79
|
files:
|
80
80
|
- ".gitignore"
|
81
81
|
- ".rubocop.yml"
|
82
|
+
- ".travis.yml"
|
82
83
|
- Gemfile
|
83
84
|
- README.md
|
84
85
|
- Rakefile
|
85
86
|
- auth0_rs256_jwt_verifier.gemspec
|
86
|
-
-
|
87
|
+
- gemfiles/json-jwt-1.10.gemfile
|
88
|
+
- gemfiles/json-jwt-1.7.gemfile
|
87
89
|
- lib/auth0_rs256_jwt_verifier.rb
|
88
90
|
- lib/auth0_rs256_jwt_verifier/certs_set.rb
|
89
91
|
- lib/auth0_rs256_jwt_verifier/exp_verifier.rb
|
@@ -95,13 +97,14 @@ files:
|
|
95
97
|
- lib/auth0_rs256_jwt_verifier/user_id.rb
|
96
98
|
- lib/auth0_rs256_jwt_verifier/valid_jwk_set.rb
|
97
99
|
- test/.rubocop.yml
|
100
|
+
- test/auth0_rs256_jwt_verifier/exp_verifier_test.rb
|
98
101
|
- test/auth0_rs256_jwt_verifier/jwt_decoder_test.rb
|
99
102
|
- test/auth0_rs256_jwt_verifier/jwt_decoder_wrapper_test.rb
|
100
103
|
- test/auth0_rs256_jwt_verifier_test.rb
|
101
104
|
- test/fixtures/sample_jwks.json
|
102
105
|
- test/fixtures/sample_jwks_2.json
|
103
106
|
- test/test_helper.rb
|
104
|
-
homepage: https://
|
107
|
+
homepage: https://github.com/DroidsOnRoids/auth0_rs256_jwt_verifier
|
105
108
|
licenses:
|
106
109
|
- MIT
|
107
110
|
metadata: {}
|
@@ -113,15 +116,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
113
116
|
requirements:
|
114
117
|
- - ">="
|
115
118
|
- !ruby/object:Gem::Version
|
116
|
-
version:
|
119
|
+
version: 2.2.0
|
117
120
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
121
|
requirements:
|
119
122
|
- - ">="
|
120
123
|
- !ruby/object:Gem::Version
|
121
124
|
version: '0'
|
122
125
|
requirements: []
|
123
|
-
|
124
|
-
rubygems_version: 2.6.8
|
126
|
+
rubygems_version: 3.0.1
|
125
127
|
signing_key:
|
126
128
|
specification_version: 4
|
127
129
|
summary: Auth0 JWT (RS256) verification library
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require "http"
|
3
|
-
require "json"
|
4
|
-
|
5
|
-
require "auth0_jwt_rs256_verifier/user_id"
|
6
|
-
require "auth0_jwt_rs256_verifier/results"
|
7
|
-
require "auth0_jwt_rs256_verifier/jwt_decoder"
|
8
|
-
require "auth0_jwt_rs256_verifier/jwt_decoder_wrapper"
|
9
|
-
require "auth0_jwt_rs256_verifier/jwk_set_downloader"
|
10
|
-
require "auth0_jwt_rs256_verifier/valid_jwk_set"
|
11
|
-
require "auth0_jwt_rs256_verifier/certs_set"
|
12
|
-
require "auth0_jwt_rs256_verifier/exp_verifier"
|
13
|
-
require "auth0_jwt_rs256_verifier/jwk"
|
14
|
-
|
15
|
-
class Auth0RS256JWTVerifier
|
16
|
-
def initialize(issuer:, audience:, jwks_url:, http: HTTP, exp_verifier: ExpVerifier.new)
|
17
|
-
@audience = audience
|
18
|
-
@issuer = issuer
|
19
|
-
@jwks_url = jwks_url
|
20
|
-
@jwks_downloader = JWKSetDownloader.new(http)
|
21
|
-
@exp_verifier = exp_verifier
|
22
|
-
@certificates = nil
|
23
|
-
end
|
24
|
-
|
25
|
-
def verify(access_token)
|
26
|
-
payload = JWTDecoderWrapper.new(
|
27
|
-
@audience,
|
28
|
-
@issuer,
|
29
|
-
certificates,
|
30
|
-
exp_verifier: @exp_verifier,
|
31
|
-
jwt_decoder: JWTDecoder.new,
|
32
|
-
).decode(access_token)
|
33
|
-
Results::ValidAccessToken.new(UserId.new(payload.sub))
|
34
|
-
rescue JWTDecoderWrapper::Error
|
35
|
-
Results::INVALID_ACCESS_TOKEN
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def certificates
|
41
|
-
return @certificates if @certificates
|
42
|
-
@certificates = CertsSet.new(ValidJWKSet.new(@jwks_downloader.download(@jwks_url)))
|
43
|
-
end
|
44
|
-
end
|