Created
October 18, 2020 20:01
-
-
Save rishavs/c7d3cd2a4718ab39ba6fa715e6a028ae to your computer and use it in GitHub Desktop.
CSRF protection in Crystal
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Embed this as a <input type="hidden"> into *every form* | |
def csrf_token(session_id, key = ENV_CSRF_TOKEN_SECRET) | |
d = OpenSSL::Digest.new("SHA256") | |
d.update session_id.to_slice | |
payload = String.build do |s| | |
s << d.hexdigest | |
s << " " | |
s << Time.utc.to_unix | |
end | |
"#{OpenSSL::HMAC.hexdigest(CSRF_TOKEN_HMAC_ALGO, key, payload)} #{payload}" | |
end | |
# Verify the token of *every posted form* before trusting the input | |
def verify_csrf_token!(session_id, token, key = ENV_CSRF_TOKEN_SECRET, ttl = ENV_CSRF_TOKEN_TTL) | |
hmac, sid_digest, timestamp = token.split(" ") | |
correct_hmac = OpenSSL::HMAC.hexdigest(CSRF_TOKEN_HMAC_ALGO, key, "#{sid_digest} #{timestamp}") | |
raise InvalidCSRFToken.new("CSRF token is corrupt") unless correct_hmac == hmac | |
raise InvalidCSRFToken.new("CSRF token is expired") unless Time.utc.to_unix + ttl > timestamp.to_i | |
correct_sid_digest = OpenSSL::Digest.new("SHA256") | |
correct_sid_digest.update session_id.to_slice | |
raise InvalidCSRFToken.new("CSRF token does not match session") unless correct_sid_digest.hexdigest == sid_digest | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html