When setting up authentication with Auth.js
and the next.js
framework, my auth.ts file is structured as follows:
import { Client } from 'ldapts';
import NextAuth, { type DefaultSession, type User } from 'next-auth';
import Credentials from 'next-auth/providers/credentials';
import { authConfig } from './auth.config';
import z from 'zod';
const CredentialsSchema = z.object({
username: z.string().regex(/^\d+$/, 'Username must only contain digits'),
password: z
.string()
.min(6, 'Password must be at least 6 characters long'),
});
declare module 'next-auth' {
interface Session {
user: {
username: string;
displayName: string;
memberOf: string[];
} & DefaultSession['user'];
}
interface User {
username: string;
displayName: string | string[] | Buffer | Buffer[];
memberOf: string | string[] | Buffer | Buffer[];
mail: string | string[] | Buffer | Buffer[];
}
}
export const { auth, signIn, signOut } = NextAuth({
...authConfig,
providers: [
Credentials({
name: 'LDAP',
credentials: {
username: { label: 'Username/DN', type: 'text', placeholder: '' },
displayName: {},
memberOf: {},
mail: {},
},
authorize: async (credentials) => {
const result = CredentialsSchema.safeParse(credentials);
if (!result.success) {
console.log(result.error.errors);
return null;
}
const { username, password } = result.data;
const ldapUrl =
process.env.LDAP_URI || 'ldaps://server.com.es:3269';
const client = new Client({
url: ldapUrl,
});
try {
await client.bind(
`CN=${username}`,
password,
);
const extraInfo = await client.search(
`CN=${username},DC=InfoDir,DC=Prod`,
{ attributes: ['cn', 'dn', 'displayName', 'memberOf', 'mail'] },
);
const { cn, dn, displayName, memberOf, mail } =
extraInfo?.searchEntries?.[0] || {};
const user: User = {
username: username,
displayName: displayName,
memberOf: memberOf,
mail: mail,
};
return user;
} catch (error) {
console.log('LDAP failed', error);
return null;
} finally {
await client.unbind();
}
},
}),
],
callbacks: {
async jwt({ token, user }) {
if (user) {
token.username = user.username;
token.displayName = user.displayName;
token.memberOf = user.memberOf;
token.email = user.email;
}
return token;
},
async session({ session, token, user }) {
return {
...session,
user: {
...session.user,
username: user.username,
displayName: user.displayName,
memberOf: user.memberOf,
},
};
},
},
});
However, I am experiencing issues during the authentication process. The authentication goes through, but an error occurs on the server with the following details:
[auth][error] JWTSessionError: Read more at https://errors.authjs.dev#jwtsessionerror
[auth][cause]: TypeError: Cannot read properties of undefined (reading 'username')
at Object.session (webpack-internal:///(rsc)/./auth.ts:90:36)
...
After making a substitution to 'token', the following error message appears:
Type '...' is not assignable to type '...'. ... Type 'unknown' is not assignable to type 'string | null | undefined'.ts(2322)