-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The `RecaptchaValidator` class is a concrete implementation of the new `IRequestValidator` (0272136). This accepts a token and an action, and validates them against reCAPTCHA's API. This takes advantage of the recently introduced `RecaptchaResponse` class to model the response from the reCAPTCHA API (3c0ad10).
- Loading branch information
1 parent
3c0ad10
commit 87d0f21
Showing
1 changed file
with
91 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/*============================================================================================================================== | ||
| Author Ignia, LLC | ||
| Client GoldSim | ||
| Project Website | ||
\=============================================================================================================================*/ | ||
using System; | ||
using System.Net; | ||
using System.Net.Http; | ||
using System.Text.Json; | ||
using System.Threading.Tasks; | ||
using GoldSim.Web.Models.Recaptcha; | ||
using OnTopic.Internal.Diagnostics; | ||
|
||
namespace GoldSim.Web.Services { | ||
|
||
/*============================================================================================================================ | ||
| CLASS: RECAPTCHA (REQUEST VALIDATOR) | ||
\---------------------------------------------------------------------------------------------------------------------------*/ | ||
/// <summary> | ||
/// Validates that a given request is from a human. | ||
/// </summary> | ||
public class RecaptchaValidator: IRequestValidator { | ||
|
||
/*========================================================================================================================== | ||
| PRIVATE VARIABLES | ||
\-------------------------------------------------------------------------------------------------------------------------*/ | ||
private readonly string _secret; | ||
private readonly string _serviceUrl; | ||
private static readonly HttpClient _client = new(); | ||
|
||
/*========================================================================================================================== | ||
| CONSTRUCTOR | ||
\-------------------------------------------------------------------------------------------------------------------------*/ | ||
/// <summary> | ||
/// Initializes a new instance of the <see cref="RecaptchaValidator"/> with necessary dependencies. | ||
/// </summary> | ||
/// <returns>A new instance of the <see cref="RecaptchaValidator"/>.</returns> | ||
public RecaptchaValidator(string secret) { | ||
_secret = secret?? throw new ArgumentNullException(nameof(secret)); | ||
_serviceUrl = "https://www.google.com/recaptcha/api/siteverify"; | ||
} | ||
|
||
/*========================================================================================================================== | ||
| IS VALID? | ||
\-------------------------------------------------------------------------------------------------------------------------*/ | ||
/// <summary> | ||
/// Determines that the request is valid, given a <paramref name="requestToken"/>. | ||
/// </summary> | ||
public async Task<bool> IsValid(string requestType, string requestToken) { | ||
|
||
/*------------------------------------------------------------------------------------------------------------------------ | ||
| Validate input | ||
\-----------------------------------------------------------------------------------------------------------------------*/ | ||
Contract.Requires(requestToken, nameof(requestToken)); | ||
|
||
/*------------------------------------------------------------------------------------------------------------------------ | ||
| Retrieve value | ||
\-----------------------------------------------------------------------------------------------------------------------*/ | ||
var uri = new Uri($"{_serviceUrl}?secret={_secret}&response={requestToken}"); | ||
var httpResponse = await _client.GetAsync(uri).ConfigureAwait(false); | ||
|
||
/*------------------------------------------------------------------------------------------------------------------------ | ||
| Validate response | ||
\-----------------------------------------------------------------------------------------------------------------------*/ | ||
if (httpResponse.StatusCode != HttpStatusCode.OK) { | ||
return false; | ||
} | ||
|
||
/*------------------------------------------------------------------------------------------------------------------------ | ||
| Validate score | ||
\-----------------------------------------------------------------------------------------------------------------------*/ | ||
var jsonResponse = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); | ||
var recaptchaResponse = JsonSerializer.Deserialize<RecaptchaResponse>( | ||
jsonResponse, | ||
new() { | ||
PropertyNameCaseInsensitive = true | ||
} | ||
); | ||
|
||
/*------------------------------------------------------------------------------------------------------------------------ | ||
| Validate response | ||
\-----------------------------------------------------------------------------------------------------------------------*/ | ||
return | ||
recaptchaResponse.Success && | ||
recaptchaResponse.Score >= 0.5 && | ||
recaptchaResponse.Action.Equals(requestType, StringComparison.Ordinal); | ||
|
||
} | ||
|
||
} // Class | ||
} // Namespace |