add passkey tests
This commit is contained in:
@@ -3,9 +3,11 @@
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import fs from 'node:fs';
|
||||
import passkeys from '../../passkeys.js';
|
||||
import speakeasy from 'speakeasy';
|
||||
import superagent from '@cloudron/superagent';
|
||||
import tokens from '../../tokens.js';
|
||||
import webauthnHelper from '../../test/webauthn-helper.js';
|
||||
|
||||
const customAvatarSize = fs.readFileSync('./logo.png').length;
|
||||
|
||||
@@ -305,6 +307,118 @@ describe('Profile API', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('passkey', function () {
|
||||
const origin = `https://${common.dashboardFqdn}`;
|
||||
let authenticator;
|
||||
|
||||
after(async function () {
|
||||
// ensure passkey is cleaned up for subsequent tests
|
||||
await passkeys.delAll();
|
||||
});
|
||||
|
||||
it('no passkey by default', async function () {
|
||||
const response = await superagent.get(`${serverUrl}/api/v1/profile/passkey`)
|
||||
.query({ access_token: user.token });
|
||||
|
||||
expect(response.status).to.equal(200);
|
||||
expect(response.body.passkey).to.be(null);
|
||||
});
|
||||
|
||||
it('fails to get registration options without token', async function () {
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/profile/passkey/register/options`)
|
||||
.send({})
|
||||
.ok(() => true);
|
||||
|
||||
expect(response.status).to.equal(401);
|
||||
});
|
||||
|
||||
it('can get registration options', async function () {
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/profile/passkey/register/options`)
|
||||
.query({ access_token: user.token })
|
||||
.send({});
|
||||
|
||||
expect(response.status).to.equal(200);
|
||||
expect(response.body.challenge).to.be.a('string');
|
||||
expect(response.body.rp).to.be.an(Object);
|
||||
});
|
||||
|
||||
it('can register passkey', async function () {
|
||||
authenticator = webauthnHelper.createVirtualAuthenticator();
|
||||
|
||||
const optionsResponse = await superagent.post(`${serverUrl}/api/v1/profile/passkey/register/options`)
|
||||
.query({ access_token: user.token })
|
||||
.send({});
|
||||
|
||||
const credential = await webauthnHelper.createRegistrationResponse(authenticator, optionsResponse.body, origin);
|
||||
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/profile/passkey/register`)
|
||||
.query({ access_token: user.token })
|
||||
.send({ credential, name: 'Test Passkey' });
|
||||
|
||||
expect(response.status).to.equal(201);
|
||||
expect(response.body.id).to.be.a('string');
|
||||
});
|
||||
|
||||
it('passkey is visible', async function () {
|
||||
const response = await superagent.get(`${serverUrl}/api/v1/profile/passkey`)
|
||||
.query({ access_token: user.token });
|
||||
|
||||
expect(response.status).to.equal(200);
|
||||
expect(response.body.passkey).to.be.an(Object);
|
||||
expect(response.body.passkey.name).to.be('Test Passkey');
|
||||
expect(response.body.passkey.credentialId).to.be(undefined); // private field stripped
|
||||
});
|
||||
|
||||
it('rejects duplicate registration', async function () {
|
||||
const optionsResponse = await superagent.post(`${serverUrl}/api/v1/profile/passkey/register/options`)
|
||||
.query({ access_token: user.token })
|
||||
.send({})
|
||||
.ok(() => true);
|
||||
|
||||
expect(optionsResponse.status).to.equal(409);
|
||||
});
|
||||
|
||||
it('fails to register without credential', async function () {
|
||||
// use owner who has no passkey
|
||||
const optionsResponse = await superagent.post(`${serverUrl}/api/v1/profile/passkey/register/options`)
|
||||
.query({ access_token: owner.token })
|
||||
.send({});
|
||||
expect(optionsResponse.status).to.equal(200);
|
||||
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/profile/passkey/register`)
|
||||
.query({ access_token: owner.token })
|
||||
.send({})
|
||||
.ok(() => true);
|
||||
|
||||
expect(response.status).to.equal(400);
|
||||
});
|
||||
|
||||
it('can disable passkey', async function () {
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/profile/passkey/disable`)
|
||||
.query({ access_token: user.token })
|
||||
.send({ password: user.password });
|
||||
|
||||
expect(response.status).to.equal(204);
|
||||
});
|
||||
|
||||
it('passkey is gone after disable', async function () {
|
||||
const response = await superagent.get(`${serverUrl}/api/v1/profile/passkey`)
|
||||
.query({ access_token: user.token });
|
||||
|
||||
expect(response.status).to.equal(200);
|
||||
expect(response.body.passkey).to.be(null);
|
||||
});
|
||||
|
||||
it('disable fails when no passkey registered', async function () {
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/profile/passkey/disable`)
|
||||
.query({ access_token: user.token })
|
||||
.send({ password: user.password })
|
||||
.ok(() => true);
|
||||
|
||||
expect(response.status).to.equal(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('avatar', function () {
|
||||
let customAvatarSize = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user