Skip to content

RFC: Hooks for the local provider #964

@phoenix-ru

Description

@phoenix-ru

Describe the feature

[Work in Progress]

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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions