Tips for correctly implementing an authorize function in TypeScript with NextAuth.js

Trying to implement the Credentials Provider in NextJs ("next": "^12.0.7") and NextAuth ("next-auth": "^4.1.2") using TypeScript has been a challenge. I am encountering difficulties in getting the function to work correctly.

Below is the code snippet from /pages/api/[...nextauth].ts

import NextAuth, {  } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { verifyOTP } from "@/lib/otp";

// Code block here...

export default NextAuth({
  
  // Configuration details...
  
})

Every time I attempt to build this application, I encounter the following error message:

Error message snippet here...

The contents of my .tsconfig file are as follows:

Contents of .tsconfig file goes here...

Answer №1

The function authorize should return an object representing a user or false/null if the credentials are not valid.

The issue with your current logic is that it does not explicitly return false/null when the condition

res.result === "approved"
is false, leading to a type error. To resolve this, you can add a return statement for null after the if block.

authorize: async (credentials, _req) => {
    try {
        const res = await verifyOTP(credentials!.phone, credentials!.otp, credentials?.username);
        if (res.result === "approved") {
            return {
                id: res.user.id,
                email: res.user.email,
                name: res.user.phone,
                token: res.user.token
            };
        }
        return null; // Ensure to include this line to meet the `authorize` typings requirement
    } catch (e: any) {
        //const errorMessage = e.response.data.message;
        //throw new Error(errorMessage);
        return null;
    }
}

Additionally, there is no need to use Promise.resolve()/Promise.reject() around the user object and null, so I have removed those as well.

Answer №3

The current problem persists in the most recent version of NextAuth, which is 4.20.1

To resolve this issue, it is necessary to correct a single type error in the return User interface that specifically requires the ID data to be a string and not a number. This limitation is acceptable since when using this provider, interactions with the database often involve retrieving strings rather than numbers.

CredentialsProvider({
      id: "password",
      name: "Email and Password",
      credentials: {
        email: { label: "Email", type: "text", placeholder: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e983868187a98e84888085c78a8684">[email protected]</a>" },
        password: { label: "Password", type: "password" }
      },
      authorize: async (credentials, req) => {
        const user = { id: '1', name: 'J Smith', email: '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="9eeafbedeadefbe6fff3eef2fbb0fdf1f3">[email protected]</a>' };
        if (user) {
          return user;
        } else {
          return null;
        }
      }
    }),

Ensure that the User object includes an ID value as a string (e.g., from 1 to "1") to resolve the type error. There is no need to modify tsconfig.json for this correction.

Answer №4

Changing the strict mode in my tsconfig.json file from true to false has resolved the issue for me.

Take a look at the visual representation provided below.

Answer №5

To resolve this issue, ensure that the user object returned by the authorize function contains an "id" property with a numeric string value as shown below:

