Open davidhedlund opened 6 years ago
Hi @davidhedlund,
I'm afraid I can provide only limited help since I am not currently developing in MediaWiki and have stopped maintaining this project.
I haven't used pywikibot before, but with MediaWiki 1.27.1 I was able to interact with the MediaWiki API using a bot from a Bash command line script. As of 1.27, logins can be facilitated using the clientlogin
action or the login
action (see these docs). If I recall correctly from my time developing my script, the latter conflicted with CASAuth, but the former definitely worked.
If it's possible to configure pywikibot to use clientlogin
rather than login
, that may fix your issue. If you find a solution, please post it here in case others have the same issue.
I can provide this excerpt from my Bash script in case that's helpful. Note that the original script has only been tested on MediaWiki 1.27.1, and this short excerpt hasn't been tested at all.
Good luck to you!
EDIT: If I recall correctly, my bot account was created while I had temporarily disabled CASAuth, so the password salting performed by CASAuth wasn't an issue for me.
#!/bin/bash
######################################################################
## ##
## Global variables ##
## ##
######################################################################
# The user name and, optionally, the password of a wiki account that
# will be used to interact with the wiki through the MediaWiki API.
# User names and passwords are case-sensitive. If the password is left
# blank here, you will be prompted for it when it is needed.
BOTNAME=MyBot # CHANGE THIS AS NEEDED
BOTPASS=
# MediaWiki provides an API for querying the server. We will use it
# to log into the bot account.
WIKIAPI="https://$(hostname).case.edu/w/api.php" # CHANGE THIS AS NEEDED
# Maintaining a login session requires that we store an HTTP cookie
# file.
COOKIE="/tmp/cookie.txt"
# The functions below set and use the following additional global
# variables
BOTISLOGGEDIN=false
######################################################################
## ##
## Function: loginbot ##
## ##
## Logs the bot into the wiki so that it can perform automated ##
## tasks. Prompts for the bot account password if one was not ##
## provided as an argument when the function was called. If ##
## successful, the function saves an HTTP cookie associated with ##
## the login session and updates the BOTISLOGGEDIN global variable. ##
## ##
######################################################################
function loginbot {
local BOTPASS=$1
local RESPONSE
local LOGINTOKEN
local LOGINSTATUS
local WARNING
local ERROR
# If the bot account password is not passed as a function
# argument, ask for it now.
if [ -z "$BOTPASS" ]; then
read -s -r -p "Enter $BOTNAME's password: " BOTPASS
echo
echo
fi
# Delete any old cookie files.
rm -f "$COOKIE"
# Logging into the wiki is a two-step process. This first step
# should result in the receipt of an HTTP cookie (saved to a file
# using -c) and a login token (a random string) that is paired to
# the cookie.
RESPONSE=$(curl -s -c "$COOKIE" $WIKIAPI \
-d "action=query" \
-d "meta=tokens" \
-d "type=login" \
-d "format=json")
LOGINTOKEN=$(echo $RESPONSE | jq '.query.tokens.logintoken | @uri' | tr -d '"')
if [ "$LOGINTOKEN" == "null" ]; then
WARNING=$(echo $RESPONSE | jq '.warnings.tokens | .["*"]' | tr -d '"')
echo >&2 "Login token retrieval failed: $WARNING"
return 1
fi
# The second step for logging in submits the cookie (submitted
# from a file using -b) and login token, along with the username
# and password, and should result in the receipt of a modified
# HTTP cookie (saved to the same file using -c). A valid return
# URL is required to log in but is not used by this script.
RESPONSE=$(curl -s -b "$COOKIE" -c "$COOKIE" $WIKIAPI \
-d "action=clientlogin" \
-d "format=json" \
-d "username=$BOTNAME" \
-d "password=$BOTPASS" \
-d "loginreturnurl=http://localhost" \
-d "logintoken=$LOGINTOKEN")
LOGINSTATUS=$(echo $RESPONSE | jq '.clientlogin.status' | tr -d '"')
if [ "$LOGINSTATUS" == "FAIL" ]; then
ERROR=$(echo $RESPONSE | jq '.clientlogin.message' | tr -d '"')
echo >&2 "Login failed: $ERROR"
return 1
fi
if [ "$LOGINSTATUS" == "PASS" ]; then
echo "Login successful."
BOTISLOGGEDIN=true
return 0
else
echo >&2 "Login failed: Result was expected to be 'PASS' but got '$LOGINSTATUS' instead"
BOTISLOGGEDIN=false
return 1
fi
} # end loginbot
######################################################################
## ##
## Function: retryprompt ##
## ##
## Asks the user if they want to retry some action that failed. ##
## Aborts if they press any key other than 'r'. ##
## ##
######################################################################
function retryprompt {
local PROMPT
read -r -n 1 -p "Press 'r' to retry, or any other key to quit: " PROMPT
echo
if [ "$PROMPT" != "r" ]; then
exit 0
else
echo
fi
} # end retryprompt
######################################################################
## ##
## Main: Functions are actually called here ##
## ##
######################################################################
# Since this script is very powerful, require sudo
if [ "$(whoami)" != "root" ]; then
echo >&2 "Aborted: superuser priveleges needed (rerun with sudo)"
exit 1
fi
# Log into the account
if [ -n "$BOTPASS" ]; then
echo "Attempting bot login using password stored in this script ..."
echo
loginbot "$BOTPASS"
else
loginbot
fi
until $BOTISLOGGEDIN; do
echo
retryprompt
loginbot
done
echo
continueprompt
# DO STUFF WITH YOUR BOT HERE
EDIT: If I recall correctly, my bot account was created while I had temporarily disabled CASAuth, so the password salting performed by CASAuth wasn't an issue for me.
Yes, that was exactly the issue. For a normal user there is no way of knowing the hashed salted 'string' MediaWiki recognizes as the account's main password. Wondering if it is possible that CASAuth integrates with CAS so that 'somehow' the passwords that gets sent to MediaWiki API is verified against CAS, instead of the salted hash.
If it's possible to configure pywikibot to use
clientlogin
rather thanlogin
, that may fix your issue. If you find a solution, please post it here in case others have the same issue.
clientlogin
(https://www.mediawiki.org/wiki/API:Login) is for those that is more 'interactive' pywikibot is more of a bot framework.
I want to confirm that your script works (even if this cannot be used to solve our problem):
With my user account created while CASAuth enabled:
Attempting bot login using password stored in this script ...
Login failed: The supplied credentials could not be authenticated.
Press 'r' to retry, or any other key to quit:
With my user account created with CASAuth temporarily disabled:
Attempting bot login using password stored in this script ...
Login successful.
Cannot login to wiki via MediaWiki API; as a result automated API-based libraries like pywikibot cannot login.
It's theoretically possible to login via API using the hash, but since the MD5 hash is salted the end user has no way of obtaining their own password.
The CASAuth extension is installed in Free Software Directory (aka the Directory). The Free Software Foundation needs pywikibot to occasionally batch upload tens of thousands files to the Directory to sync the wiki with the data provided by the Debian package repository.