import NextAuth, { User } from 'next-auth'
import Credentials from 'next-auth/providers/credentials'
import {
InitiateAuthCommand,
InitiateAuthCommandInput,
} from '@aws-sdk/client-cognito-identity-provider'
import { cognitoClient } from './constants/cognito'
import { getSecretHash, getUserAttributes } from './actions/auth-utils'
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [
Credentials({
credentials: {
username: { label: 'Username' },
password: { label: 'Password', type: 'password' },
},
async authorize(
credentials: Partial<Record<'username' | 'password', unknown>>
): Promise<User | null> {
if (!credentials) return null
try {
const secretHash = await getSecretHash(credentials.username as string)
const command = new InitiateAuthCommand({
AuthFlow: 'USER_PASSWORD_AUTH',
ClientId: process.env.COGNITO_CLIENT_ID!,
AuthParameters: {
USERNAME: credentials.username,
PASSWORD: credentials.password,
SECRET_HASH: secretHash,
},
} as InitiateAuthCommandInput)
const response = await cognitoClient.send(command)
if (response.AuthenticationResult) {
const userAttributes = await getUserAttributes(
credentials.username as string
)
return {
id: userAttributes?.sub,
name:
userAttributes?.['cognito:username'] ||
(credentials.username as string),
...userAttributes,
}
} else {
return null
}
} catch (error) {
console.error(error)
return null
}
},
}),
],
pages: {
signIn: '/login',
},
callbacks: {
async session({ session, token }) {
session.user = {
...session.user,
id: token.sub ?? '',
name: token.name ?? '',
}
return session
},
async jwt({ token, account, profile }) {
if (account) {
token.accessToken = account.access_token
}
if (profile) {
token.sub = profile.sub ?? ''
token.username = profile['cognito:username'] ?? ''
}
return token
},
},
debug: process.env.NODE_ENV !== 'production',
})