1 2 module vibeauth.challenges.recaptcha; 3 4 import vibe.http.client; 5 import vibe.stream.operations; 6 import vibe.data.json; 7 8 import std.conv; 9 10 import vibeauth.challenges.base; 11 12 /// Class that implements the google recaptcha challenge 13 class ReCaptcha : IChallenge { 14 15 private immutable { 16 string siteKey; 17 string secretKey; 18 } 19 20 this(string siteKey, string secretKey) { 21 this.siteKey = siteKey; 22 this.secretKey = secretKey; 23 } 24 25 /// Generate a challenge. The request must be initiated from the challenge template 26 string generate(HTTPServerRequest req, HTTPServerResponse res) { 27 return ""; 28 } 29 30 /// Get a template for the current challenge 31 string getTemplate(string challangeLocation) { 32 auto tpl = `<script src="https://www.google.com/recaptcha/api.js?render=` ~ siteKey ~ `"></script> 33 <script> 34 grecaptcha.ready(function() { 35 grecaptcha.execute('` ~ siteKey ~ `', {action: 'login'}).then(function(token) { 36 document.querySelector("#recaptchaValue").value = token; 37 }); 38 }); 39 </script> 40 <input id="recaptchaValue" name="response" type="hidden" value="">`; 41 42 return tpl; 43 } 44 45 /// Returns the site key 46 Json getConfig() { 47 auto result = Json.emptyObject; 48 49 result["siteKey"] = siteKey; 50 51 return result; 52 } 53 54 /// Validate the challenge 55 bool validate(HTTPServerRequest req, HTTPServerResponse res, string response) { 56 Json result; 57 58 requestHTTP("https://www.google.com/recaptcha/api/siteverify?secret=" ~ secretKey ~ "&response=" ~ response, 59 (scope req) { 60 req.method = HTTPMethod.POST; 61 req.headers["Content-length"] = "0"; 62 }, 63 (scope res) { 64 result = res.bodyReader.readAllUTF8().parseJsonString; 65 } 66 ); 67 68 if("success" !in result) { 69 return false; 70 } 71 72 return result["success"].to!bool == true; 73 } 74 }