We recently launched Maiden Desmodus on Kongregate and part of converting the client for their site involved integrating their user authentication with our own account system. This was a fairly simple process, but I’ll outline the steps I took here in case it proves useful to anyone else.
When users connect to Maiden Desmodus for the first time, either using our web client or via telnet they are first prompted to create an account. They specify a name, password and (optionally) an email address. They can then go on to create a character and join the game. The account name and password are required to login each time they access the game. Kongregate however require that users are able to play the games on their site without having to create an additional account, so we needed to integrate the two systems.
Client Changes
I won’t cover loading the Kongregate API as it’s well covered in their own docs and I didn’t do much more than copy and paste. In order to bypass the usual login the client sends a string built from the kongregate username and authentication token as soon as a connection is established and the api has loaded.
username = kongregate.services.getUsername();
authtoken = kongregate.services.getGameAuthToken();
send("kongregate." + username + "." + authtoken);
If it’s a guest user we need them to login to Kongregate before we can log them into the server so we change the “play now” button on the client to a “login or register” button and have that bring up the Kongregate sigin box.
if (kongregate.services.isGuest()) {
// add sign in text and button to intro screen
playBtn.label = "Sign in or Register";
playBtn.visible = true;
}
// called when button is clicked kongregate.services.showSignInBox();
All we need to do then is add an event to handle the login once they complete the signin box, and again this is covered in the Kongregate docs.
private function onKongregateInPageLogin(event:Event):void {
// Get the user's new login credentials
username = kongregate.services.getUsername();
authtoken = kongregate.services.getGameAuthToken();
send("kongregate." + username + "." + authtoken);
}
Server Changes
In our new connection handler we need some way to receive the username and authentication token from the client and then validate it with the Kongregate server.
if arg.startswith('kongregate'):
args = arg.split('.')
username = args[1]
authtoken = args[2]
if username == 'Guest':
sock.send('Please login with your Kongregate username and password.')
return
auth = kong.authenticate(username, authtoken)
The Kongregate server exposes several http services which return JSON strings so it’s quite easy for our Python server to talk to it using the simplejson library.
KEY = 'this-is-your-game-api-key'
AUTH_URL = 'http://www.kongregate.com/api/authenticate.json'
def authenticate(user, auth):
args = {
'username': user,
'game_auth_token': auth,
'api_key': KEY,
}
url = AUTH_URL + '?' + urllib.urlencode(args)
result = simplejson.load(urllib.urlopen(url))
if 'error' in result:
mud.log_string('Kongregate authenticate error: ' + result['error_description'])
return False
else:
return result['success']
Once we have a successful authentication we can check for an existing account and log the user in, or else create a new account for them.
if auth:
# successfully authenticated, check for existing account and login
name = username + '_kong'
if account_exists(name):
# login to an existing account
acct = mudsys.load_account(name)
utils.staff_log("Account '" + acct.name + "' loaded.")
mudsys.attach_account_socket(acct, sock)
else:
# create a new account
The only thing to note in the above code is that we append “_kong” to the username when we create the account on our server. This is to prevent clashes between Kongregate users and any existing users who may have the same account name. The Kongregate docs specify that you should use the ID to authenticate users, but it works fine with the username (both should be unique to each user anyway) and I find that the username is more useful as an account name.
