Add passkey support
This commit is contained in:
+56
-1
@@ -18,7 +18,11 @@ exports = module.exports = {
|
||||
enableTwoFactorAuthentication,
|
||||
disableTwoFactorAuthentication,
|
||||
setNotificationConfig,
|
||||
destroyUserSession
|
||||
destroyUserSession,
|
||||
getPasskey,
|
||||
getPasskeyRegistrationOptions,
|
||||
registerPasskey,
|
||||
deletePasskey
|
||||
};
|
||||
|
||||
const assert = require('node:assert'),
|
||||
@@ -27,6 +31,7 @@ const assert = require('node:assert'),
|
||||
HttpError = require('@cloudron/connect-lastmile').HttpError,
|
||||
HttpSuccess = require('@cloudron/connect-lastmile').HttpSuccess,
|
||||
oidcServer = require('../oidcserver.js'),
|
||||
passkeys = require('../passkeys.js'),
|
||||
safe = require('safetydance'),
|
||||
tokens = require('../tokens.js'),
|
||||
userDirectory = require('../user-directory.js'),
|
||||
@@ -252,3 +257,53 @@ async function destroyUserSession(req, res, next) {
|
||||
|
||||
next(new HttpSuccess(204));
|
||||
}
|
||||
|
||||
async function getPasskey(req, res, next) {
|
||||
assert.strictEqual(typeof req.user, 'object');
|
||||
|
||||
const [error, result] = await safe(passkeys.list(req.user.id));
|
||||
if (error) return next(BoxError.toHttpError(error));
|
||||
|
||||
// Only one passkey per user - return first one or null
|
||||
const passkey = result.length > 0 ? passkeys.removePrivateFields(result[0]) : null;
|
||||
next(new HttpSuccess(200, { passkey }));
|
||||
}
|
||||
|
||||
async function getPasskeyRegistrationOptions(req, res, next) {
|
||||
assert.strictEqual(typeof req.user, 'object');
|
||||
|
||||
const [error, options] = await safe(passkeys.generateRegistrationOptions(req.user));
|
||||
if (error) return next(BoxError.toHttpError(error));
|
||||
|
||||
next(new HttpSuccess(200, options));
|
||||
}
|
||||
|
||||
async function registerPasskey(req, res, next) {
|
||||
assert.strictEqual(typeof req.user, 'object');
|
||||
assert.strictEqual(typeof req.body, 'object');
|
||||
|
||||
if (!req.body.credential || typeof req.body.credential !== 'object') return next(new HttpError(400, 'credential must be an object'));
|
||||
if (req.body.name && typeof req.body.name !== 'string') return next(new HttpError(400, 'name must be a string'));
|
||||
|
||||
const name = req.body.name || 'Passkey';
|
||||
|
||||
const [error, result] = await safe(passkeys.verifyRegistration(req.user, req.body.credential, name));
|
||||
if (error) return next(BoxError.toHttpError(error));
|
||||
|
||||
next(new HttpSuccess(201, { id: result.id }));
|
||||
}
|
||||
|
||||
async function deletePasskey(req, res, next) {
|
||||
assert.strictEqual(typeof req.user, 'object');
|
||||
|
||||
// Get the user's passkey (only one allowed)
|
||||
const [listError, result] = await safe(passkeys.list(req.user.id));
|
||||
if (listError) return next(BoxError.toHttpError(listError));
|
||||
|
||||
if (result.length === 0) return next(new HttpError(404, 'No passkey registered'));
|
||||
|
||||
const [error] = await safe(passkeys.del(result[0].id, req.user.id));
|
||||
if (error) return next(BoxError.toHttpError(error));
|
||||
|
||||
next(new HttpSuccess(204));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user