Deploy Promiscuity Auth API / deploy (push) Failing after 20s
Deploy Promiscuity Character API / deploy (push) Failing after 19s
Deploy Promiscuity Crafting API / deploy (push) Failing after 20s
Deploy Promiscuity Inventory API / deploy (push) Failing after 19s
Deploy Promiscuity Locations API / deploy (push) Failing after 19s
Deploy Promiscuity Mail API / deploy (push) Failing after 20s
Deploy Promiscuity World API / deploy (push) Failing after 20s
k8s smoke test / test (push) Failing after 20s
67 lines
3.1 KiB
C#
67 lines
3.1 KiB
C#
using System.Text.RegularExpressions;
|
|
|
|
namespace AuthApi.Services;
|
|
|
|
public class SteamOpenIdService
|
|
{
|
|
public const string Endpoint = "https://steamcommunity.com/openid/login";
|
|
private static readonly Regex ClaimedIdPattern = new(
|
|
"^https?://steamcommunity\\.com/openid/id/(?<id>[0-9]{17})$",
|
|
RegexOptions.Compiled | RegexOptions.CultureInvariant);
|
|
private readonly IHttpClientFactory _httpClients;
|
|
|
|
public SteamOpenIdService(IHttpClientFactory httpClients) => _httpClients = httpClients;
|
|
|
|
public static string BuildAuthenticationUrl(string realm, string returnUrl)
|
|
{
|
|
var parameters = new Dictionary<string, string>
|
|
{
|
|
["openid.ns"] = "http://specs.openid.net/auth/2.0",
|
|
["openid.mode"] = "checkid_setup",
|
|
["openid.return_to"] = returnUrl,
|
|
["openid.realm"] = realm,
|
|
["openid.identity"] = "http://specs.openid.net/auth/2.0/identifier_select",
|
|
["openid.claimed_id"] = "http://specs.openid.net/auth/2.0/identifier_select"
|
|
};
|
|
return Endpoint + "?" + string.Join("&", parameters.Select(pair =>
|
|
$"{Uri.EscapeDataString(pair.Key)}={Uri.EscapeDataString(pair.Value)}"));
|
|
}
|
|
|
|
public async Task<string?> VerifyCallbackAsync(IQueryCollection query, string expectedReturnUrl, CancellationToken cancellationToken)
|
|
{
|
|
if (!string.Equals(query["openid.mode"], "id_res", StringComparison.Ordinal) ||
|
|
!string.Equals(query["openid.op_endpoint"].ToString().TrimEnd('/'), Endpoint.TrimEnd('/'), StringComparison.OrdinalIgnoreCase) ||
|
|
!string.Equals(query["openid.return_to"], expectedReturnUrl, StringComparison.Ordinal))
|
|
return null;
|
|
|
|
var claimedId = query["openid.claimed_id"].ToString();
|
|
if (!string.Equals(claimedId, query["openid.identity"], StringComparison.Ordinal))
|
|
return null;
|
|
var match = ClaimedIdPattern.Match(claimedId);
|
|
if (!match.Success)
|
|
return null;
|
|
|
|
var fields = query
|
|
.Where(pair => pair.Key.StartsWith("openid.", StringComparison.Ordinal))
|
|
.ToDictionary(pair => pair.Key, pair => pair.Value.ToString());
|
|
fields["openid.mode"] = "check_authentication";
|
|
var client = _httpClients.CreateClient(nameof(SteamOpenIdService));
|
|
client.Timeout = TimeSpan.FromSeconds(15);
|
|
using var response = await client.PostAsync(Endpoint, new FormUrlEncodedContent(fields), cancellationToken);
|
|
if (!response.IsSuccessStatusCode)
|
|
return null;
|
|
var validation = await response.Content.ReadAsStringAsync(cancellationToken);
|
|
return IsValidAuthenticationResponse(validation) ? match.Groups["id"].Value : null;
|
|
}
|
|
|
|
internal static bool IsValidAuthenticationResponse(string response) =>
|
|
response.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
|
.Any(line => string.Equals(line, "is_valid:true", StringComparison.Ordinal));
|
|
|
|
internal static string? ExtractSteamId(string claimedId)
|
|
{
|
|
var match = ClaimedIdPattern.Match(claimedId);
|
|
return match.Success ? match.Groups["id"].Value : null;
|
|
}
|
|
}
|