Here are the flat results of the getchallenge method: (it takes no parameters or auth)
auth_scheme
c0
challenge
c0:1073113200:2831:60:2TCbFBYR72f2jhVDuowz:0fba728f5964ea54160a5b18317d92df
expire_time
1073116091
server_time
1073116031
success
OK
Ignore "auth_scheme = c0" for now. It might be used in the future if we implement other auth schemes or change or auth scheme. In that case we'd add a new capabilities exchange: client would say, "I know c0 and c1". Server would then say, "Use c1, it's the best." But it's just c0 for now, and always will be as long as you don't specify what you know. (if you want to be paranoid, you can make your client check for "c0")
(expire_time - server_time) is how long you have to use that challenge. (currently always 60 seconds) You'll currently get an "invalid password" error if you challenge expires, but we might change that to "challenge stale" in the future. In any case, get the challenge right before you do any other action. Getting a challenge is incredibly fast.
The real meat is "challenge". Don't try to dissect or understand it. It's an opaque cookie. Read the LJ source if you care. (cgi-bin/ljlib.pl, sub get_challenge)
Now, to use it send "user" (flat) or "username" (xml-rpc), then:
key "auth_method" with value "challenge"
key "auth_challenge" with the challenge you got, and:
key "auth_response" of MD5_hex(Challenge + MD5_hex(Password))
Don't send "password" or "hpassword". (that's the whole point).
The challenge can only be used once. You'll get "invalid password" errors if it's used more than once.
This code is live on the test server: http://test.livejournal.org/ It'll be live on the real site in the next day or two, if not sooner.
Enjoy! Any questions?
# Perl Sample Code....
use strict;
use Fcntl;
use XMLRPC::Lite;
use Data::Dumper;
use Digest::MD5 qw(md5_hex);
my $xmlrpc = new XMLRPC::Lite;
$xmlrpc->proxy("http://www.lj.com/interface/xmlrpc");
my $get_chal = xmlrpc_call("LJ.XMLRPC.getchallenge");
my $chal = $get_chal->{'challenge'};
my $user = "brad";
my $pass = "test";
print "chal: $chal\n";
my $response = md5_hex($chal . md5_hex($pass));
my $login = xmlrpc_call('LJ.XMLRPC.login', {
'username' => $user,
'auth_method' => 'challenge',
'auth_challenge' => $chal,
'auth_response' => $response,
});
print Dumper($login);
sub xmlrpc_call {
my ($method, $req) = @_;
my $res = $xmlrpc->call($method, $req);
if ($res->fault) {
print STDERR "Error:\n".
" String: " . $res->faultstring . "\n" .
" Code: " . $res->faultcode . "\n";
exit 1;
}
return $res->result;
}