Skip to content

RFC: Hooks for the local provider #964

@phoenix-ru

Description

@phoenix-ru

Describe the feature

It is an often requested feature to support hooking into the calls done by NuxtAuth. Common use-cases include:

Less common, but still valid cases:

How would you implement this?

Proposed API

I envision the usage of the new hooks as following

// in nuxt.config.ts
{
  auth: {
    provider: {
      type: 'local',
      hooks: './config/NuxtAuthHooks.ts'
    }
  }
}

// in ./config/NuxtAuthHooks.ts
import { defineHooks } from '#auth'

export default defineHooks({
  async beforeSignInRequest(authState, request) {
    // Read the values
    console.log(authState) // { data, status, lastRefreshedAt, token, refreshToken }
    console.log(request) // { method, body, params, headers }

    // Write the values
    request.headers.set('X-Custom-Header', 'some value')

    // Set the `$fetch` options (to have a very precise control)
    request.onResponse = (fetchResponse => {
      console.log(fetchResponse.response.headers) // access the response headers
    })

    // Run some async work
    await callOtherFunction()

    // Stop the request arbitrarily
    if (!request.body) {
      return false // will throw a generic error
    }

    // Stop the request with a custom error
    if (request.body.password === '42') {
      throw new Error('This is a custom error message')
    }
  },

  async onSignInResponse(authState, response) {
    // Read the values
    console.log(authState) // { data, status, lastRefreshedAt, token, refreshToken }
    console.log(response) // return value of `$fetch.raw`: { _data, headers, /*...*/ }
    const refreshToken = response.headers.get('X-Your-Custom-Header-Token')

    // Set the values
    response._data.token = `Bearer ${response._data.token}` // e.g. format the token

    // Reject the response
    // By returning `false` - will throw a generic error
    if (!response._data.token) {
      return false
    }
    // By explicitly throwing
    if (!refreshToken) {
      throw new Error('Refresh token was not returned')
    }

    // Accept the response
    return {
      token: response._data.token,
      refreshToken, // can skip or set to `undefined` if you don't use it
      session: response._data.user
        // this will be returned from the `signIn` function, `getSession` will not be called
        ? response._data.user 
        // `getSession` will be called afterwards
        : undefined,

      // TODO: Should this be a part of the hook vs a param to `signIn`?
      redirect: 'wip'
    }
  },

  onSignInError(authState, stage, error) {
    console.log(stage) // 'beforeRequest', 'request', 'onResponse' - WIP
  }
})

Additional information

  • Would you be willing to help implement this feature?

Provider

  • AuthJS
  • Local
  • Refresh
  • New Provider

Metadata

Metadata

Assignees

No one assigned

    Labels

    1.xenhancementAn improvement that needs to be addedp2Nice to have

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions