"Encountered a type error with the authorization from the credentials provider

Challenge

I find myself utilizing a lone CredentialsProvider in next-auth, but grappling with the approach to managing async authorize() alongside a customized user interface.

The portrayal of the user interface within types/next-auth.d.ts reads as follows:

import NextAuth from "next-auth"

declare module "next-auth" {
  interface User {
    id: string
    address: string
    name?: string
  }
}

This outlines the provider specification in [...nextauth].ts:

CredentialsProvider({
  name: "Ethereum",
  credentials: {
    message: {
      label: "Message",
      type: "text",
    },
    signature: {
      label: "Signature",
      type: "text",
    },
  },
  async authorize(credentials) {
    try {
      const nextAuthUrl = process.env.NEXTAUTH_URL
      if (!nextAuthUrl) return null
      if (!credentials) return null

      // [verify the credential here]
      // "message" contains the verified information

      let user = await prisma.user.findUnique({
        where: {
          address: message.address,
        },
      })
      if (!user) {
        user = await prisma.user.create({
          data: {
            address: message.address,
          },
        })
      }

      return {
        id: user.id,
        address: user.address,
        name: user.name
      }
    } catch (e) {
      console.error(e)
      return null
    }
  },
})

The obstacle becomes evident now in the TypeScript error present in the async authorize(credentials)

Type '(credentials: Record<"message" | "signature", string> | undefined) => Promise<{ id: string; address: string; name: string | null; } | null>' is not assignable to type '(credentials: Record<"message" | "signature", string> | undefined, req: Pick<RequestInternal, "body" | "query" | "headers" | "method">) => Awaitable<...>'.
  Type 'Promise<{ id: string; address: string; name: string | null; } | null>' is not assignable to type 'Awaitable<User | null>'.
    Type 'Promise<{ id: string; address: string; name: string | null; } | null>' is not assignable to type 'PromiseLike<User | null>'.
      Types of property 'then' are incompatible.
        Type '<TResult1 = { id: string; address: string; name: string | null; } | null, TResult2 = never>(onfulfilled?: ((value: { id: string; address: string; name: string | null; } | null) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<...>) | ... 1 more ... | unde...' is not assignable to type '<TResult1 = User | null, TResult2 = never>(onfulfilled?: ((value: User | null) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<...>) | null | undefined) => PromiseLike<...>'.
          Types of parameters 'onfulfilled' and 'onfulfilled' are incompatible.
            Types of parameters 'value' and 'value' are incompatible.
              Type '{ id: string; address: string; name: string | null; } | null' is not assignable to type 'User |...

Documentation

Credentials provider

NextAuth with typescript/extend interface

Answer №1

Encountered a similar issue myself. Instead of disabling strict mode in .tsconfig, I opted to handle the object returned by authorize() through parsing...

async authorize(credentials) {
  // ...
  return {
    // ...
  } as any. // <-- Made this change
}

Although not ideal, I find it preferable to compromising strict mode.

This adjustment doesn't compromise type safety for subsequent steps, as the typed usage is upheld within the jwt({user}) callback without issues.

Answer №2

According to information provided on GitHub TypeScript error for the Credentials provider #2701, the current solution for this problem involves changing the tsconfig.json file by setting strict to false ("strict": false). This adjustment is necessary because NextAuth.js was originally developed with "strict": false, but efforts are underway to make it compatible with strict set to true.

Answer №3

Through specifying the return type of the function as a Promise, I successfully resolved the problem.

 async validateUserInput(input, request): Promise<any> {
   //implementation
}

Answer №4

Summary:

The issue I was experiencing was resolved simply by including the id field in the user object.

For example:

import nextAuth from "next-auth/next";
import { AuthOptions } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";

export const authOptions: AuthOptions = {
  providers: [
    CredentialsProvider({
      credentials: {
        email: {},
        password: {},
      },
      async authorize(credentials) {
        const user = { id: "hello", name: "jay", password: "dave" };
        if (!user || !user.password) return null;

        const passwordsMatch = user.password === credentials?.password;

        if (passwordsMatch) return user;
        return null;
      },
    }),
  ],
};

export default nextAuth(authOptions);

I decided to include the id field after reviewing the types of data structures being used.

Here is how the credentials config interface is defined:

export interface CredentialsConfig<
  C extends Record<string, CredentialInput> = Record<string, CredentialInput>
> extends CommonProviderOptions {
  type: "credentials"
  credentials: C
  authorize: (
    credentials: Record<keyof C, string> | undefined,
    req: Pick<RequestInternal, "body" | "query" | "headers" | "method">
  ) => Awaitable<User | null>
}

It is clear that the User object must have an id field based on this definition:

export interface DefaultUser {
  id: string
  name?: string | null
  email?: string | null
  image?: string | null
}

/**
 * The shape of the returned object in the OAuth providers' `profile` callback,
 * available in the `jwt` and `session` callbacks,
 * or the second parameter of the `session` callback, when using a database.
 *
 * [`signIn` callback](https://next-auth.js.org/configuration/callbacks#sign-in-callback) |
 * [`session` callback](https://next-auth.js.org/configuration/callbacks#jwt-callback) |
 * [`jwt` callback](https://next-auth.js.org/configuration/callbacks#jwt-callback) |
 * [`profile` OAuth provider callback](https://next-auth.js.org/configuration/providers#using-a-custom-provider)
 */
export interface User extends DefaultUser {}

