usps-jwt_auth 1.0.6 → 1.1.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/Gemfile.lock +5 -3
- data/lib/usps/jwt_auth/concern.rb +1 -1
- data/lib/usps/jwt_auth/decode.rb +4 -0
- data/lib/usps/jwt_auth/encode.rb +27 -1
- 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: be13d7639636f1abce28a82c032ea04883808bec8bb3925060f3f2071e1bf3ef
|
|
4
|
+
data.tar.gz: 8486bf2584dbcc901f00e17ef059ec3125db036f76f7c81080d68125177f50b0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2a8d5e69bd26ed1a65da6f4c7beb907aa570e7ae1942c4f256fee3c42e8f39bdcbc938018b626825ac77e5d50a64d6b994534361acfac8fda025c2681f39d4a3
|
|
7
|
+
data.tar.gz: 5fc08818ac1c3cd4b13b1005f294d6bfd0d3837fc03fd0609c74235cf9de706d5311fc01aaa44cb3cda34edcad22636f56807f6a0ac7d5e7e7b5c79a43048f5f
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
usps-jwt_auth (1.0
|
|
4
|
+
usps-jwt_auth (1.1.0)
|
|
5
5
|
activesupport (~> 8.0)
|
|
6
6
|
colorize (~> 1.1)
|
|
7
7
|
fileutils (~> 1.7)
|
|
@@ -49,7 +49,9 @@ GEM
|
|
|
49
49
|
language_server-protocol (3.17.0.5)
|
|
50
50
|
lint_roller (1.1.0)
|
|
51
51
|
logger (1.7.0)
|
|
52
|
-
minitest (
|
|
52
|
+
minitest (6.0.6)
|
|
53
|
+
drb (~> 2.0)
|
|
54
|
+
prism (~> 1.5)
|
|
53
55
|
parallel (1.27.0)
|
|
54
56
|
parser (3.3.9.0)
|
|
55
57
|
ast (~> 2.4.1)
|
|
@@ -118,7 +120,7 @@ GEM
|
|
|
118
120
|
concurrent-ruby (~> 1.0)
|
|
119
121
|
unicode-display_width (3.2.0)
|
|
120
122
|
unicode-emoji (~> 4.1)
|
|
121
|
-
unicode-emoji (4.
|
|
123
|
+
unicode-emoji (4.2.0)
|
|
122
124
|
uri (1.0.4)
|
|
123
125
|
|
|
124
126
|
PLATFORMS
|
|
@@ -54,7 +54,7 @@ module Usps
|
|
|
54
54
|
|
|
55
55
|
# Admin has entered impersonation mode -- override current_user
|
|
56
56
|
@current_user = JwtAuth.config.find_member.call(session['impersonate']['impersonated'])
|
|
57
|
-
rescue JWT::
|
|
57
|
+
rescue JWT::DecodeError
|
|
58
58
|
clear_jwt
|
|
59
59
|
nil
|
|
60
60
|
rescue ActiveRecord::RecordNotFound => e
|
data/lib/usps/jwt_auth/decode.rb
CHANGED
|
@@ -34,6 +34,10 @@ module Usps
|
|
|
34
34
|
|
|
35
35
|
def public_key(token)
|
|
36
36
|
OpenSSL::PKey::RSA.new(File.read("#{JwtAuth.config.public_keys_path}/#{fingerprint(token)}.pub"))
|
|
37
|
+
rescue Errno::ENOENT
|
|
38
|
+
# No public key matches the token's fingerprint (e.g. a stale token after key rotation),
|
|
39
|
+
# so the token cannot be verified and is treated as invalid.
|
|
40
|
+
raise JWT::VerificationError, 'No public key for token fingerprint'
|
|
37
41
|
end
|
|
38
42
|
|
|
39
43
|
def fingerprint(token)
|
data/lib/usps/jwt_auth/encode.rb
CHANGED
|
@@ -30,12 +30,34 @@ module Usps
|
|
|
30
30
|
@public_key ||= private_key.public_key
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
# OpenSSH-style SHA256 key fingerprint: base64url(SHA256(ssh-rsa wire blob)),
|
|
34
|
+
# i.e. the value `ssh-keygen -lf` prints as `SHA256:...`. This matches the key
|
|
35
|
+
# filenames and `key` claim that the consuming apps already recognize.
|
|
33
36
|
def fingerprint
|
|
34
|
-
OpenSSL::Digest::SHA256.
|
|
37
|
+
digest = OpenSSL::Digest::SHA256.digest(ssh_public_blob)
|
|
38
|
+
[digest].pack('m0').tr('+/', '-_').delete('=')
|
|
35
39
|
end
|
|
36
40
|
|
|
37
41
|
private
|
|
38
42
|
|
|
43
|
+
# Public key in the OpenSSH wire format: string('ssh-rsa') + mpint(e) + mpint(n).
|
|
44
|
+
def ssh_public_blob
|
|
45
|
+
ssh_string('ssh-rsa') + ssh_mpint(public_key.e) + ssh_mpint(public_key.n)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# SSH "string": 4-byte big-endian length prefix followed by the bytes.
|
|
49
|
+
def ssh_string(bytes)
|
|
50
|
+
[bytes.bytesize].pack('N') + bytes.b
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# SSH "mpint": a length-prefixed big-endian integer; a leading zero byte is
|
|
54
|
+
# prepended when the high bit is set so the value stays non-negative.
|
|
55
|
+
def ssh_mpint(num)
|
|
56
|
+
bytes = num.to_s(2)
|
|
57
|
+
bytes = "\x00".b + bytes if bytes.bytes.first && bytes.bytes.first >= 0x80
|
|
58
|
+
ssh_string(bytes)
|
|
59
|
+
end
|
|
60
|
+
|
|
39
61
|
def expires_at
|
|
40
62
|
::Time.now.to_i + @expiration_time
|
|
41
63
|
end
|
|
@@ -64,8 +86,12 @@ module Usps
|
|
|
64
86
|
::FileUtils.chmod(0o600, path)
|
|
65
87
|
end
|
|
66
88
|
|
|
89
|
+
# Ensure the public key is published, but only write it when missing — the file
|
|
90
|
+
# is stable for a given key, so rewriting it on every encode is needless churn.
|
|
67
91
|
def store_public_key
|
|
68
92
|
path = "#{JwtAuth.config.public_keys_path}/#{fingerprint}.pub"
|
|
93
|
+
return if File.exist?(path)
|
|
94
|
+
|
|
69
95
|
File.open(path, 'w+') { |f| f.puts(public_key) }
|
|
70
96
|
::FileUtils.chmod(0o644, path)
|
|
71
97
|
end
|