usps-jwt_auth 1.2.0 → 1.2.2
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/Gemfile.lock +1 -1
- data/lib/usps/jwt_auth/concern.rb +15 -2
- data/lib/usps/jwt_auth/decode.rb +18 -2
- data/lib/usps/jwt_auth/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 17662af2194b354229fdc800d007e1121fb3a34dbb65bcf1a8e1df2ec0011087
|
|
4
|
+
data.tar.gz: 7a2017a06711cb9a4714b111a4a2ee85ca3ede7c7e9d0d851e098d1dd83fa302
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 33b3ce36812329c3d25a890fd1c5d0c8b591671fef159fd602276b5217f238c021e65c60512e1ea75dc5addc07d6b1f56b0b6c2329c027cfe79362f9752752c4
|
|
7
|
+
data.tar.gz: e7e2aed19988c5148ad9550e20b94e018ac1fad129704badbce18a35f027d9c5da231b1570d7eb9821d08838921af238fed223cdd7412b72e5f2b9dab69a7f41
|
data/Gemfile.lock
CHANGED
|
@@ -64,14 +64,21 @@ module Usps
|
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
def jwt_user
|
|
67
|
-
|
|
67
|
+
return unless fetch_jwt
|
|
68
|
+
# A blank certificate claim is malformed and must never resolve to a member
|
|
69
|
+
# (e.g. a stray blank-certificate row would otherwise authenticate as that record).
|
|
70
|
+
return if jwt['certificate'].blank?
|
|
71
|
+
|
|
72
|
+
@jwt_user ||= JwtAuth.config.find_member.call(jwt['certificate'])
|
|
68
73
|
end
|
|
69
74
|
|
|
70
75
|
def set_new_jwt
|
|
71
76
|
return if params[:jwt].blank? || @set_new_jwt
|
|
72
77
|
|
|
73
78
|
store_jwt(params[:jwt])
|
|
74
|
-
|
|
79
|
+
# An unverifiable token (e.g. a key we cannot resolve) clears the jwt and returns
|
|
80
|
+
# nil; fall through so the visitor is sent to login rather than into the app.
|
|
81
|
+
return unless ensure_valid_jwt_has_valid_member!
|
|
75
82
|
|
|
76
83
|
redirect_to_path!
|
|
77
84
|
@set_new_jwt = true
|
|
@@ -124,6 +131,12 @@ module Usps
|
|
|
124
131
|
def ensure_valid_jwt_has_valid_member!
|
|
125
132
|
fetch_jwt
|
|
126
133
|
jwt_user
|
|
134
|
+
rescue JWT::DecodeError
|
|
135
|
+
# The token cannot be verified (e.g. an unresolvable key). Drop it and report
|
|
136
|
+
# "not signed in" so the caller redirects to login — never let this escape as an
|
|
137
|
+
# unhandled 500, which the error page would re-trigger when it re-authenticates.
|
|
138
|
+
clear_jwt
|
|
139
|
+
@current_user = nil
|
|
127
140
|
rescue ActiveRecord::RecordNotFound
|
|
128
141
|
reset_session
|
|
129
142
|
clear_jwt
|
data/lib/usps/jwt_auth/decode.rb
CHANGED
|
@@ -9,6 +9,10 @@ module Usps
|
|
|
9
9
|
# Decode and validate data from a JWT
|
|
10
10
|
#
|
|
11
11
|
class Decode
|
|
12
|
+
# Keep a slow or unreachable store from tying up the caller (e.g. a web worker).
|
|
13
|
+
OPEN_TIMEOUT = 2
|
|
14
|
+
READ_TIMEOUT = 2
|
|
15
|
+
|
|
12
16
|
def self.decode(token, audience: [], issuer: nil)
|
|
13
17
|
new.decode(token, audience: audience, issuer: issuer)
|
|
14
18
|
end
|
|
@@ -75,15 +79,27 @@ module Usps
|
|
|
75
79
|
raise JWT::VerificationError, 'Fetched public key does not match token fingerprint'
|
|
76
80
|
end
|
|
77
81
|
|
|
82
|
+
cache_key(fingerprint, pem)
|
|
83
|
+
key
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Persist the verified key so the next decode skips the fetch — but best-effort: an
|
|
87
|
+
# unwritable cache dir (e.g. a read-only or wrong-owner deploy) must NOT fail a token
|
|
88
|
+
# we have already fetched and verified. On a write error we just refetch next time.
|
|
89
|
+
def cache_key(fingerprint, pem)
|
|
78
90
|
path = cache_path(fingerprint)
|
|
79
91
|
FileUtils.mkdir_p(File.dirname(path))
|
|
80
92
|
File.write(path, pem)
|
|
81
|
-
|
|
93
|
+
rescue SystemCallError
|
|
94
|
+
nil
|
|
82
95
|
end
|
|
83
96
|
|
|
84
97
|
def http_get(url)
|
|
85
98
|
uri = URI.parse(url)
|
|
86
|
-
response = Net::HTTP.
|
|
99
|
+
response = Net::HTTP.start(
|
|
100
|
+
uri.host, uri.port,
|
|
101
|
+
use_ssl: uri.scheme == 'https', open_timeout: OPEN_TIMEOUT, read_timeout: READ_TIMEOUT
|
|
102
|
+
) { |http| http.get(uri.request_uri) }
|
|
87
103
|
raise "HTTP #{response.code} for #{url}" unless response.is_a?(Net::HTTPSuccess)
|
|
88
104
|
|
|
89
105
|
response.body
|