Therefore, it is essential to include the id field in the User object.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How to dynamically generate Angular component selectors with variables or loops?

Looking to dynamically generate the Selector Tag in my app.component.html using a variable. Let's say the variable name is: componentVar:string What I want in my app.component.html: <componentVar></componentVar> or <app-componentVar& ...

There seems to be an issue with Material-UI and TypeScript where a parameter of type 'string' does not have an index signature in the type 'ClassNameMap<"container" | "navBar" | "section0">'

My current project is encountering a TS Error stating "(No index signature with a parameter of type 'string' was found on type 'ClassNameMap<"container" | "navBar" | "section0">'.)" The code below is used to assign styles to vari ...

Activate the function only once the display has finished rendering all items from ng-repeat, not just when ng-repeat reaches its last index

Currently, I am generating a list using ng-repeat and each iteration is rendering a component tag with a unique id based on the $index value. The implementation looks like this: <div ng-if="$ctrl.myArr.length > 0" ng-repeat="obj in $ctrl.myArr"> ...

What is the process for creating a unit test case for an Angular service page?

How can I create test cases for the service page using Jasmine? I attempted to write unit tests for the following function. service.page.ts get(): Observable<Array<modelsample>> { const endpoint = "URL" ; return ...

Using TypeScript with Angular-UI Modals

Currently, my goal is to create a modal using angular-ui-bootstrap combined with typescript. To begin, I referenced an example from this link (which originally utilizes jQuery) and proceeded to convert the jQuery code into typescript classes. After succes ...

Identifying the specific @Input that has changed in ngOnChanges

I am currently utilizing Angular 2. At the moment, I have two @input variables named aa and bb. My objective is: When aa changes, perform a specific action. When bb changes, execute a different action. How can I identify which @Input has changed within ...

Next.js is displaying only the compiling and not-found pages, failing to render the app routes

browser consoleEverything seemed to be fine in my Next.js application, but when I turned off my laptop and restarted the application, it displayed compiling / not-found Everything was perfect in my code. ...

When a function is included in an object, it transforms into something other than a function

In my model, it looks like this: export default class UserObject { name: string; id: string; validateInsert() { } } If I interact with the model in this way: const modelUser: UserModel = new UserModel(); modelUser.ID = 1; modelUser ...

Leveraging React Hooks to display a dynamic pie chart by fetching and mapping data from an API

I have a task where I need to fetch data from an API that returns an object containing two numbers and a list structured like this... {2, 1 , []} The project I'm currently working on utilizes 'use-global-hook' for managing state in Redux. T ...

Do you believe this problem with transpilation has been properly reported to babel-jest?

I recently encountered a problem in the jest project regarding babel-jest transpilation. I added some code that appeared to be error-free, but caused transpilation to fail completely. Although the issue seemed related to a Typescript Next project, there a ...

how to verify if a variable exists in TypeScript

Is there a recommended method for verifying if a variable has a value in TypeScript 4.2? My variable may contain a boolean value. I'm thinking that using if(v){} won't suffice as the condition could be disregarded if it's set to false. ...

Typescript: creating index signatures for class properties

Encountering a problem with index signatures while attempting to access static and instantiated class properties dynamically. Despite researching solutions online, I have been unable to resolve the issue. The problem was replicated on a simple class: int ...

Discovering how to display the hidden messages section in the absence of any ongoing chats with the help of angular2

I currently have 2 tabs set up on my page. The active messages tab is functioning perfectly without any issues. However, I am encountering an error with the closed messages tab. If there are no messages in this tab, the system displays an error message w ...

Is there a more efficient method for providing hooks to children in React when using TypeScript?

My component structure looks something like this: Modal ModalTitle ModalBody FormElements MySelect MyTextField MyCheckbox DisplayInfo ModalActions I have a state variable called formVars, and a function named handleAction, ...

Open the JSON file and showcase its contents using Angular

I am attempting to read a JSON file and populate a table with the values. I've experimented with this.http.get('./data/file.json') .map(response => response.json()) .subscribe(result => this.results =result, function(error) ...

On the first load, Next.js retrieves a token from an API and saves it for later use

Currently working on an application with next.js, the challenge lies in retrieving a guest token from an API and storing it in a cookie for use throughout the entire application. My goal is to have this token set in the cookie before any page is loaded. H ...

Tips for fetching individual item information from Firebase real-time database using Angular 9 and displaying it in an HTML format

product.component.ts import { AngularFireDatabase } from '@angular/fire/database'; import { ProductService } from './../product.service'; import { ActivatedRoute } from '@angular/router'; import { Component, OnInit} from &apo ...

A guide on converting TypeScript to JavaScript while utilizing top-level await

Exploring the capabilities of top-level await introduced with TypeScript 3.8 in a NodeJS setting. Here's an example of TypeScript code utilizing this feature: import { getDoctorsPage } from "./utils/axios.provider"; const page = await getDo ...

Activating the microphone device on the MediaStream results in an echo of one's own voice

I am in the process of creating an Angular application that enables two users to have a video call using the Openvidu calling solution. As part of this application, I have implemented a feature that allows users to switch between different cameras or micr ...

The TypeScript error states, "Object does not contain property 'name'."

Can someone help me with this array.map function I'm trying to use: {props.help.map((e, i) => { return <a key={i}>{e.name}</a> })} The {e} object contains keys 'name' and 'href' I keep getting an error message that ...