authorize: async (credentials, req) => {
        await connectDB();
        try {
          if (!credentials?.username) {
            return null;
          }
          if (!credentials?.password) {
            return null;
          }
          const user = {
            id: "1",
            username: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1f7d7a737370717a73735f78727e7673317c7072">[email protected]</a>",
            name: "Bello shehu",
          };
          // retrieve user from database
          return user;
        } catch (error) {
          return null;
        }

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

In Production mode, Angular automatically reloads the page every time my data request service is executed to fetch data from the API

The Issue at Hand I have developed an angular application that functions flawlessly on the development server. This application utilizes localStorage to store the user's JWT token, although I am aware that this may not be the most secure method. How ...

Determine whether a response is not received within 8 seconds

One of the methods in my Angular component is responsible for returning data Here is a snippet of that method getRecognitionById() { this.loaderService.show(null, true); forkJoin( this.vendorWebApiService.getRecognitionById(this.executiveCh ...

Error: An unauthorized attempt was made to modify property settings for certain users, which are designated as read-only

Within my Ionic app, there exists a specific page where users have the ability to modify information related to a particular city. What I aim to achieve is for these modifications to only be visible to other users who are also located within the same "City ...

The supabaseClient.auth.session appears to be missing or not recognized as a valid

After recently updating from the v1 version of Supabase to v2, I am encountering an error message that reads "supabaseClient.auth.session is not a function" consistently. Does anyone have any insights into why this might be happening? In the previous Supa ...

Tips for refreshing a React component using incremental changes retrieved from an API

I am developing a unique React application using Next.js and TypeScript, with an api-backed data set in one component that needs to be cached indefinitely. Unlike traditional examples I have found online, my component must: Fetch only the most recent 100 ...

What is the best way to bring in the angular/http module?

Currently, I am creating an application in Visual Studio with the help of gulp and node. Node organizes all dependencies into a folder named node_modules. During the build process, gulp transfers these dependencies to a directory called libs within wwwroo ...

What advantages does using an RxJS Subject have over handling multiple event listeners individually in terms of speed

After investigating a page's slow performance, I identified an angular directive as the root cause. The culprit was a piece of code that registered event listeners on the window keydown event multiple times: @HostListener('window:keydown', ...

Sending data to Dialog Component

While working on implementing the dialog component of material2, I encountered a particular issue: I am aiming to create a versatile dialog for all confirmation messages, allowing developers to input text based on business requirements. However, according ...

Utilizing checkboxes for toggling the visibility of buttons in Angular

I want to dynamically show or hide buttons based on a checkbox. Here is the HTML code I am using: <input class="form-check-input" [(ngModel)]="switchCase" type="checkbox" id="flexSwitchCheckChecked" (change)=" ...

Implementing conditional where clauses in Firestore queries with dynamic parameters

Consider this scenario: I have a dynamic filter list for my product list, and I want to send an HTTPS request to a cloud function based on the selected filters. However, when trying to set multiple conditional where clauses from that request... The multip ...

Getting the parent from a child in Typescript: Best Practices

Querying: In TypeScript, is it possible to retrieve a parent instance from a child instance? I am aware that casting a child into its parent is a method, however, the child's additional properties still exist in the parent, albeit concealed. Check o ...

The process of setting permissions for a webview app to only access a middleware in next.js

Is there a way to restrict access to middleware in Next.js so that only mobile devices can access it? I need to handle certain DOM elements for a webview app, but for desktop web, I want them to go directly to the index page without passing through the mid ...

Vue3 can accept a prop of type String or PropType

In my Vue3 project, I have a component that accepts a prop which can be either a string or an object. Here's how it looks: import { defineComponent } from 'vue' const Component = defineComponent({ props: { book: { type: [String, ...

Utilizing Axios to access the PancakeSwap Pairs API within a NextJs application

Having trouble extracting liquidity data from complex nested PancakeSwap data, encountering undefined values and errors due to mismatched data formats in axios/react const lpPairs = await axios.get('https://api.pancakeswap.info/api/v2/pairs'); ...

Tips for creating a personalized asynchronous Express handler that seamlessly receives specific typed parameters

In my quest to create a unique Express endpoint wrapper, I aim to wrap async functions and handle errors effectively. The current implementation is basic but functional: import type {Request, RequestHandler, Response} from 'express'; type Handle ...

Steer clear of utilizing the "any" type in your Express.js application built with

I have a node/express/typescript method that looks like this: // eslint-disable-next-line export const errorConverter = (err: any, req: any, res: any, next: any) => { let error = err if (!(error instanceof ApiError)) { const statusCode = e ...

React waitforelement fails to work in conjunction with asynchronous calls

I am currently experimenting with a straightforward login form that includes an asynchronous call in React using TypeScript and classes. Here is how my component appears: import * as React from 'react'; import { LoginService } from './servic ...

Issue with Apollo Client - Mutation failing due to undefined property 'data'

When attempting to call a mutation on the client side in Next.js, I encounter an error every time I use the useMutation hook or the client itself, resulting in the following error: Cannot read property 'data' of undefined. See the code snippets b ...

The module "@uploadthing/react" does not contain the exported member "FileWithPath"

'use client' import type { FileWithPath } from '@uploadthing/react' import { useCallback, Dispatch, SetStateAction } from 'react' import { useDropzone } from '@uploadthing/react/hooks' import { generateClientDropzon ...

Using the hash(#) symbol in Vue 3 for routing

Even though I am using createWebHistory, my URL still contains a hash symbol like localhost/#/projects. Am I overlooking something in my code? How can I get rid of the # symbol? router const routes: Array<RouteRecordRaw> = [ { path: " ...