I am trying to create a script to login to a private Wiki so that I can make changes. This is the code I created to do this. When I send this login token request I successfully get a login token. However when I use that token and send a request to login I get a result of "Failed" with a reason stating "Unable to continue login. Your session most likely timed out."
The apiUrl is set to the Wikipedia url, but the problem exists on my private wiki as well.
public static class WikiAccess
{
static string apiUrl = "https://en.wikipedia.org/w/api.php";
// I am calling this with a working bot username and password
public static async Task<bool> LoginToWikiAsync(string userName, string password)
{
// Create the request parameters to get a login token
var tokenParameters = new Dictionary<string, string>
{
{ "action", "query" },
{ "format", "json" },
{ "meta", "tokens" },
{ "formatversion", "2" },
{ "type", "login" },
};
// Send the login Token Request
var tokenResponse = await SendMessageToWikiGet(tokenParameters);
JObject tokenJsonResponse = ParseString(tokenResponse);
// this gets the login token
string loginToken = tokenJsonResponse["query"]["tokens"]["logintoken"].Value<string>();
var loginParameters = new Dictionary<string, string>
{
{ "action", "login" },
{ "format", "json" },
{ "lgname", userName },
{ "lgpassword", password },
{ "lgtoken", loginToken },
{ "formatversion", "2" },
};
// Send login request
var loginResponse = await SendMessageToWikiPost(loginParameters);
JObject loginJsonResponse = ParseString(loginResponse);
Debug.Log("Login Result: " + loginJsonResponse);
/*
Login Result: {
"login": {
"result": "Failed",
"reason": "Unable to continue login. Your session most likely timed out."
}
}
*/
string loginResult = loginJsonResponse["login"]["result"].Value<string>();
// The login result returns "Failed"
return loginResult == "Success";
}
static JObject ParseString(string value)
{
try
{
return JObject.Parse(value);
}
catch (Exception ex)
{
Debug.LogError(value);
throw ex;
}
}
public static Task<string> SendMessageToWikiGet(Dictionary<string, string> parameters)
{
// Build the query string and send the request to the url via Get
string url = apiUrl + "?" + BuildQueryString(parameters);
Debug.Log(url);
return SendMessageToUrlGet(url);
}
public static Task<string> SendMessageToWikiPost(Dictionary<string, string> parameters)
{
// Build the query string and send the request to the url via Post
return SendMessageToUrlPost(apiUrl, BuildQueryString(parameters));
}
static WebClient client;
public async static Task<string> SendMessageToUrlPost(string url, string parameters)
{
client ??= new();
client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
var response = await client.UploadStringTaskAsync(url, parameters);
return response;
}
public async static Task<string> SendMessageToUrlGet(string url)
{
client ??= new();
var tokenResponse = await client.DownloadStringTaskAsync(url);
return tokenResponse;
}
static string BuildQueryString(Dictionary<string, string> parameters)
{
StringBuilder queryBuilder = new StringBuilder();
foreach (var parameter in parameters)
{
queryBuilder.Append($"{Uri.EscapeDataString(parameter.Key)}={Uri.EscapeDataString(parameter.Value)}&");
}
string returnValue = queryBuilder.ToString().TrimEnd('&');
//Debug.Log(returnValue);
return returnValue;
}
}
I should be receiving this:
{
"login": {
"result": "Success",
"lguserid": 1,
"lgusername": "UserName"
}
}
but instead I am receiving this:
{
"login": {
"result": "Failed",
"reason": "Unable to continue login. Your session most likely timed out."
}
}
I will get this message no matter what I do. Even if I put in an incorrect user name and password. As best as I can tell this is not actually timing out and something else is happening.
What am I missing here?
I ended up figuring it out. At some point MediaWiki started requiring cookies in order to work properly. So I changed this:
To this:
Now it works just fine!
Edit: Here is the full script with some basic functions and the infrastructure to expand on this if anyone is interested.