keybase / keybase-issues

A single repo for managing publicly recognized issues with the keybase client, installer, and website.
902 stars 37 forks source link

How do you login via the API in NodeJS? #3054

Closed aendra-rininsland closed 7 years ago

aendra-rininsland commented 7 years ago

I'm working on an open source implementation of the API that will enable easy use of it, but I'm getting really stuck on the login portion, I get Failure in verify PDPKA5 whenever I try to do so.

Here's my code, be forewarned it's long:


async (params: LoginParams): Promise<LoginResponse> => {
      const { email_or_username, passphrase, login_session, salt: saltHex } = params;
      const N = Math.pow(2, 15);
      const r = 8;
      const p = 1;
      const dkLen = 256;
      const key = new Buffer(passphrase);
      const salt = hex2bin(saltHex);

      try {
        const passphraseStream = await hash(key, { N, r, p }, dkLen, salt);
        const v5 = passphraseStream.slice(192, 224).toString('base64');
        const v4 = passphraseStream.slice(224, 256).toString('base64');
        const users = await api.userLookup({ usernames: email_or_username });
        let kid;
        if (users.status.code === 0 && users.them.length > 0) {
          const me = users.them.find(d => d.basics.username === email_or_username);
          if (me) {
            console.dir(me.public_keys.primary);
            kid = me.public_keys.primary.kid;
          }
        }

        const payload = {
          body: {
            auth: {
              session: login_session,
              nonce: randomBytes(16).toString(),
            },
            key: {
              kid,
              host: 'keybase.io',
              username: email_or_username,
            },
            type: 'auth',
            version: 1,
          },
          ctime: Date.now(),
          expire_in: 157680000,
          tag: 'signature',
        };

        const pdpka4 = new Buffer(
            msgpack.pack(canonicalJson(
              {
                body: {
                  payload,
                  detached: true,
                  hash_type: 10,
                  key: kid,
                  sig: v4,
                  sig_type: 32,
                },
                tag: 514,
                version: 1,
              }
          ))).toString('base64');

        const pdpka5 = new Buffer(
          msgpack.pack(canonicalJson(
            {
              body: {
                payload,
                detached: true,
                hash_type: 10,
                key: kid,
                sig: v5,
                sig_type: 32,
              },
              tag: 514,
              version: 1,
            },
          ))).toString('base64');

        const result = await (await fetch(`${apiBase}/login.json`, {
          method: 'POST',
          headers: {
            Accept: 'application/json',
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            email_or_username,
            pdpka4,
            pdpka5,
          }),
        })).json();
        session = result.session;
        return result;
      } catch (e) {
        throw e;
      }
    }

I'm using:

I've tried to follow the instructions here to the letter, but I still feel like I'm missing something. Any help? Thanks!

aendra-rininsland commented 7 years ago

Apologies, I hadn't noticed your excellent login implementation, keybase-login. I've replaced all of the above with a single call to that and my life is much improved. 😄

maxtaco commented 7 years ago

Ah cool, thanks for reminding me, I had forgotten about it!!