It took me a while to understand. The documentation is not very clear.

However, is always good to read it first -> https://next-auth.js.org/providers/credentials

After reading that part…

For NextAuth to work with Signin.js custom pages ( https://next-auth.js.org/configuration/pages ), the following should be added to the API:

//pages/api/auth/[...nextauth].js
...
pages: {
    signIn: '/auth/signin',
    //signOut: '/auth/signout',
    error: '/auth/error', // Error code passed in query string as ?error=
    // verifyRequest: '/auth/verify-request', // (used for check email message)
    // newUser: '/auth/new-user' // New users will be directed here on first sign in (leave the property out if not of interest)
  }
...

At the front, we can create a custom panel with textfields and labels, but the what we would like to focus is the button using Next-Auth:

//pages/auth/signin.js

 import { getProviders} from "next-auth/react"

//Some react form structure... but in the button
...
onClick={async (event) => {
                    const x = signIn("credentials",
                      {
                        redirect: false,
                        username, password,
                        callbackUrl: 'http://localhost:3000'
                      })
                      .then((data) => {
                        console.log("****signin ok: ", data)
                        if (data.error) {
                          console.log("ERRROR: ", data.error)
                        }
                        //Some front logic here...
                      })
                      .catch((error) => {
                        console.log("*****error adminInitiateAuth: ", error)
                        console.log(JSON.stringify(error))
                        //Some front logic here...
                      })
                  }}
...

To respond properly if there is an error, we use rejections.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/reject

The final part of the code In the API…

//pages/api/auth/[...nextauth].js

//Including the authentication provider...
....
CredentialsProvider({
        name: 'Credentials',
        
        credentials: {
            username: { label: "Username", type: "text", placeholder: "jsmith" },
            password: { label: "Password", type: "password" }
        },
        async authorize(credentials, req) {
            try {
                console.debug("****createCredential: ", JSON.stringify(credentials))
                var aws = require('aws-sdk');
aws.config.update({
    region: 'us-east-1',
    credentials: new aws.CognitoIdentityCredentials({
        IdentityPoolId: '???'
    })
});
                var cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider();
                const UserPoolId = process.env.SOMEPOOLID
                const userParams = {
                    "AuthParameters": {
                        "USERNAME": credentials.username,
                        "PASSWORD": credentials.password,
                    },
                    "AuthFlow": "ADMIN_NO_SRP_AUTH",
                    "ClientId": process.env.SOMECLIENTID,
                    UserPoolId
                };
                const errorInit = await cognitoidentityserviceprovider
                    .adminInitiateAuth(userParams).promise()
                    .then((data) => {
                        return null
                    })
                    .catch((error) => {
                        console.error("*****error createCredential adminInitiateAuth: ", error)
                        console.error(JSON.stringify(error))
                        return error
                    })
                if (errorInit) {
                    console.error("*****errorInit: ", errorInit)
                    if (errorInit.code) {
                        return Promise.reject(new Error(
                            errorInit.code
                        ))
                    }
                    return Promise.reject(new Error(
                        "Unknown Error"
                    ))
                }

...
//since we have a valid user... we use the cognitos user information for custom logic

After signing in successfully, we can transfer the info from the user to the session in the callbacks Next-Auth Callbacks ( https://next-auth.js.org/configuration/callbacks ):

async jwt({ token, user, account, profile, isNewUser }) {
      
      if (user) {
        token.enabled = user.Enabled
        console.debug("IFFFFFFFFFFF***********", user)
        const ua = user.UserAttributes
        for (let i = 0; i < ua.length; i++) {
          const att = ua[i];
          token[att.Name] = att.Value
        }
        console.debug("Token after data transfer: ", token)
        // some custom logic here
      }
      return token
    }

CONCLUSION (I hate reading these…):

it works to me