Fix 2FA endpoints (#2921)

* Fix 2FA endpoints

* use fields in data classes

* optimize usings
This commit is contained in:
Vita Chumakova
2023-06-21 15:11:38 +04:00
committed by GitHub
parent 327f988512
commit 7132340ff7
4 changed files with 88 additions and 62 deletions

View File

@@ -0,0 +1,38 @@
// _ _ _ ____ _ _____
// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
// |
// Copyright 2015-2023 Łukasz "JustArchi" Domeradzki
// Contact: JustArchi@JustArchi.net
// |
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// |
// http://www.apache.org/licenses/LICENSE-2.0
// |
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using Newtonsoft.Json;
namespace ArchiSteamFarm.Steam.Data;
internal sealed class ConfirmationData {
[JsonProperty(PropertyName = "id", Required = Required.Always)]
internal readonly ulong ID;
[JsonProperty(PropertyName = "nonce", Required = Required.Always)]
internal readonly ulong Nonce;
[JsonProperty(PropertyName = "creator_id", Required = Required.Always)]
internal readonly ulong CreatorID;
[JsonProperty(PropertyName = "type", Required = Required.Always)]
internal readonly string TypeText = "";
}

View File

@@ -0,0 +1,36 @@
// _ _ _ ____ _ _____
// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
// |
// Copyright 2015-2023 Łukasz "JustArchi" Domeradzki
// Contact: JustArchi@JustArchi.net
// |
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// |
// http://www.apache.org/licenses/LICENSE-2.0
// |
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System.Collections.Generic;
using Newtonsoft.Json;
namespace ArchiSteamFarm.Steam.Data;
internal sealed class ConfirmationsResponse : BooleanResponse {
[JsonProperty("needauth", Required = Required.DisallowNull)]
internal readonly bool NeedAuthentication;
[JsonProperty("conf", Required = Required.DisallowNull)]
internal readonly HashSet<ConfirmationData>? Confirmations;
[JsonConstructor]
private ConfirmationsResponse() { }
}

View File

@@ -1853,7 +1853,7 @@ public sealed class ArchiWebHandler : IDisposable {
return resultInSeconds == 0 ? (byte) 0 : (byte) (resultInSeconds / 86400);
}
internal async Task<IDocument?> GetConfirmationsPage(string deviceID, string confirmationHash, ulong time) {
internal async Task<ConfirmationsResponse?> GetConfirmationsPage(string deviceID, string confirmationHash, ulong time) {
if (string.IsNullOrEmpty(deviceID)) {
throw new ArgumentNullException(nameof(deviceID));
}
@@ -1889,9 +1889,9 @@ public sealed class ArchiWebHandler : IDisposable {
}
}
Uri request = new(SteamCommunityURL, $"/mobileconf/conf?a={Bot.SteamID}&k={Uri.EscapeDataString(confirmationHash)}&l=english&m=android&p={Uri.EscapeDataString(deviceID)}&t={time}&tag=conf");
Uri request = new(SteamCommunityURL, $"/mobileconf/getlist?a={Bot.SteamID}&k={Uri.EscapeDataString(confirmationHash)}&l=english&m=react&p={Uri.EscapeDataString(deviceID)}&t={time}&tag=conf");
HtmlDocumentResponse? response = await UrlGetToHtmlDocumentWithSession(request, checkSessionPreemptively: false).ConfigureAwait(false);
ObjectResponse<ConfirmationsResponse>? response = await UrlGetToJsonObjectWithSession<ConfirmationsResponse>(request, checkSessionPreemptively: false).ConfigureAwait(false);
return response?.Content;
}
@@ -2121,7 +2121,7 @@ public sealed class ArchiWebHandler : IDisposable {
}
}
Uri request = new(SteamCommunityURL, $"/mobileconf/ajaxop?a={Bot.SteamID}&cid={confirmationID}&ck={confirmationKey}&k={Uri.EscapeDataString(confirmationHash)}&l=english&m=android&op={(accept ? "allow" : "cancel")}&p={Uri.EscapeDataString(deviceID)}&t={time}&tag=conf");
Uri request = new(SteamCommunityURL, $"/mobileconf/ajaxop?a={Bot.SteamID}&cid={confirmationID}&ck={confirmationKey}&k={Uri.EscapeDataString(confirmationHash)}&l=english&m=react&op={(accept ? "allow" : "cancel")}&p={Uri.EscapeDataString(deviceID)}&t={time}&tag=conf");
ObjectResponse<BooleanResponse>? response = await UrlGetToJsonObjectWithSession<BooleanResponse>(request).ConfigureAwait(false);
@@ -2165,7 +2165,7 @@ public sealed class ArchiWebHandler : IDisposable {
List<KeyValuePair<string, string>> data = new(8 + (confirmations.Count * 2)) {
new KeyValuePair<string, string>("a", Bot.SteamID.ToString(CultureInfo.InvariantCulture)),
new KeyValuePair<string, string>("k", confirmationHash),
new KeyValuePair<string, string>("m", "android"),
new KeyValuePair<string, string>("m", "react"),
new KeyValuePair<string, string>("op", accept ? "allow" : "cancel"),
new KeyValuePair<string, string>("p", deviceID),
new KeyValuePair<string, string>("t", time.ToString(CultureInfo.InvariantCulture)),

View File

@@ -28,10 +28,10 @@ using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using AngleSharp.Dom;
using ArchiSteamFarm.Core;
using ArchiSteamFarm.Helpers;
using ArchiSteamFarm.Localization;
using ArchiSteamFarm.Steam.Data;
using ArchiSteamFarm.Storage;
using Newtonsoft.Json;
@@ -172,71 +172,23 @@ public sealed class MobileAuthenticator : IDisposable {
}
// ReSharper disable RedundantSuppressNullableWarningExpression - required for .NET Framework
using IDocument? htmlDocument = await Bot.ArchiWebHandler.GetConfirmationsPage(deviceID!, confirmationHash!, time).ConfigureAwait(false);
ConfirmationsResponse? response = await Bot.ArchiWebHandler.GetConfirmationsPage(deviceID!, confirmationHash!, time).ConfigureAwait(false);
// ReSharper restore RedundantSuppressNullableWarningExpression - required for .NET Framework
if (htmlDocument == null) {
if (response?.Confirmations == null) {
return null;
}
IEnumerable<IElement> confirmationNodes = htmlDocument.SelectNodes<IElement>("//div[@class='mobileconf_list_entry']");
if (!response.Success) {
return null;
}
HashSet<Confirmation> result = new();
foreach (IElement confirmationNode in confirmationNodes) {
string? idText = confirmationNode.GetAttribute("data-confid");
if (string.IsNullOrEmpty(idText)) {
Bot.ArchiLogger.LogNullError(idText);
return null;
}
if (!ulong.TryParse(idText, out ulong id) || (id == 0)) {
Bot.ArchiLogger.LogNullError(id);
return null;
}
string? keyText = confirmationNode.GetAttribute("data-key");
if (string.IsNullOrEmpty(keyText)) {
Bot.ArchiLogger.LogNullError(keyText);
return null;
}
if (!ulong.TryParse(keyText, out ulong key) || (key == 0)) {
Bot.ArchiLogger.LogNullError(key);
return null;
}
string? creatorText = confirmationNode.GetAttribute("data-creator");
if (string.IsNullOrEmpty(creatorText)) {
Bot.ArchiLogger.LogNullError(creatorText);
return null;
}
if (!ulong.TryParse(creatorText, out ulong creator) || (creator == 0)) {
Bot.ArchiLogger.LogNullError(creator);
return null;
}
string? typeText = confirmationNode.GetAttribute("data-type");
if (string.IsNullOrEmpty(typeText)) {
Bot.ArchiLogger.LogNullError(typeText);
return null;
}
foreach (ConfirmationData confirmation in response.Confirmations) {
// ReSharper disable once RedundantSuppressNullableWarningExpression - required for .NET Framework
if (!Enum.TryParse(typeText!, out Confirmation.EType type) || (type == Confirmation.EType.Unknown)) {
if (!Enum.TryParse(confirmation.TypeText!, out Confirmation.EType type) || (type == Confirmation.EType.Unknown)) {
Bot.ArchiLogger.LogNullError(type);
return null;
@@ -248,7 +200,7 @@ public sealed class MobileAuthenticator : IDisposable {
return null;
}
result.Add(new Confirmation(id, key, creator, type));
result.Add(new Confirmation(confirmation.ID, confirmation.Nonce, confirmation.CreatorID, type));
}
return result;