Reputation: 11
I need to add the "profile" property in my section object because in my application I have different personas and I need to do a conditional rendering for each type of user. After obtaining the token through the backend, I make a request to obtain the logged in user's data and thus store the result of this request in the NextAuth.js section, but I cannot add the "profile" property, only obtaining the "name" and properties "email", which are already from NextAuth.js.
src\app\api\auth[...nextauth]\route.ts:
import { Client, createClient } from 'ldapjs'
import { NextAuthOptions } from 'next-auth'
import NextAuth from 'next-auth/next'
import CredentialsProvider from 'next-auth/providers/credentials'
const client: Client = createClient({
url: process.env.ACTIVE_DIRECTORY_URL || ''
})
const handler = NextAuth({
providers: [
CredentialsProvider({
name: 'LDAP',
credentials: {
username: { label: 'username', type: 'text', placeholder: '' },
password: { label: 'Password', type: 'password' }
},
async authorize(credentials) {
if (!credentials?.username || !credentials?.password) {
return null
}
return new Promise((resolve, reject) => {
client.bind(
credentials.username + '@lorem-ipum.net',
credentials.password,
(error) => {
if (error) {
console.error(error)
reject(error)
} else {
resolve({
email: credentials.username,
password: credentials.password
})
}
}
)
})
}
})
],
callbacks: {
async jwt({ token, user, session }) {
if (user) {
const tokenResult = await fetch(
process.env.BACKEND_URL + '/user/login',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
userName: user.email,
password: user.password
}),
cache: 'no-store'
}
).then(async (response) => {
return await response.json()
})
token.accessToken = tokenResult.token
user = await fetch(process.env.BACKEND_URL + '/user/userLogged', {
method: 'GET',
headers: { Authorization: 'Bearer ' + tokenResult.token }
}).then(async (response) => {
return await response.json()
})
}
return { ...token, ...user, ...session }
},
async session({ session, user }) {
return { ...session, ...user }
}
},
pages: {
signIn: '/login'
},
session: {
strategy: 'jwt'
}
} as NextAuthOptions)
export { handler as GET, handler as POST }
@types\next-auth.d.ts:
/* eslint-disable @typescript-eslint/no-unused-vars */
import NextAuth, { DefaultSession } from 'next-auth'
declare module 'next-auth' {
interface Session extends DefaultSession {
user: {
profile: string
}
}
}
src\app\layout.tsx:
import '@radix-ui/themes/styles.css'
import { getServerSession } from 'next-auth'
import './globals.css'
export default async function RootLayout({
login
}: {
login: React.ReactNode
}) {
const session = await getServerSession()
console.log(session?.user)
return (
<html lang="en">
<body>
{session?.user ? (
<>
{/* Here would be the conditional rendering by user type ("profile" property) */}
</>
) : (
login
)}
</body>
</html>
)
}
By just getting the "profile" property in "console.log(session?.user)", I can continue my work without any problems.
Upvotes: 0
Views: 4342
Reputation: 49
If you want to Extend the default interface properties, follow this guide.
By default, TypeScript will merge new interface properties and overwrite existing ones. In this case, the default session user properties will be overwritten, with the new one defined above.
You'll need to declare the type extension for TypeScript to recognize session.user.profile as a valid field.
// @types\next-auth.d.ts
import NextAuth from 'next-auth';
declare module 'next-auth' {
interface Session {
user: {
profile: string;
} & DefaultSession['user'];
}
}
You can also store the profile property to the user by using callbacks. This question can also be helpful for you.
next-auth-extending-user-schema-to-include-new-fields
Upvotes: 2