warden-auth0 0.5.1 → 2.0.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/README.md +23 -0
- data/lib/warden/auth0/strategy.rb +35 -4
- data/lib/warden/auth0/token_decoder.rb +9 -11
- data/lib/warden/auth0/version.rb +1 -1
- data/lib/warden/auth0.rb +4 -45
- data/warden-auth0.gemspec +0 -1
- metadata +2 -22
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8c9e553549199de29e2c2bc57d460446f5ab3a703713062a0a6a813814c47af2
|
|
4
|
+
data.tar.gz: 62bcd022d6d526c3bfc80963754476ad8b698ad3b7d7f2a3c6a30efc0ba2e536
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e6fd5caf3bfd2f5474f990fe424a5be1c42b82b9e7577a843b7721041d57e53a0909a6b7d1b25885305a8f375e0e812088b9587ef3c1ae1ec8ca1da96a2516cd
|
|
7
|
+
data.tar.gz: aefd93fdc3655f844ca867ad08c75bd8410c3096f17b1bc3b028aa4c18b413c92f34e055fe2d8b3d1aeb946fdd8f12c95e2b7d72bb113e8461c796927b5b5528
|
data/README.md
CHANGED
|
@@ -39,6 +39,29 @@ Or install it yourself as:
|
|
|
39
39
|
|
|
40
40
|
You can look at this gem's wiki to see some [example applications](https://github.com/waiting-for-dev/warden-jwt_auth/wiki). Please, add yours if you think it can help somebody.
|
|
41
41
|
|
|
42
|
+
### Auth0 JWT strategy and JWKS
|
|
43
|
+
|
|
44
|
+
Tokens are verified with `issuer`, `audience`, `algorithm`, and a **JWKS** object passed to `ruby-jwt`. The strategy does **not** define a `jwks_url` setting: you assign `jwks` yourself, usually once at boot.
|
|
45
|
+
|
|
46
|
+
```ruby
|
|
47
|
+
Warden::Auth0::Strategy.configure do |config|
|
|
48
|
+
config.issuer = 'https://YOUR_DOMAIN.auth0.com/'
|
|
49
|
+
config.aud = 'https://your-api-identifier' # Auth0 API audience
|
|
50
|
+
config.algorithm = 'RS256'
|
|
51
|
+
config.jwks = Warden::Auth0::Strategy.fetch_jwks(
|
|
52
|
+
'https://YOUR_DOMAIN.auth0.com/.well-known/jwks.json'
|
|
53
|
+
)
|
|
54
|
+
# Optional: TLS verification for JWKS HTTP fetch (default: true)
|
|
55
|
+
# config.verify_ssl = true
|
|
56
|
+
end
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`fetch_jwks` returns signing keys (`use: sig`) suitable for verification. For tests or advanced cases, set `config.jwks` to any value accepted by `JWT.decode`’s `jwks:` option (see [ruby-jwt](https://github.com/jwt/ruby-jwt)).
|
|
60
|
+
|
|
61
|
+
**Migration:** If you previously relied on a `jwks_url` strategy setting, remove it and set `jwks` explicitly as above (or load keys another way and assign `config.jwks`).
|
|
62
|
+
|
|
63
|
+
Register the strategy and implement a resolver for your Warden scope (e.g. `user_resolver`) as in the examples under [Warden scopes configuration](#warden-scopes-configuration).
|
|
64
|
+
|
|
42
65
|
At its core, this library consists of:
|
|
43
66
|
|
|
44
67
|
- A Warden strategy that authenticates a user if a valid JWT token is present in the request headers.
|
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'warden'
|
|
4
|
+
require 'dry/configurable'
|
|
4
5
|
|
|
5
6
|
module Warden
|
|
6
7
|
module Auth0
|
|
7
8
|
# Warden strategy to authenticate a user through a JWT token in the
|
|
8
|
-
#
|
|
9
|
+
# request header (see Warden::Auth0.config.token_header).
|
|
10
|
+
#
|
|
11
|
+
# Configure issuer, aud, algorithm on the strategy before adding to Warden.
|
|
9
12
|
class Strategy < Warden::Strategies::Base
|
|
13
|
+
extend Dry::Configurable
|
|
14
|
+
|
|
15
|
+
setting :algorithm
|
|
16
|
+
setting :issuer
|
|
17
|
+
setting :aud
|
|
18
|
+
setting :verify_ssl, default: true
|
|
19
|
+
|
|
20
|
+
# Store the JWKS after fetching it
|
|
21
|
+
setting :jwks
|
|
22
|
+
|
|
10
23
|
def valid?
|
|
11
24
|
token_exists? && issuer_claim_valid? && aud_claim_valid?
|
|
12
25
|
end
|
|
@@ -42,7 +55,8 @@ module Warden
|
|
|
42
55
|
end
|
|
43
56
|
|
|
44
57
|
def decoded_token
|
|
45
|
-
|
|
58
|
+
cfg = self.class.config
|
|
59
|
+
TokenDecoder.new(algorithm: cfg.algorithm, jwks: cfg.jwks).call(token)
|
|
46
60
|
end
|
|
47
61
|
|
|
48
62
|
def issuer_claim_valid?
|
|
@@ -60,14 +74,14 @@ module Warden
|
|
|
60
74
|
end
|
|
61
75
|
|
|
62
76
|
def configured_aud
|
|
63
|
-
audience =
|
|
77
|
+
audience = self.class.config.aud
|
|
64
78
|
raise Errors::NoConfiguredAud if audience.nil?
|
|
65
79
|
|
|
66
80
|
audience
|
|
67
81
|
end
|
|
68
82
|
|
|
69
83
|
def configured_issuer
|
|
70
|
-
configured_issuer =
|
|
84
|
+
configured_issuer = self.class.config.issuer
|
|
71
85
|
raise Errors::NoConfiguredIssuer if configured_issuer.nil?
|
|
72
86
|
|
|
73
87
|
configured_issuer
|
|
@@ -100,6 +114,23 @@ module Warden
|
|
|
100
114
|
|
|
101
115
|
false
|
|
102
116
|
end
|
|
117
|
+
|
|
118
|
+
# Fetches JWKS from the given URL.
|
|
119
|
+
def self.fetch_jwks(jwks_url)
|
|
120
|
+
puts "Fetching JWKS from #{jwks_url}"
|
|
121
|
+
raise 'No url provided for fetching jwks' if jwks_url.nil?
|
|
122
|
+
jwks_response = self.connection.get(jwks_url).body
|
|
123
|
+
jwks = JWT::JWK::Set.new(jwks_response)
|
|
124
|
+
jwks.select { |key| key[:use] == 'sig' }
|
|
125
|
+
rescue StandardError => e
|
|
126
|
+
raise "Failed to fetch JWKS: #{e.message}"
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def self.connection
|
|
130
|
+
Faraday.new(request: { timeout: 5 }, ssl: { verify: config.verify_ssl }) do |conn|
|
|
131
|
+
conn.response :json
|
|
132
|
+
end
|
|
133
|
+
end
|
|
103
134
|
end
|
|
104
135
|
end
|
|
105
136
|
end
|
|
@@ -4,24 +4,22 @@ require 'jwt/error'
|
|
|
4
4
|
|
|
5
5
|
module Warden
|
|
6
6
|
module Auth0
|
|
7
|
-
# Decodes a JWT into a hash payload
|
|
7
|
+
# Decodes a JWT into a hash payload. Algorithm and JWKS are provided by the strategy config.
|
|
8
8
|
class TokenDecoder
|
|
9
|
-
|
|
9
|
+
attr_reader :algorithm, :jwks
|
|
10
|
+
|
|
11
|
+
# @param algorithm [String] algorithm (e.g. 'RS256')
|
|
12
|
+
# @param jwks [Object] JWKS used to verify (e.g. JWT::JWK::Set)
|
|
13
|
+
def initialize(algorithm:, jwks:)
|
|
14
|
+
@algorithm = algorithm
|
|
15
|
+
@jwks = jwks
|
|
16
|
+
end
|
|
10
17
|
|
|
11
18
|
# Decodes the payload from a JWT as a hash
|
|
12
19
|
#
|
|
13
|
-
# @see JWT.decode for all the exceptions than can be raised when given
|
|
14
|
-
# token is invalid
|
|
15
|
-
#
|
|
16
20
|
# @param token [String] a JWT
|
|
17
21
|
# @return [Hash] payload decoded from the JWT
|
|
18
22
|
def call(token)
|
|
19
|
-
decode(token)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
private
|
|
23
|
-
|
|
24
|
-
def decode(token)
|
|
25
23
|
JWT.decode(token, nil, true, algorithms: algorithm, jwks: jwks)[0]
|
|
26
24
|
end
|
|
27
25
|
end
|
data/lib/warden/auth0/version.rb
CHANGED
data/lib/warden/auth0.rb
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'dry/configurable'
|
|
4
|
-
require 'dry/auto_inject'
|
|
5
4
|
require 'jwt'
|
|
6
5
|
require 'warden'
|
|
7
6
|
require 'faraday'
|
|
@@ -10,53 +9,13 @@ module Warden
|
|
|
10
9
|
# Auth0 authentication plugin for warden.
|
|
11
10
|
#
|
|
12
11
|
# It consists of a strategy which tries to authenticate an user decoding a
|
|
13
|
-
# token present in the
|
|
12
|
+
# token present in the request header (as `Bearer %token%`). The header name
|
|
13
|
+
# is configured via +token_header+.
|
|
14
14
|
module Auth0
|
|
15
15
|
extend Dry::Configurable
|
|
16
|
-
# Request header that will be used for receiving and returning the token.
|
|
17
|
-
setting :token_header, default: 'Authorization'
|
|
18
|
-
|
|
19
|
-
# The algorithm used to encode the token
|
|
20
|
-
setting :algorithm
|
|
21
|
-
|
|
22
|
-
# The issuer claims associated with the tokens
|
|
23
|
-
#
|
|
24
|
-
# Will be used to only apply the warden strategy when the issuer matches.
|
|
25
|
-
# This allows for multiple token issuers being used.
|
|
26
|
-
# @see https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1
|
|
27
|
-
setting :issuer, default: nil
|
|
28
|
-
|
|
29
|
-
# The aud claims associated with the tokens
|
|
30
|
-
#
|
|
31
|
-
# Will be used to only apply the warden strategy when the audience matches.
|
|
32
|
-
setting :aud, default: nil
|
|
33
|
-
|
|
34
|
-
# The url to fetch jwks from
|
|
35
|
-
setting :jwks_url
|
|
36
|
-
|
|
37
|
-
setting :verify_ssl, default: true
|
|
38
16
|
|
|
39
|
-
#
|
|
40
|
-
setting :
|
|
41
|
-
|
|
42
|
-
Import = Dry::AutoInject(config)
|
|
43
|
-
|
|
44
|
-
# Method to fetch JWKS from the specified URL
|
|
45
|
-
def self.fetch_jwks(jwks_url)
|
|
46
|
-
raise 'No url provided for fetching jwks' if jwks_url.nil?
|
|
47
|
-
|
|
48
|
-
jwks_response = connection.get(jwks_url).body
|
|
49
|
-
jwks = JWT::JWK::Set.new(jwks_response)
|
|
50
|
-
jwks.select { |key| key[:use] == 'sig' }
|
|
51
|
-
rescue StandardError => e
|
|
52
|
-
raise "Failed to fetch JWKS: #{e.message}"
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def self.connection
|
|
56
|
-
Faraday.new(request: { timeout: 5 }, ssl: { verify: config.verify_ssl }) do |conn|
|
|
57
|
-
conn.response :json
|
|
58
|
-
end
|
|
59
|
-
end
|
|
17
|
+
# Request header used for receiving and returning the token.
|
|
18
|
+
setting :token_header, default: 'Authorization'
|
|
60
19
|
end
|
|
61
20
|
end
|
|
62
21
|
|
data/warden-auth0.gemspec
CHANGED
|
@@ -21,7 +21,6 @@ Gem::Specification.new do |spec|
|
|
|
21
21
|
|
|
22
22
|
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
23
23
|
|
|
24
|
-
spec.add_dependency 'dry-auto_inject', '>= 0.8', '< 2'
|
|
25
24
|
spec.add_dependency 'dry-configurable', '>= 0.13', '< 2'
|
|
26
25
|
spec.add_dependency 'faraday', '2.9.0'
|
|
27
26
|
spec.add_dependency 'jwt', '~> 2.1'
|
metadata
CHANGED
|
@@ -1,35 +1,15 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: warden-auth0
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- 1KOMMA5º
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-04-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
|
-
- !ruby/object:Gem::Dependency
|
|
14
|
-
name: dry-auto_inject
|
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
|
16
|
-
requirements:
|
|
17
|
-
- - ">="
|
|
18
|
-
- !ruby/object:Gem::Version
|
|
19
|
-
version: '0.8'
|
|
20
|
-
- - "<"
|
|
21
|
-
- !ruby/object:Gem::Version
|
|
22
|
-
version: '2'
|
|
23
|
-
type: :runtime
|
|
24
|
-
prerelease: false
|
|
25
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
26
|
-
requirements:
|
|
27
|
-
- - ">="
|
|
28
|
-
- !ruby/object:Gem::Version
|
|
29
|
-
version: '0.8'
|
|
30
|
-
- - "<"
|
|
31
|
-
- !ruby/object:Gem::Version
|
|
32
|
-
version: '2'
|
|
33
13
|
- !ruby/object:Gem::Dependency
|
|
34
14
|
name: dry-configurable
|
|
35
15
|
requirement: !ruby/object:Gem::Requirement
|