rack-cloudflare-jwt 0.0.6 → 0.0.7
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/lib/rack/cloudflare_jwt/auth.rb +40 -17
- data/lib/rack/cloudflare_jwt/version.rb +1 -1
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c4ed6badeecd1b367985b571e0c2d308b1ec1f738f228c1d818ea1d17ef4f05
|
4
|
+
data.tar.gz: ac39d8ec47898b8069e538a1b1593faea1f5e8b0f7823a9e8eb75ea7d7add310
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 24184df0dd0e17acc8e6cad290a7b34e40146865c9a377475d135e0ad7046f7b6bea682418a9602e08be89964902ab4cd680be8d49f853b38ef6e3920ad09cee
|
7
|
+
data.tar.gz: 196a5aa4ab5ea4370d21a90080493025dc3530cda35b027bdb24a2844ae0dfa3d9f117dc137e011ec65ee0ebc9d3875394286328b708aca2a9c9007ddd88ae4d
|
@@ -11,12 +11,17 @@ module Rack
|
|
11
11
|
#
|
12
12
|
# @see https://developers.cloudflare.com/access/setting-up-access/validate-jwt-tokens/
|
13
13
|
class Auth
|
14
|
+
# Custom decode token error.
|
15
|
+
class DecodeTokenError < StandardError; end
|
16
|
+
|
14
17
|
# Certs path
|
15
18
|
CERTS_PATH = '/cdn-cgi/access/certs'
|
16
19
|
# Default algorithm
|
17
20
|
DEFAULT_ALGORITHM = 'RS256'
|
18
21
|
# CloudFlare JWT header.
|
19
22
|
HEADER_NAME = 'HTTP_CF_ACCESS_JWT_ASSERTION'
|
23
|
+
# HTTP_HOST header.
|
24
|
+
HEADER_HTTP_HOST = 'HTTP_HOST'
|
20
25
|
|
21
26
|
# Token regex.
|
22
27
|
#
|
@@ -79,12 +84,14 @@ module Rack
|
|
79
84
|
# extract the token from header.
|
80
85
|
token = env[HEADER_NAME]
|
81
86
|
decoded_token = public_keys(env).find do |key|
|
82
|
-
|
83
|
-
|
87
|
+
break decode_token(token, key.public_key)
|
88
|
+
rescue DecodeTokenError => e
|
89
|
+
logger.info e.message
|
90
|
+
nil
|
84
91
|
end
|
85
92
|
|
86
93
|
if decoded_token
|
87
|
-
|
94
|
+
logger.debug 'CloudFlare JWT token is valid'
|
88
95
|
|
89
96
|
env['jwt.payload'] = decoded_token.first
|
90
97
|
env['jwt.header'] = decoded_token.last
|
@@ -103,30 +110,32 @@ module Rack
|
|
103
110
|
# {"alg"=>"RS256"} # header
|
104
111
|
# ]
|
105
112
|
#
|
106
|
-
# @return [Array<Hash>] the token.
|
113
|
+
# @return [Array<Hash>] the token or `nil` at error.
|
114
|
+
# @raise [DecodeTokenError] if the token is invalid.
|
115
|
+
#
|
107
116
|
# @see https://github.com/jwt/ruby-jwt/tree/v2.2.1#algorithms-and-usage
|
108
117
|
def decode_token(token, secret)
|
109
118
|
Rack::JWT::Token.decode(token, secret, true, aud: policy_aud, verify_aud: true, algorithm: DEFAULT_ALGORITHM)
|
110
119
|
rescue ::JWT::VerificationError
|
111
|
-
|
120
|
+
raise DecodeTokenError, 'Invalid JWT token : Signature Verification Error'
|
112
121
|
rescue ::JWT::ExpiredSignature
|
113
|
-
|
122
|
+
raise DecodeTokenError, 'Invalid JWT token : Expired Signature (exp)'
|
114
123
|
rescue ::JWT::IncorrectAlgorithm
|
115
|
-
|
124
|
+
raise DecodeTokenError, 'Invalid JWT token : Incorrect Key Algorithm'
|
116
125
|
rescue ::JWT::ImmatureSignature
|
117
|
-
|
126
|
+
raise DecodeTokenError, 'Invalid JWT token : Immature Signature (nbf)'
|
118
127
|
rescue ::JWT::InvalidIssuerError
|
119
|
-
|
128
|
+
raise DecodeTokenError, 'Invalid JWT token : Invalid Issuer (iss)'
|
120
129
|
rescue ::JWT::InvalidIatError
|
121
|
-
|
130
|
+
raise DecodeTokenError, 'Invalid JWT token : Invalid Issued At (iat)'
|
122
131
|
rescue ::JWT::InvalidAudError
|
123
|
-
|
132
|
+
raise DecodeTokenError, 'Invalid JWT token : Invalid Audience (aud)'
|
124
133
|
rescue ::JWT::InvalidSubError
|
125
|
-
|
134
|
+
raise DecodeTokenError, 'Invalid JWT token : Invalid Subject (sub)'
|
126
135
|
rescue ::JWT::InvalidJtiError
|
127
|
-
|
136
|
+
raise DecodeTokenError, 'Invalid JWT token : Invalid JWT ID (jti)'
|
128
137
|
rescue ::JWT::DecodeError
|
129
|
-
|
138
|
+
raise DecodeTokenError, 'Invalid JWT token : Decode Error'
|
130
139
|
end
|
131
140
|
|
132
141
|
# Private: Check if current path is in the include_paths.
|
@@ -162,8 +171,8 @@ module Rack
|
|
162
171
|
#
|
163
172
|
# @return [Array<OpenSSL::PKey::RSA>] the public keys.
|
164
173
|
def public_keys(env)
|
165
|
-
host = env[
|
166
|
-
keys =
|
174
|
+
host = env[HEADER_HTTP_HOST]
|
175
|
+
keys = cache.fetch([self.class.name, '#secrets', host]) { fetch_public_keys(host) }
|
167
176
|
keys.map do |jwk_data|
|
168
177
|
::JWT::JWK.import(jwk_data).keypair
|
169
178
|
end
|
@@ -176,10 +185,24 @@ module Rack
|
|
176
185
|
# @return [Array<Hash>] the public keys.
|
177
186
|
def fetch_public_keys(host)
|
178
187
|
json = Net::HTTP.get(host, CERTS_PATH)
|
179
|
-
json.
|
188
|
+
json.empty? ? [] : MultiJson.load(json, symbolize_keys: true).fetch(:keys)
|
180
189
|
rescue StandardError
|
181
190
|
[]
|
182
191
|
end
|
192
|
+
|
193
|
+
# Private: Get a cache store.
|
194
|
+
#
|
195
|
+
# @return [ActiveSupport::Cache::Store] the cache store.
|
196
|
+
def cache
|
197
|
+
Rails.cache
|
198
|
+
end
|
199
|
+
|
200
|
+
# Private: Get a logger.
|
201
|
+
#
|
202
|
+
# @return [ActiveSupport::Logger] the logger.
|
203
|
+
def logger
|
204
|
+
Rails.logger
|
205
|
+
end
|
183
206
|
end
|
184
207
|
end
|
185
208
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-cloudflare-jwt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aleksei Vokhmin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-02-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: 0.16.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: webmock
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 3.8.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 3.8.0
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: jwt
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|