if rotating account does not work, re login
This commit is contained in:
parent
aefed18612
commit
9a409bcab0
1 changed files with 78 additions and 66 deletions
|
|
@ -35,75 +35,80 @@ var builder = WebApplication.CreateBuilder(args);
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
app.UseWebSockets();
|
app.UseWebSockets();
|
||||||
|
|
||||||
Config.Instance.Accounts.ForEach(async account =>
|
void LogInAllAccounts()
|
||||||
{
|
{
|
||||||
try
|
Config.Instance.Accounts.ForEach(async account =>
|
||||||
{
|
{
|
||||||
var cookieContainer = new CookieContainer();
|
try
|
||||||
var handler = new HttpClientHandler
|
|
||||||
{
|
{
|
||||||
CookieContainer = cookieContainer
|
var cookieContainer = new CookieContainer();
|
||||||
};
|
var handler = new HttpClientHandler
|
||||||
var httpClient = new HttpClientCookieContainer(handler)
|
|
||||||
{
|
|
||||||
BaseAddress = new Uri("https://api.vrchat.cloud/api/1")
|
|
||||||
|
|
||||||
};
|
|
||||||
httpClient.DefaultRequestHeaders.Add("User-Agent", userAgent);
|
|
||||||
|
|
||||||
Console.WriteLine($"Creating API for {account.username}");
|
|
||||||
|
|
||||||
string encodedUsername = HttpUtility.UrlEncode(account.username);
|
|
||||||
string encodedPassword = HttpUtility.UrlEncode(account.password);
|
|
||||||
|
|
||||||
// Create Basic auth string
|
|
||||||
string authString = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{encodedUsername}:{encodedPassword}"));
|
|
||||||
|
|
||||||
// Add basic auth header
|
|
||||||
var request = new HttpRequestMessage(HttpMethod.Get, "/api/1/auth/user");
|
|
||||||
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authString);
|
|
||||||
var authResp = await httpClient.SendAsync(request);
|
|
||||||
if ((await authResp.Content.ReadAsStringAsync()).Contains("totp"))
|
|
||||||
{
|
|
||||||
Console.WriteLine($"TOTP required for {account.username}");
|
|
||||||
if (account.totpSecret == null)
|
|
||||||
{
|
{
|
||||||
Console.WriteLine($"No TOTP secret found for {account.username}");
|
CookieContainer = cookieContainer
|
||||||
return;
|
};
|
||||||
}
|
var httpClient = new HttpClientCookieContainer(handler)
|
||||||
|
{
|
||||||
// totp constructor needs a byte array decoded from the base32 secret
|
BaseAddress = new Uri("https://api.vrchat.cloud/api/1")
|
||||||
var totp = new Totp(Base32Encoding.ToBytes(account.totpSecret.Replace(" ", "")));
|
|
||||||
var code = totp.ComputeTotp();
|
};
|
||||||
if (code == null)
|
httpClient.DefaultRequestHeaders.Add("User-Agent", userAgent);
|
||||||
{
|
|
||||||
Console.WriteLine($"Failed to generate TOTP for {account.username}");
|
Console.WriteLine($"Creating API for {account.username}");
|
||||||
return;
|
|
||||||
}
|
string encodedUsername = HttpUtility.UrlEncode(account.username);
|
||||||
|
string encodedPassword = HttpUtility.UrlEncode(account.password);
|
||||||
var verifyReq = new HttpRequestMessage(HttpMethod.Post, "/api/1/auth/twofactorauth/totp/verify");
|
|
||||||
// set content type
|
// Create Basic auth string
|
||||||
verifyReq.Content = new StringContent($"{{\"code\":\"{code}\"}}", Encoding.UTF8, "application/json");
|
string authString = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{encodedUsername}:{encodedPassword}"));
|
||||||
var verifyResp = await httpClient.SendAsync(verifyReq);
|
|
||||||
var verifyRes = await verifyResp.Content.ReadFromJsonAsync<TotpVerifyResponse>();
|
// Add basic auth header
|
||||||
|
var request = new HttpRequestMessage(HttpMethod.Get, "/api/1/auth/user");
|
||||||
if (verifyRes.verified == false)
|
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authString);
|
||||||
{
|
var authResp = await httpClient.SendAsync(request);
|
||||||
Console.WriteLine($"Failed to verify TOTP for {account.username}");
|
if ((await authResp.Content.ReadAsStringAsync()).Contains("totp"))
|
||||||
return;
|
{
|
||||||
|
Console.WriteLine($"TOTP required for {account.username}");
|
||||||
|
if (account.totpSecret == null)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"No TOTP secret found for {account.username}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// totp constructor needs a byte array decoded from the base32 secret
|
||||||
|
var totp = new Totp(Base32Encoding.ToBytes(account.totpSecret.Replace(" ", "")));
|
||||||
|
var code = totp.ComputeTotp();
|
||||||
|
if (code == null)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Failed to generate TOTP for {account.username}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var verifyReq = new HttpRequestMessage(HttpMethod.Post, "/api/1/auth/twofactorauth/totp/verify");
|
||||||
|
// set content type
|
||||||
|
verifyReq.Content = new StringContent($"{{\"code\":\"{code}\"}}", Encoding.UTF8, "application/json");
|
||||||
|
var verifyResp = await httpClient.SendAsync(verifyReq);
|
||||||
|
var verifyRes = await verifyResp.Content.ReadFromJsonAsync<TotpVerifyResponse>();
|
||||||
|
|
||||||
|
if (verifyRes.verified == false)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Failed to verify TOTP for {account.username}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var curUserResp = await httpClient.GetAsync("/api/1/auth/user");
|
||||||
|
var curUser = await curUserResp.Content.ReadFromJsonAsync<User>();
|
||||||
|
Console.WriteLine($"Logged in as {curUser.displayName}");
|
||||||
|
apiAccounts.Add(httpClient);
|
||||||
}
|
}
|
||||||
|
catch (HttpRequestException e)
|
||||||
var curUserResp = await httpClient.GetAsync("/api/1/auth/user");
|
{
|
||||||
var curUser = await curUserResp.Content.ReadFromJsonAsync<User>();
|
Console.WriteLine($"Failed to create API for {account.username}: {e.Message}, {e.StatusCode}, {e}");
|
||||||
Console.WriteLine($"Logged in as {curUser.displayName}");
|
}
|
||||||
apiAccounts.Add(httpClient);
|
});
|
||||||
} catch (HttpRequestException e)
|
}
|
||||||
{
|
LogInAllAccounts();
|
||||||
Console.WriteLine($"Failed to create API for {account.username}: {e.Message}, {e.StatusCode}, {e}");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapGet("/", () => $"Logged in with {apiAccounts.Count} accounts");
|
app.MapGet("/", () => $"Logged in with {apiAccounts.Count} accounts");
|
||||||
app.MapGet("/rotate", () =>
|
app.MapGet("/rotate", () =>
|
||||||
|
|
@ -172,7 +177,7 @@ app.Use(async (context, next) =>
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
async Task DoRequest(HttpContext context, bool retriedAlready = false)
|
async Task DoRequest(HttpContext context, bool retriedAlready = false, bool reAuthedAlready = false)
|
||||||
{
|
{
|
||||||
if (apiAccounts.Count == 0)
|
if (apiAccounts.Count == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -230,9 +235,16 @@ async Task DoRequest(HttpContext context, bool retriedAlready = false)
|
||||||
{
|
{
|
||||||
if (retriedAlready)
|
if (retriedAlready)
|
||||||
{
|
{
|
||||||
context.Response.StatusCode = 500;
|
if (reAuthedAlready)
|
||||||
Console.Error.WriteLine($"Failed to authenticate: {response.StatusCode}");
|
{
|
||||||
await context.Response.WriteAsync("Failed to authenticate");
|
Console.Error.WriteLine($"Failed to re-authenticate all accounts");
|
||||||
|
context.Response.StatusCode = 500;
|
||||||
|
await context.Response.WriteAsync("Failed to re-authenticate all accounts");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// re-login all accounts and try again
|
||||||
|
LogInAllAccounts();
|
||||||
|
await DoRequest(context, true, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Console.Error.WriteLine($"Retrying request due to {response.StatusCode}");
|
Console.Error.WriteLine($"Retrying request due to {response.StatusCode}");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue