Meteor Authenticate email/password from a different server with bcrypt

Viewed 721

I want to let my meteor users login through a ruby app.

Where I am

  • I have two websites, both on the same domain, both share the same MongoDB.
  • One is a METEOR-app with accounts-password (which uses bcrypt)
  • The other is a RUBY ON RAILS-app which uses devise (which also uses bcrypt) for authentication.
  • On both apps I can register and login, separately.

When I transfer (copy/paste) the encrypted_password from Meteor's "bcrypt" field to Ruby's "encrypted_password" and try to login I get rejected. It does not work vice versa. Then I recreated the kind of salting by the meteor app in my ruby app (SHA-256 plain-password-hashing before they got compared against).

(here is the meteor accounts-password source file (https://github.com/meteor/meteor/blob/oplog-backlog-on-1.0.3.1/packages/accounts-password/password_server.js ))

and this is my Ruby implementation:

class BCryptSHA256Hasher < Hasher
  def initialize
    @algorithm = :bcrypt_sha256
    @cost = 10
    @digest = OpenSSL::Digest::SHA256.new
  end

  def salt
    BCrypt::Engine.generate_salt(@cost)
  end

  def get_password_string(password)
    @digest.digest(password) unless @digest.nil?
  end

  def encode(password, salt)
    password = get_password_string(password)
    hash = BCrypt::Engine.hash_secret(password, salt)
    return hash
  end

  def verify(password, encoded)
    password_digest = get_password_string(password)
    hash = BCrypt::Engine.hash_secret(password_digest, encoded)
    # password = "asdfasdf"
    # encoded  = "$2a$10$FqvtI7zNgmdWJJG1n9JwZewVYrzEn38JIxEGwmMviMsZsrCmYHqWm"
    # hash     = "$2a$10$FqvtI7zNgmdWJJG1n9JwZe22XU1hRDSNtHIrnYve9FbmjjqJCLhZi"
    # constant_time_comparison:
    constant_time_compare(encoded, hash)
  end

  def constant_time_compare(a, b)
    check = a.bytesize ^ b.bytesize
    a.bytes.zip(b.bytes) { |x, y| check |= x ^ y }
    check == 0
  end

end

Here is a valid User-document, which will be used by both servers:

{
  "_id": "g4BPfpavJGGTNgJcE",
  "authentication_token": "iZqmCsYS1Y9Xxh6t22-X",
  "confirmed_at": new Date(1457963598783),
  "createdAt": new Date(1457963456581),
  "current_sign_in_at": new Date(1457966356123),
  "current_sign_in_ip": "127.0.0.1",
  "email": "demo@demo.com",
  "emails": [
    {
      "address": "demo@demo.com",
      "verified": true
    }
  ],
  "encrypted_password": "$2a$10$7/PJw51HgXfzYJWpaBHGj.QoRCTl0E29X0ZYTZPQhLRo69DGi8Xou",
  "failed_attempts": 0,
  "last_sign_in_at": new Date(1457966356123),
  "last_sign_in_ip": "127.0.0.1",
  "profile": {
    "_id": ObjectId("56e6c1e7a54d7595e099da27"),
    "firstName": "asdf",
    "lastName": "asdf"
  },
  "reset_password_sent_at": null,
  "reset_password_token": null,
  "services": {
    "_id": ObjectId("56e6c1e7a54d7595e099da28"),
    "password": {
      "bcrypt": "$2a$10$7/PJw51HgXfzYJWpaBHGj.QoRCTl0E29X0ZYTZPQhLRo69DGi8Xou"
    },
    "resume": {
      "loginTokens": [

      ]
    }
  },
  "sign_in_count": 1,
  "updated_at": new Date(1457966356127),
  "username": "mediatainment"
}
1 Answers
Related