What is the proper way to import all existing Discourse users to intercoin.app from Discourse? Is there some sort of REST endpoint that returns all users with their hashed passwords and salts, among other things? What is the link to the hash algorithm on github? I will have to code on our side, to use the same hash algorithm with the entered password and salt, if our own doesn’t work, in order to let those guys log in. I think #2 is relevant whenever a Discourse user turns on SSO later (like we are) so solving it would help other Discourse users too.
def confirm_password?(password)
return false unless password_hash && salt
self.password_hash == hash_password(password, salt)
end
def hash_password(password, salt)
raise StandardError.new("password is too long") if password.size > User.max_password_length
Pbkdf2.hash_password(password, salt, Rails.configuration.pbkdf2_iterations, Rails.configuration.pbkdf2_algorithm)
end
Excellent! Now what is the HTTP endpoint that I call in order to get all the user info, including password hash and salt?
I imagine that there isn’t one to serve up to the public at large (why make it easier to hack people?) So what can I do? Connect to the MySQL database? Write a Discourse plugin?
I just spoke to our team, and they agree, I’m prepared to pay someone to build a small Discourse plugin that would expose via an endpoint some JSON info about a user, given their email address.
So given an email the plugin will just search user_email table by the mail, then find user_id and grab the user row, and send all the “safe” fields, including the salt.
For extra security, the requests can be signed via HMAC using a shared secret that can be provided to the plugin.
Does anyone want to make this one? Message me or reply here and let me know how to contact you. Hopefully it’s straightforward (a couple SELECTs and a check for HMAC if the secret was set). We’ll read the JSON.
The xorcist library is just a faster string xor, right? What if one of the characters ends up being 0 because ‘a’ was xored with ‘a’ – what happens to that string? Aren’t strings null-terminated?
My goal is to port this to PHP, so anything you can do to help (such as giving me info on how to replicate it in PHP) will be very helpful.
Also what is this line doing? ret.bytes.map { |b| ("0" + b.to_s(16))[-2..-1] }.join("")
$u = hash_hmac('sha256', $password, $salt . pack('N', 1));
$ret = $u = hash_hmac('sha256', $password, $u);
for ($i=2; $i<$iterations; ++$i) {
$u = hash_hmac('sha256', $password, $u);
$ret = ($ret ^ $u);
}
// todo: figure out what RUBY is doing on this last line
Is this close? Can you please fix up this PHP code?
Yes! I was able to create a script that goes through all the Discourse users, and imports them with their passphrase hash into our platform.
Soon, we’ll be able to let anyone who has a Discourse forum add also Events, Videoconferencing, Media, and more, with Discourse living in the “Discuss” tab. You can see the result on https://intercoin.app
Basically turning any Discourse installation into a modern social network a la Facebook. We worked for years on those features and now we want to integrate them tightly with Discourse and Wordpress too. So people can combine Wordpress, Discourse and Qbix and self-host their entire community.
In Qbix, we hash the password on the client at least with sha1(password + userId) before sending it to the server. Even when it’s https. We do it so the server or any MITM NEVER has the password, to re-use it across sites. But, Discourse simply sends the password to the server. So we had to turn off this hashing on the client side. Is it possible to do some iterations of hash_pbkdf2 on the client side, and the rest on the server side? I tried it and it doesn’t seem to line up:
Would it be possible to just use Discourse as an SSO Provider, instead of using our site as the SSO provider? Then hosts of Discourse forums would be even more likely to expand it with Qbix features, since the login would remain exactly the same, and on Discourse’s side. Facebook, Google, and whatever else. Is there any documentation on what kind of information Discourse Connect as an SSO Provider returns to our consumer site? Does it include things like the photo we can download, firstname, lastname, and username at least?
TBH I don’t think Discourse submitting a password over HTTPS is your largest security challenge at this moment.
Sure. I think you get most stuff in the standard user serializer.
But if that’s not enough you can always use the API to grab more information from Discourse.
I would recommend to Discourse to hash things with a salt (userId works) before sending the password over the wire. Why not? It doesn’t have to become incompatible with what you are storing in the database now. Simply do the first 100 iterations in Javascript, then subtract 10 from 64000. You have a custom implementation of it anyway (copied from rails) so you’d just send along an isHashed variable, and if it’s true, then do the “last” 64K-10 steps only.
The user ID is not known before login so that won’t work…
10 iterations are not secure, and 63990 iterations are less secure than 64000 iterations. So although it’s marginal it seems like you are replacing one secure method with two less secure methods and a lot of extra complexity.