Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 3 additions & 109 deletions modules/bitgo/test/unit/bitgo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import * as nock from 'nock';
import * as should from 'should';
import assert = require('assert');

import { common, generateGPGKeyPair, encryptAndSignText } from '@bitgo/sdk-core';
import { common, generateGPGKeyPair } from '@bitgo/sdk-core';
import { bip32, ECPair } from '@bitgo/utxo-lib';
import * as _ from 'lodash';
import * as BitGoJS from '../../src/index';
Expand Down Expand Up @@ -709,19 +709,12 @@ describe('BitGo Prototype Methods', function () {
.post('/api/auth/v1/session')
.reply(200, async (uri, requestBody) => {
assert(typeof requestBody === 'object');
should.exist(requestBody.publicKey);
should.exist(requestBody.userId);
should.exist(requestBody.passkey);
requestBody.userId.should.equal(userId);
requestBody.passkey.should.equal(passkey);
const encryptedToken = (await encryptAndSignText(
'access_token',
requestBody.publicKey,
keyPair.privateKey
)) as string;

return {
encryptedToken: encryptedToken,
access_token: 'access_token',
user: { username: 'auth-test@bitgo.com' },
};
});
Expand All @@ -732,105 +725,6 @@ describe('BitGo Prototype Methods', function () {
response.access_token.should.equal('access_token');
});

it('should not authenticate with wrong encryption key', async () => {
const keyPair = await generateGPGKeyPair('secp256k1');

nock('https://bitgo.fakeurl')
.persist()
.get('/api/v1/client/constants')
.reply(200, { ttl: 3600, constants: { passkeyBitGoGpgKey: keyPair.publicKey } });
nock('https://bitgo.fakeurl')
.post('/api/auth/v1/session')
.reply(200, async () => {
const keyPair = await generateGPGKeyPair('secp256k1');
const encryptedToken = (await encryptAndSignText(
'access_token',
keyPair.publicKey,
keyPair.privateKey
)) as string;
return {
encryptedToken: encryptedToken,
user: { username: 'auth-test@bitgo.com' },
};
});

const bitgo = TestBitGo.decorate(BitGo, { env: 'mock' });
try {
await bitgo.authenticateWithPasskey(
'{"id": "id", "response": {"authenticatorData": "123", "clientDataJSON": "123", "signature": "123", "userHandle": "123"}}'
);
assert.fail('Expected error not thrown');
} catch (e) {
assert.equal(e.message, 'Error decrypting message: Session key decryption failed.');
}
});

it('should not authenticate with wrong signing key', async () => {
const userId = '123';
const passkey = `{"id": "id", "response": {"authenticatorData": "123", "clientDataJSON": "123", "signature": "123", "userHandle": "${userId}"}}`;
const badKeyPair = await generateGPGKeyPair('secp256k1');
const bitgoKeyPair = await generateGPGKeyPair('secp256k1');

nock('https://bitgo.fakeurl')
.persist()
.get('/api/v1/client/constants')
.reply(200, { ttl: 3600, constants: { passkeyBitGoGpgKey: bitgoKeyPair.publicKey } });

nock('https://bitgo.fakeurl')
.post('/api/auth/v1/session')
.reply(200, async (uri, requestBody) => {
assert(typeof requestBody === 'object');
const encryptedToken = (await encryptAndSignText(
'access_token',
requestBody.publicKey,
badKeyPair.privateKey
)) as string;

return {
encryptedToken: encryptedToken,
user: { username: 'auth-test@bitgo.com' },
};
});

const bitgo = TestBitGo.decorate(BitGo, { env: 'mock' });
try {
await bitgo.authenticateWithPasskey(passkey);
assert.fail('Expected error not thrown');
} catch (e) {
assert(e.message.startsWith('Error decrypting message: Could not find signing key with key ID'));
}
});
it('should throw - missing bitgo public key', async () => {
const userId = '123';
const passkey = `{"id": "id", "response": {"authenticatorData": "123", "clientDataJSON": "123", "signature": "123", "userHandle": "${userId}"}}`;
const keyPair = await generateGPGKeyPair('secp256k1');

nock('https://bitgo.fakeurl').persist().get('/api/v1/client/constants').reply(200, { ttl: 3600, constants: {} });

nock('https://bitgo.fakeurl')
.post('/api/auth/v1/session')
.reply(200, async (uri, requestBody) => {
assert(typeof requestBody === 'object');
const encryptedToken = (await encryptAndSignText(
'access_token',
requestBody.publicKey,
keyPair.privateKey
)) as string;

return {
encryptedToken: encryptedToken,
user: { username: 'auth-test@bitgo.com' },
};
});

const bitgo = TestBitGo.decorate(BitGo, { env: 'mock' });
try {
await bitgo.authenticateWithPasskey(passkey);
assert.fail('Expected error not thrown');
} catch (e) {
assert.equal(e.message, 'Unable to get passkeyBitGoGpgKey');
}
});
it('should throw - invalid userHandle', async () => {
const passkey = `{"id": "id", "response": {"authenticatorData": "123", "clientDataJSON": "123", "signature": "123", "userHandle": 123}}`;
const bitgo = TestBitGo.decorate(BitGo, { env: 'mock' });
Expand Down Expand Up @@ -862,7 +756,7 @@ describe('BitGo Prototype Methods', function () {
assert(e.message.includes('JSON'));
}
});
it('should throw - missing encrypted token', async () => {
it('should throw - missing access token', async () => {
const passkey = `{"id": "id", "response": { "authenticatorData": "123", "clientDataJSON": "123", "signature": "123", "userHandle": "123"}}`;
nock('https://bitgo.fakeurl')
.post('/api/auth/v1/session')
Expand Down
18 changes: 1 addition & 17 deletions modules/sdk-api/src/bitgoAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ import {
IRequestTracer,
makeRandomKey,
sanitizeLegacyPath,
generateGPGKeyPair,
readSignedMessage,
} from '@bitgo/sdk-core';
import * as sjcl from '@bitgo/sjcl';
import * as utxolib from '@bitgo/utxo-lib';
Expand Down Expand Up @@ -958,31 +956,17 @@ export class BitGoAPI implements BitGoBase {
this.validatePasskeyResponse(passkey);
const userId = JSON.parse(passkey).response.userHandle;

const userGpgKey = await generateGPGKeyPair('secp256k1');
const response: superagent.Response = await request.send({
passkey: passkey,
userId: userId,
publicKey: userGpgKey.publicKey,
});
// extract body and user information
const body = response.body;
this._user = body.user;

if (body.access_token) {
this._token = body.access_token;
} else if (body.encryptedToken) {
const constants = await this.fetchConstants();

if (!constants.passkeyBitGoGpgKey) {
throw new Error('Unable to get passkeyBitGoGpgKey');
}

const access_token = await readSignedMessage(
body.encryptedToken,
constants.passkeyBitGoGpgKey,
userGpgKey.privateKey
);
response.body.access_token = access_token;
response.body.access_token = body.access_token;
} else {
throw new Error('Failed to login. Please contact support@bitgo.com');
}
Expand Down
Loading