Skip to content

Commit d642e1e

Browse files
committed
make authorization codes one-time use
1 parent 2111013 commit d642e1e

File tree

2 files changed

+19
-3
lines changed

2 files changed

+19
-3
lines changed

controllers/verify.rb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,21 @@ def http_response(code, data)
102102

103103
if Login.expired? login
104104
puts "The auth code expired"
105-
http_error 400, {error: "invalid_request", error_description: "The auth code has expired (valid for 60 seconds)"}
105+
http_error 400, {error: "invalid_request", error_description: "The authorization code has expired (valid for 60 seconds)"}
106+
end
107+
108+
if Login.used? login
109+
puts "The auth code has been used"
110+
http_error 400, {error: "invalid_request", error_description: "The authorization code has already been used"}
106111
end
107112

108113
if login['redirect_uri'] != params[:redirect_uri]
109114
puts "The redirect_uri parameter did not match"
110115
http_error 400, {error: "invalid_request", error_description: "The 'redirect_uri' parameter did not match"}
111116
end
112117

118+
Login.mark_used login
119+
113120
Log.save login
114121

115122
puts "Successful auth code verification"

models/login.rb

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ class Login
33
def self.generate_auth_code(params)
44
jwt = JWT.encode(params.merge({
55
:nonce => Random.rand(100000..999999),
6-
:created_at => Time.now.to_i
6+
:created_at => Time.now.to_i,
7+
:id => "#{Time.now.to_i}.#{Random.rand(10000..99999)}"
78
}), SiteConfig.jwt_key)
89

910
salt = SecureRandom.random_bytes(16)
@@ -53,8 +54,16 @@ def self.decode_auth_code(code)
5354
end
5455
end
5556

57+
def self.used?(login)
58+
# When a code is used, the ID cached in Redis for 2 minutes. If it's present, it has been used.
59+
return R.get "indieauth::code::#{login['id']}"
60+
end
61+
62+
def self.mark_used(login)
63+
R.setex "indieauth::code::#{login['id']}", 120, Time.now.to_i
64+
end
65+
5666
def self.expired?(login)
57-
return false
5867
# Auth codes are only valid for 60 seconds
5968
return login['created_at'] < Time.now.to_i - 60
6069
end

0 commit comments

Comments
 (0)