Skip to content

Commit

Permalink
make authorization codes one-time use
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronpk committed Jul 29, 2020
1 parent 2111013 commit d642e1e
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 3 deletions.
9 changes: 8 additions & 1 deletion controllers/verify.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,21 @@ def http_response(code, data)

if Login.expired? login
puts "The auth code expired"
http_error 400, {error: "invalid_request", error_description: "The auth code has expired (valid for 60 seconds)"}
http_error 400, {error: "invalid_request", error_description: "The authorization code has expired (valid for 60 seconds)"}
end

if Login.used? login
puts "The auth code has been used"
http_error 400, {error: "invalid_request", error_description: "The authorization code has already been used"}
end

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

Login.mark_used login

Log.save login

puts "Successful auth code verification"
Expand Down
13 changes: 11 additions & 2 deletions models/login.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ class Login
def self.generate_auth_code(params)
jwt = JWT.encode(params.merge({
:nonce => Random.rand(100000..999999),
:created_at => Time.now.to_i
:created_at => Time.now.to_i,
:id => "#{Time.now.to_i}.#{Random.rand(10000..99999)}"
}), SiteConfig.jwt_key)

salt = SecureRandom.random_bytes(16)
Expand Down Expand Up @@ -53,8 +54,16 @@ def self.decode_auth_code(code)
end
end

def self.used?(login)
# When a code is used, the ID cached in Redis for 2 minutes. If it's present, it has been used.
return R.get "indieauth::code::#{login['id']}"
end

def self.mark_used(login)
R.setex "indieauth::code::#{login['id']}", 120, Time.now.to_i
end

def self.expired?(login)
return false
# Auth codes are only valid for 60 seconds
return login['created_at'] < Time.now.to_i - 60
end
Expand Down

0 comments on commit d642e1e

Please sign in to comment.