"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

An issue encountered with getServerSideProps in NextJS 12 is causing a HttpError stating that cookies are not iterable, leading

Currently, I have an application running smoothly on my localhost. However, when it comes to production, an unexpected error has popped up: Error: HttpError: cookies is not iterable at handleError (/usr/src/.next/server/chunks/6830.js:163:11) at sendReques ...

How to access a component attribute in a JavaScript library method in Angular 8

Within my Angular project, I am utilizing Semantic UI with the code snippet below: componentProperty: boolean = false; ngOnInit() { (<any>$('.ui.dropdown')).dropdown(); (<any>$('.ui.input')).popup({ ...

Can you explain the distinction between employing 'from' and 'of' in switchMap?

Here is my TypeScript code utilizing RxJS: function getParam(val:any):Observable<any> { return from(val).pipe(delay(1000)) } of(1,2,3,4).pipe( switchMap(val => getParam(val)) ).subscribe(val => console.log(val)); ...

Guide on Linking a Variable to $scope in Angular 2

Struggling to find up-to-date Angular 2 syntax is a challenge. So, how can we properly connect variables (whether simple or objects) in Angular now that the concept of controller $scope has evolved? import {Component} from '@angular/core' @Comp ...

Incorporate unique images and titles into shared Facebook links on-the-fly using React JS and Next JS applications

I have been working on my React JS web application that features a dynamic list of articles. I am currently trying to implement a feature that allows users to share the current link, which is the article details page, on Facebook. Despite spending hours ...

Angular: extracting value from forkJoin nested within another observable's pipe

Here is the scenario that needs to be implemented: An API call is made which returns a response containing an array of objects. The objects are then mapped to another array of objects. For each item in this new array, another API call needs to be made. Th ...

Tips for showing the upcoming week in an angular application

Could someone please assist me with displaying the dates for the next 7 days using TypeScript? I am familiar with obtaining the date for the 7th day ahead, but I am unsure on how to generate a list of the 7 consecutive days. ...

Importing modules dynamically in NextJS allows for the loading of

I have a basic function that is responsible for loading a script: const creditCardScript = ( onReadyCB, onErrorCB, ) => { let script = document.createElement("script"); script.type = "text/javascript"; script.src = process.CREDIT_CARD_SCRIPT; ...

Consistentize Column Titles in Uploaded Excel Spreadsheet

I have a friend who takes customer orders, and these customers are required to submit an excel sheet with specific fields such as item, description, brand, quantity, etc. However, the challenge arises when these sheets do not consistently use the same colu ...

Retrieving the <html> tag within an Angular component

In an Angular component, the <body> and <head> tags can be accessed by injecting DOCUMENT as shown below: import { DOCUMENT } from '@angular/common'; import { Inject } from '@angular/core'; export class TestComponent { c ...

Tips for effectively utilizing a Query or QueryTask with local graphics (GraphicsLayer)

Working on developing an ESRI map prototype using Angular4, I have successfully utilized the Draw tool to initiate a Query on a FeatureLayer to draw various graphics such as ConvexHull and Buffer. The primary goal was to create a clear Buffer graphic over ...

Trouble arises from the object data type not being properly acknowledged in TypeScript

In the code snippet provided, I am facing a challenge where I need to pass data to an if block with two different types. These types are handled separately in the if block. How can I make TypeScript understand that the selected object could be either of ty ...

Combine two arrays into one

When attempting to combine two arrays, the result looks like the image linked below: I want the merged array to resemble the following example: {0: {…}, storedArr: Array(2)} 0: address: "ifanio de los Santos Ave, Mandaluyong, 1550 Metro Manila, Phi ...

Is there a way to update the text of a button when it is clicked?

Is there a way to dynamically change the text of a button when it is clicked and revert back to its original text when clicked again? I have attempted something along these lines, but I am unsure how to target the text since there isn't a property si ...

Receive emails: using the require() function with ES Module

After following the react-email documentation, I encountered an error when trying to run the yarn email command: $ email dev --port 3001 ***\node_modules\ora\index.js:65 if (process.platform === 'win32') { ...

Exploring the Material Drawer functionality within an Angular application

I'm having trouble integrating the Material Drawer component into my Angular app. Despite following the instructions on https://material.io/develop/web/components/drawers/, it's not rendering properly. Could someone please provide a detailed, s ...

Having trouble with form validation in React.js? Wondering about the best ways to compare two fields? Let's

It's important to ensure that users enter the same email in both the email and confirmEmail input fields. I've experimented with a few methods, but I'm not certain of the best approach. Is there a simpler way that I might be overlooking? In ...

Guide to displaying the value of a field in an object upon clicking the inline edit button using TypeScript

Is it possible to console log a specific attribute of an object when clicking on the edit button using the code below? Please provide guidance on how to utilize the index to access the value of "name". Refer to the last line in the code with the comment. ...

What is the process of programmatically sorting a column in a Material UI DataGrid?

Hey there! I'm currently working on a DataGrid that has a column with a custom header, specifically a Select option. My goal is to have the column sorted in descending order every time a user selects an option from the dropdown menu. renderHeader: (pa ...

Transforming functions into a new typed object with different function signatures

I am currently updating some React/Redux code that previously followed an older pattern to a more modern "hooks" based approach, using TypeScript. In the old pattern, we utilized "class-based" components and passed their "dispatch" functions using mapDisp ...