Debugging before dbAuth login handler

Hi!

I completed this guide https://redwoodjs.com/docs/how-to/dbauth-passwordless but now that I try and log in I get the incorrectPassword message I set in loginOptions . I found out that the loginOptions.handler() function doesn’t run. Is there a way to debug what happens before it runs? Mainly I would like to see what is the hash computed from the user’s input.

Thank you

@rob any thoughts on how to help @anto?

Hmm, I don’t know where that doc came from…looks like it got merged in 3 months ago, but this is the first time I’ve seen it! I can’t vouch for whether it works or not. If you really want to use that code I’d try contacting the author and see if he can help? brendandonahue (Brendan Donahue) · GitHub

dbAuth does support TouchID/FaceID (aka WebAuthn) out of the box, you just have to say “yes” to that option when setting up the first time. But you still need to first create an account with a username and password (subsequent logins can be done with your fingerprint).

If I was going to write something from scratch I’d probably skip the standard dbAuth flow entirely: it’s really wired up to want to log someone in with a username and password. But, as long as the proper cookie exists, dbAuth will still do whatever is needed to authenticate your request and make sure you’re who you say you are.

I’d do something similar to how the forgot password flow works: you create a unique token on the server and store it in the database in the User model. Email the user a link back to the site, including that token. The link would be an api-side function, not to the web side (which is running in the browser and can’t set the secure cookie we want). Assuming the token is valid, log that person in by setting the cookie (rather than trying to call the login handler in the dbAuth code which, again, assumes a username and password).

Here’s a quick code block that sets the cookie in the response of the function, redirecting the user back to the homepage (I haven’t tested this, but it’s the general idea!):

// api/src/functions/passwordless.js

import { encryptSession } from '@redwoodjs/auth-dbauth-api'
import { db } from 'src/lib/db'

const secureCookie = (user) => {
  const expires = new Date()
  expires.setFullYear(expires.getFullYear() + 1)

  const cookieAttrs = [
    `Expires=${expires.toUTCString()}`,
    'HttpOnly=true',
    'Path=/',
    'SameSite=Strict',
    `Secure=${process.env.NODE_ENV !== 'development'}`,
  ]
  const data = JSON.stringify({ id: user.id })
  const encrypted = encryptSession(data)

  return [`session=${encrypted}`, ...cookieAttrs].join('; ')
}

// this is the function that gets called when the function is loaded
// this would be the link in the email, something like:
// https://example.com/.redwood/functions/passwordless?token=abc123
export const handler = async (event) => {
  const { token } = event.queryStringParameters
  const user = await db.user.findFirst({
    where: { passwordToken: token }
  })

  if (user) {
    return {
      statusCode: 302,
      headers: {
        'Set-Cookie': secureCookie(user),
        Location: '/',
      },
    }
  } else {
    return {
      statusCode: 302,
      headers: {
        Location: '/?error=Token+not+found',
      },
    }
  }
}

If the token isn’t valid then the error query string variable will be available and you can show them the message on the page they’re redirected to. Otherwise, they’re logged in!