@auth/core
Version:
Authentication for the Web.
69 lines (60 loc) • 2.36 kB
text/typescript
import type { InternalOptions, RequestInternal, ResponseInternal, User } from "../../types.js"
import type { Cookie, SessionStore } from "../utils/cookie.js"
import { getLoggedInUser } from "../utils/session.js"
import { assertInternalOptionsWebAuthn, inferWebAuthnOptions, getAuthenticationResponse, getRegistrationResponse } from "../utils/webauthn-utils.js"
/**
* Returns authentication or registration options for a WebAuthn flow
* depending on the parameters provided.
*/
export async function webAuthnOptions(
request: RequestInternal,
options: InternalOptions,
sessionStore: SessionStore,
cookies: Cookie[]
): Promise<ResponseInternal> {
// Return an error if the adapter is missing or if the provider
// is not a webauthn provider.
const narrowOptions = assertInternalOptionsWebAuthn(options)
const { provider } = narrowOptions
// Extract the action from the query parameters
const { action } = (request.query ?? {}) as Record<string, unknown>
// Action must be either "register", "authenticate", or undefined
if (action !== "register" && action !== "authenticate" && typeof action !== "undefined") {
return {
status: 400,
body: { error: "Invalid action" },
cookies,
headers: {
"Content-Type": "application/json"
}
}
}
// Get the user info from the session
const sessionUser = await getLoggedInUser(options, sessionStore)
// Extract user info from request
// If session user exists, we don't need to call getUserInfo
const getUserInfoResponse = sessionUser ? {
user: sessionUser,
exists: true
} : await provider.getUserInfo(options, request)
const userInfo = getUserInfoResponse?.user
// Make a decision on what kind of webauthn options to return
const decision = inferWebAuthnOptions(action, !!sessionUser, getUserInfoResponse)
switch (decision) {
case "authenticate":
return getAuthenticationResponse(narrowOptions, request, userInfo, cookies)
case "register":
if (typeof userInfo?.email === "string") {
return getRegistrationResponse(narrowOptions, request, userInfo as User & { email: string }, cookies)
}
default:
return {
status: 400,
body: { error: "Invalid request" },
cookies,
headers: {
"Content-Type": "application/json"
}
}
}
}