Skip to content

Commit

Permalink
Add WebAuthn error
Browse files Browse the repository at this point in the history
  • Loading branch information
pozylon committed Dec 18, 2024
1 parent 950b5e7 commit b351f2a
Show file tree
Hide file tree
Showing 6 changed files with 22 additions and 5 deletions.
2 changes: 2 additions & 0 deletions packages/api/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ export const UserWebAuthnCredentialsNotFoundError = createError(
'User WebAuth Credentials not found',
);

export const WebAuthnDisabledError = createError('WebAuthnDisabledError', 'WebAuthn disabled');

export const UserWeb3AddressNotFoundError = createError(
'UserWeb3AddressNotFoundError',
'Web3 Account not found for User',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { log } from '@unchainedshop/logger';
import { Context } from '../../../context.js';
import { WebAuthnDisabledError } from '../../../errors.js';

export default async function addWebAuthnCredentials(
root: never,
Expand All @@ -15,6 +16,8 @@ export default async function addWebAuthnCredentials(
credentials,
);

if (!webAuthnService) throw new WebAuthnDisabledError();

return modules.users.updateUser(
{ _id: userId },
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default async function createWebAuthnCredentialRequestOptions(
extensionOptions,
);

if (username) {
if (username && options) {
const user = await modules.users.findUserByUsername(username);
options.allowCredentials = user?.services?.webAuthn?.map(({ id, type }) => ({
id,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { log } from '@unchainedshop/logger';
import { Context } from '../../../context.js';
import { WebAuthnDisabledError } from '../../../errors.js';

export default async function loginWithWebAuthn(
root: never,
Expand All @@ -16,12 +17,14 @@ export default async function loginWithWebAuthn(
let user = await context.modules.users.findUserByUsername(username);
if (!user) throw new Error('User not found');

await context.modules.users.webAuthn.verifyCredentialRequest(
const verification = await context.modules.users.webAuthn.verifyCredentialRequest(
user.services?.webAuthn,
user.username,
params.webAuthnPublicKeyCredentials,
);

if (!verification) throw new WebAuthnDisabledError();

user = await context.modules.users.updateHeartbeat(user._id, {
remoteAddress: context.remoteAddress,
remotePort: context.remotePort,
Expand Down
4 changes: 2 additions & 2 deletions packages/api/src/schema/mutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export default [
"""
Create WebAuthn PublicKeyCredentialCreationOptions to use for Registering a new WebAuthn Device
"""
createWebAuthnCredentialCreationOptions(username: String!, extensionOptions: JSON): JSON!
createWebAuthnCredentialCreationOptions(username: String!, extensionOptions: JSON): JSON
"""
Register WebAuthn Credentials for current user
Expand All @@ -90,7 +90,7 @@ export default [
"""
Create WebAuthn PublicKeyCredentialRequestrOptions to use for WebAuthn Login Flow
"""
createWebAuthnCredentialRequestOptions(username: String, extensionOptions: JSON): JSON!
createWebAuthnCredentialRequestOptions(username: String, extensionOptions: JSON): JSON
"""
Creates an alternative cart. If you use this feature, you should use explicit orderId's when using the
Expand Down
11 changes: 10 additions & 1 deletion packages/core-users/src/module/configureUsersWebAuthnModule.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ModuleInput } from '@unchainedshop/mongodb';
import { createLogger } from '@unchainedshop/logger';
import { WebAuthnCredentialsCreationRequestsCollection } from '../db/WebAuthnCredentialsCreationRequestsCollection.js';

import type { PublicKeyCredentialCreationOptions, PublicKeyCredentialRequestOptions } from 'fido2-lib';
export interface UsersWebAuthnModule {
findMDSMetadataForAAGUID: (aaguid: string) => Promise<any>;
Expand Down Expand Up @@ -97,6 +98,8 @@ export const configureUsersWebAuthnModule = async ({
},

createCredentialCreationOptions: async (origin, username, extensionOptions) => {
if (!f2l) return null;

const registrationOptions = await f2l.attestationOptions(extensionOptions);
const challenge = Buffer.from(registrationOptions.challenge).toString('base64');
const { insertedId } = await WebAuthnCredentialsCreationRequests.insertOne({
Expand All @@ -115,6 +118,8 @@ export const configureUsersWebAuthnModule = async ({
},

createCredentialRequestOptions: async (origin, username, extensionOptions) => {
if (!f2l) return null;

const loginOptions = await f2l.assertionOptions(extensionOptions);
const challenge = Buffer.from(loginOptions.challenge).toString('base64');
const { insertedId } = await WebAuthnCredentialsCreationRequests.insertOne({
Expand All @@ -133,6 +138,8 @@ export const configureUsersWebAuthnModule = async ({
},

verifyCredentialCreation: async (username, credentials) => {
if (!f2l) return null;

const request = await WebAuthnCredentialsCreationRequests.findOne(
{
username,
Expand Down Expand Up @@ -180,6 +187,8 @@ export const configureUsersWebAuthnModule = async ({
},

verifyCredentialRequest: async (userPublicKeys, username, credentials) => {
if (!f2l) return null;

const request = await WebAuthnCredentialsCreationRequests.findOne(
{
_id: credentials.requestId,
Expand All @@ -198,7 +207,7 @@ export const configureUsersWebAuthnModule = async ({
return credentials.id === publicCredentials.id;
}) || {};

if (!publicKey) throw new Error('WebAuthn not setup');
if (!publicKey) return null;

const assertionExpectations = {
challenge: request.challenge,
Expand Down

0 comments on commit b351f2a

Please sign in to comment.