summaryrefslogtreecommitdiff
path: root/api
diff options
context:
space:
mode:
authorJoe Carstairs <jcarstairs@scottlogic.com>2024-01-22 17:14:35 +0000
committerJoe Carstairs <jcarstairs@scottlogic.com>2024-01-29 10:51:49 +0000
commit1c5ee8b6f0d22ca9aebdfda88b0ceca8aededbf5 (patch)
tree39a915aa53576ed272f754624819524880962652 /api
parenteac3fb00ef11c08a277dd8f9e2684b79f15193c2 (diff)
Authentication methods are single-responsibility
Diffstat (limited to 'api')
-rw-r--r--api/auth/_generateAuthenticationOptions.ts20
-rw-r--r--api/auth/_verifyAuthenticationResponse.ts39
2 files changed, 10 insertions, 49 deletions
diff --git a/api/auth/_generateAuthenticationOptions.ts b/api/auth/_generateAuthenticationOptions.ts
index 88237ac..e7d37c8 100644
--- a/api/auth/_generateAuthenticationOptions.ts
+++ b/api/auth/_generateAuthenticationOptions.ts
@@ -1,6 +1,7 @@
+import type User from '../types/User';
+
import RELYING_PARTY from './_relyingParty';
import simplewebauthn from '@simplewebauthn/server';
-import getUser from '../db/_getUser';
import getAuthenticators from '../db/_getAuthenticators';
import setCurrentChallenge from '../db/_setCurrentChallenge';
@@ -9,22 +10,11 @@ import setCurrentChallenge from '../db/_setCurrentChallenge';
* authenticate using an authenticator which is already associated with their
* account in the database.
*
- * If a user doesn't currently have an account, they have to create one first,
- * get their account ID and register an authenticator.
- *
* The result should be consumed by \@simplewebauthn/browser's
* `startAuthentication()` method.
*/
-export default async function generateAuthenticationOptions(userId: string) {
- const user = await getUser(userId);
- if (!user) {
- return Promise.reject(`
- Failed to generate authentication options because user with ID ${userId}
- did not exist.
- `);
- }
-
- const userAuthenticators = await getAuthenticators(userId, ['id', 'transports', 'type']);
+export default async function generateAuthenticationOptions(user: User) {
+ const userAuthenticators = await getAuthenticators(user.id, ['id', 'transports', 'type']);
const options = await simplewebauthn.generateAuthenticationOptions({
rpID: RELYING_PARTY.id,
@@ -35,7 +25,5 @@ export default async function generateAuthenticationOptions(userId: string) {
userVerification: 'preferred',
});
- await setCurrentChallenge(userId, options.challenge);
-
return options;
}
diff --git a/api/auth/_verifyAuthenticationResponse.ts b/api/auth/_verifyAuthenticationResponse.ts
index 7ef0e65..c819060 100644
--- a/api/auth/_verifyAuthenticationResponse.ts
+++ b/api/auth/_verifyAuthenticationResponse.ts
@@ -1,44 +1,19 @@
import type Authenticator from '../types/Authenticator';
import type { AuthenticationResponseJSON, AuthenticatorDevice } from '@simplewebauthn/server/script/deps';
-import getCurrentChallenge from '../db/_getCurrentChallenge';
-import getUser from '../db/_getUser';
import simplewebauthn from '@simplewebauthn/server';
import RELYING_PARTY from './_relyingParty';
-import getAuthenticator from '../db/_getAuthenticator';
-import updateAuthenticator from '../db/_updateAuthenticator';
/// Verifies the registration response returned by @simplewebauthn/browser's
-/// startAuthentication() method. Includes checking the provided challenge
-/// matches the most recent challenge for the salient user. If verification is
-/// successful, saves the new authenticator to the database.
+/// startAuthentication() method.
export default async function verifyAuthenticationResponse(
- userId: string,
- authenticatorId: string,
+ authenticator: Pick<Authenticator, 'id' | 'publicKey' | 'counter' | 'transports'>,
authenticationResponse: AuthenticationResponseJSON,
+ expectedChallenge: string,
): Promise<boolean> {
- const user = await getUser(userId);
- if (!user) {
- return Promise.reject(`
- Failed to verify authentication response because user with ID ${userId}
- did not exist.
- `);
- }
-
- const expectedChallenge = await getCurrentChallenge(userId);
- if (!expectedChallenge) {
- return Promise.reject(`
- Failed to verify authentication response because user with ID ${userId}
- did not have any existing challenges in the database.
- `);
- }
-
- const textEncoder = new TextEncoder();
- const fields: (keyof Authenticator)[] = ['id', 'publicKey', 'counter', 'transports'];
- const authenticator = await getAuthenticator(authenticatorId, fields);
const adaptedAuthenticator: AuthenticatorDevice = {
- credentialID: textEncoder.encode(authenticator.id),
- credentialPublicKey: textEncoder.encode(authenticator.publicKey),
+ credentialID: authenticator.id,
+ credentialPublicKey: authenticator.publicKey,
counter: authenticator.counter,
transports: authenticator.transports,
}
@@ -56,6 +31,4 @@ export default async function verifyAuthenticationResponse(
if (!verification.verified) {
return false;
}
-
- updateAuthenticator(authenticator.id, { counter: authenticator.counter + 1 });
-} \ No newline at end of file
+}