Closed fayazara closed 1 week ago
I was thinking if something like below would make sense
get the userName from user session if it exists or check the body later, I am aware the user might not always have user.email this is just a POC
More detailed version here
Another workaround would be passing an email to the body, but this would be quite error prone - any user can hit this endpoint and pass in any email and there's no way for me to validate it in the backend, the email should be picked from the logged in users session
There is the validateUser
function. You can check if the user is logged in with that one. Something like this?
export default defineWebAuthnRegisterEventHandler({
...,
async validateUser(body) {
const { user } = await requireUserSession(event);
return user.email === body.userName;
},
...,
});
Doesn't work, I still get the same error, this is my endpoint
import { z } from "zod";
import { userActions } from "~~/server/services/db/UserActions";
/**
* This endpoint is used to connect a passkey to an existing user.
*/
export default defineWebAuthnRegisterEventHandler({
async validateUser(event) {
const { user } = await requireUserSession(event);
console.log(user.email, body.userName);
return user.email === body.userName;
},
async onSuccess(event, { credential, user }) {
// const { user } = await requireUserSession(event);
// const record = await userActions.linkPasskeyToUser(
// user.id,
// passkeyName,
// credential,
// );
console.log(user);
return { credential };
},
});
I believe its because the EventHandler immidiately checks for the body
What about?
// api route to link a passkey to a authenticated user
export default defineWebAuthnRegisterEventHandler({
// ...,
async validateUser(body) {
const { user } = await requireUserSession(event);
return user.email === body.userName;
},
// ...,
});
Then in your dashboard, once logged in, you send the user.email
in the session:
<script setup lang="ts">
const { register, authenticate } = useWebAuthn({
registerEndpoint: '/api/me/passkeys/register',
})
const { user } = useUserSession()
async function registerPasskey() {
await register({ userName: user.value.email })
.then(fetchUserSession) // refetch the user session
}
</script>
No, this still doesn't work it throws - message : "User Validation Error"
with 400 Bad response
// app/components/App/Settings/PasskeyManager.vue
<template>
<UButton
icon="i-ph-fingerprint"
label="Link Passkey"
size="lg"
color="black"
@click="linkPasskey"
/>
</template>
<script setup>
const { register } = useWebAuthn({
registerEndpoint: "/api/auth/webauthn/link-passkey",
});
const { user } = useUserSession();
async function linkPasskey() {
await register({ userName: user.value.email, displayName: user.value.name });
}
</script>
// server/api/auth/webauthn/link-passkey.js
import { z } from "zod";
export default defineWebAuthnRegisterEventHandler({
async validateUser(body) {
const { user } = await requireUserSession(event);
return user.email === body.userName;
},
async onSuccess(event, { credential, user }) {
console.log(credential, user);
return "Success";
},
});
Trying to figure out whats happening because it's not logging any errors just throws an error
I see that we have
defineWebAuthnRegisterEventHandler
but this is always expecting a userName and when we want to just link an credential to a existing user, its not possible.The above endpoint breaks - it throws
@Gerbuuun is this handled somewhere that I am missing in the docs or can we not do this currently?
I can contribute, just want to make sure if this is not implemented already