rack-cloudflare-jwt 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|