James (unknownj) wrote in lj_dev,

I hope this isn't terribly off-topic, it's certainly development work, relating to LJ, and involves the use of a client of sorts, so I feel it's mostly in-keeping with the spirit of the thing..

I have a site that runs alongside an LJ community, and does.. well.. various things. One such thing is that (in theory) the site maintains a list of mappings from LJ username to "real name", which then goes into the community style itself as an associative array and overrides the usernames in comments and entries and displays the users' actual names.

Now in order to get that to work nicely, along with all the other site features, I need to have some means of authenticating users so as not to allow people to update each other's names, which of course would lead to all kinds of fun and games. I've come up with what I think is a decent way of doing that, but I'd really appreciate feedback on a) whether there's a better way and b) whether or not I'm leaving myself open to massive security holes. Because the site itself effectively works as a client, interacting with LJ itself, this would seem to be an appropriate place to ask.

So the site throws up an input box for your username, a hidden input item that contains a randomly generated key, and a submit button. The user is then pointed to a reply page for an entry within the community (opening in a new window), where there are various layout overrides to give it a very specific look and feel. One of those is that an md5 hash of the key is passed via an argument, and displayed on the page with the instruction "Hey, post this string in the box below and hit submit".

Upon submission, obviously the page then returns the user to the EntryPage view, where rather than rendering comments, the page renders 0x0 images which are actually calls to a PHP file on the server, which have arguments with the comment talkid. When the server encounters a new talkid (having saved all previously seen ones), it then fires off an HTTP GET request to that EntryPage, passing the talkid as an argument, along with another argument that tells the page to just return the posted text, and the user who posted it. This is then stored in a database on the site.

So all this is happening as the EntryPage view loads. Once that's loaded, the user is told to close this window and swap back to the form, where they then hit "submit". Upon submission, the site hashes the key that was in the hidden field, and checks the submitted hash and username against existing hashes and usernames held on file from the post. If there's a match, it gives the browser a cookie, and the user is now authenticated.

So the idea is, since only user X can post that hash in the community, and since only user X can possibly know the unhashed key value, then the person who was served the form must be the same person as the one who posted the comment, ergo authentication. Convoluted, I know, but I'm not sure I know how to do "simple"..

I guess my question is, am I missing a really easy trick here? I've thought pretty hard about it, and I think that it's impossible (within reason) to fake your way through the process, because you'd either have to spoof a comment by the desired user, or reverse-engineer the form based on an alreay-posted comment (in which case you'd have to unhash the md5 crap in the comment). So what you end up with, in theory, is a way to validate that a user of your website who says they're user X on LJ actually is user X.

Or is there a huge security hole that I've missed? Any obvious exploits?

Thanks to anybody who took the time to get through all that, I know it's not necessarily the most logical process in the world, and am always open to suggestions for improvement :o)

All feedback / comments / criticism welcome..
Tags: openid

  • Post a new comment


    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded