EXTERNAL API AUTH : Zustand + NextAuth + NextJS 13
Unanswered
Lancashire Heeler posted this in #help-forum
Lancashire HeelerOP
I'm using state manager zustand and fetch inside store.
I failed to find ways to send bearer token when using API outside of NextAuth provider.
How can I it? I tried many solutions in google (callback) but failed.
I failed to find ways to send bearer token when using API outside of NextAuth provider.
How can I it? I tried many solutions in google (callback) but failed.
67 Replies
@Lancashire Heeler I'm using state manager zustand and fetch inside store.
I failed to find ways to send bearer token when using API outside of NextAuth provider.
How can I it? I tried many solutions in google (callback) but failed.
you could pass it to
fetchDatafetchData: async (email:string, token:string) => {}@Ray you could pass it to `fetchData`
ts
fetchData: async (email:string, token:string) => {}
Lancashire HeelerOP
How to get the bearer token in the first place?
@Lancashire Heeler Click to see attachment
getServerSession() on server side or useSession on client sideLancashire HeelerOP
Return empty user:{}
@Lancashire Heeler Click to see attachment
Lancashire HeelerOP
for getServerSession
useSession return >
{"data":{"user":{},"expires":"2024-02-24T08:50:01.891Z"},"status":"authenticated"}Return same empty user
any solutions?
thanks @Ray
When I send fetch directly inside nextjs component in the API I can get user data.
But I want to fetch inside zustand.
@Lancashire Heeler When I send fetch directly inside nextjs component in the API I can get user data.
could you show how do you fetch?
Lancashire HeelerOP
const Header = () => {
const session = useSession();
const seseso = getSession();
const isDesktop = useMediaQuery(
const isMobileLandscape = useMediaQuery(
);
const {fetchData} = useUserInformation();
const [datas, setDatas] = useState({})
useEffect(() => {
// Fetch initial data and set it in the store
// fetchData(data?.user?.getToken());
const test = async () => {
const dynamicData = await fetch('/api/v1/AUTH/global/token')
.then((res) => res.json())
.then((data) => {
setDatas(data);
})
;
}
test();
// eslint-disabl
const session = useSession();
const seseso = getSession();
const isDesktop = useMediaQuery(
(max-width: ${breakpoints.desktop}));const isMobileLandscape = useMediaQuery(
(max-width: ${breakpoints.mobileLandscape}));
const {fetchData} = useUserInformation();
const [datas, setDatas] = useState({})
useEffect(() => {
// Fetch initial data and set it in the store
// fetchData(data?.user?.getToken());
const test = async () => {
const dynamicData = await fetch('/api/v1/AUTH/global/token')
.then((res) => res.json())
.then((data) => {
setDatas(data);
})
;
}
test();
// eslint-disabl
Header.tsx
@Lancashire Heeler const Header = () => {
const session = useSession();
const seseso = getSession();
const isDesktop = useMediaQuery(`(max-width: ${breakpoints.desktop})`);
const isMobileLandscape = useMediaQuery(
`(max-width: ${breakpoints.mobileLandscape})`
);
const {fetchData} = useUserInformation();
const [datas, setDatas] = useState({})
useEffect(() => {
// Fetch initial data and set it in the store
// fetchData(data?.user?.getToken());
const test = async () => {
const dynamicData = await fetch('/api/v1/AUTH/global/token')
.then((res) => res.json())
.then((data) => {
setDatas(data);
})
;
}
test();
// eslint-disabl
if you are fetching on client side, I think
fetchData should work too. Have you tried it?Lancashire HeelerOP
return null sadly
@Lancashire Heeler return null sadly
where does it return null?
the token in route handler?
Lancashire HeelerOP
I'm taking it directly from cookies instead.
Lancashire HeelerOP
Still failed.
@Lancashire Heeler Still failed.
show the codes and errors
@Ray show the codes and errors
Lancashire HeelerOP
This also empty?
Did I installed next-auth wrongly?
@Lancashire Heeler This also empty?
Lancashire HeelerOP
@Lancashire Heeler Did I installed next-auth wrongly?
show the config for next-auth
Lancashire HeelerOP
import NextAuth, { NextAuthOptions } from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import prisma from "@/prisma/client";
import CredentialsProvider from "next-auth/providers/credentials";
import bcrypt from "bcrypt";
declare module "next-auth" {
interface Session {
accessToken?: string;
// Add any other custom properties you need
}
}
export const authOption: NextAuthOptions = {
adapter: PrismaAdapter(prisma),
providers: [
CredentialsProvider({
name: "Credentials",
credentials: {
email: { label: "Email", type: "email", placeholder: "Email" },
password: { label: "Password", type: "password" },
},
async authorize(credentials, req) {
if (!credentials?.email || !credentials?.password) return null;
const user = await prisma.user.findUnique({
where: { email: credentials.email },
});
if (!user) return null;
const passwordMatch = await bcrypt.compare(
credentials.password,
user.hashedPassword!
);
return passwordMatch ? user : null;
},
}),
], session: {
strategy: "jwt",
},
pages: {
signIn: "/auth/signin",
},
secret: process.env.NEXT_AUTH_SECRET,
jwt: {
secret: process.env.NEXT_AUTH_JWT_SECRET
},
callbacks: {
async jwt({ token, account, profile, trigger }) {
// Check if account exists and contains access_token
console.log('token +jwt+ ' + JSON.stringify(token));
console.log('account +jwt+ ' + JSON.stringify(account));
console.log('profile +jwt+ ' + JSON.stringify(profile));
console.log('trigger +jwt+ ' + JSON.stringify(trigger));
if (account?.access_token) {
token.accessToken = account.access_token;
}
return token;
},
async session({ session, token, user }) {
// Expose the access token for API requests
console.log('session -' + JSON.stringify(session));
console.log('token -' + JSON.stringify(session));
console.log('user -' + JSON.stringify(session));
return session;
},
},
};
const handler = NextAuth(authOption);
export { handler as GET, handler as POST };Lancashire HeelerOP
token +jwt+ {"name":"admin","email":"admin@mail.com","picture":null,"sub":"clrqjl2gy0002lfspvwv6ixv8"}
account +jwt+ {"providerAccountId":"clrqjl2gy0002lfspvwv6ixv8","type":"credentials","provider":"credentials"}
profile +jwt+ undefined
trigger +jwt+ "signIn"Lancashire HeelerOP
Hm,... but why it doesnt.
Have you tested on your side?
{
"name": "start-template",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@headlessui/react": "^1.7.17",
"@next-auth/prisma-adapter": "^1.0.7",
"@prisma/client": "^5.5.2",
"bcrypt": "^5.1.1",
"cookie": "^0.6.0",
"eslint-plugin-react-hooks": "^4.6.0",
"flowbite-react": "^0.7.2",
"js-cookie": "^3.0.5",
"next": "13.5.4",
"next-auth": "^4.24.3",
"react": "^18",
"react-countdown": "^2.3.5",
"react-dom": "^18",
"react-icons": "^4.12.0",
"react-toastify": "^9.1.3",
"usehooks-ts": "^2.9.1",
"zod": "^3.22.4",
"zod-validation-error": "^3.0.0",
"zustand": "^4.4.7"
},
"devDependencies": {
"@types/bcrypt": "^5.0.0",
"@types/js-cookie": "^3.0.6",
"@types/node": "^20.8.9",
"@types/react": "^18",
"@types/react-dom": "^18",
"autoprefixer": "^10",
"daisyui": "^4.4.23",
"eslint": "^8",
"eslint-config-next": "13.5.4",
"postcss": "^8",
"prisma": "^5.5.2",
"tailwindcss": "^3",
"ts-node": "^10.9.1",
"typescript": "^5.2.2"
}
}My stack
@Lancashire Heeler Hm,... but why it doesnt.
what is not working?
Lancashire HeelerOP
profile +jwt+ undefined <---
Eh, shoot.
@Lancashire Heeler
token +jwt+ {"name":"admin","email":"admin@mail.com","picture":null,"sub":"clrqjl2gy0002lfspvwv6ixv8"}
account +jwt+ {"providerAccountId":"clrqjl2gy0002lfspvwv6ixv8","type":"credentials","provider":"credentials"}
profile +jwt+ undefined
trigger +jwt+ "signIn"
you were logging in with credential
Lancashire HeelerOP
account +jwt+ {"providerAccountId":"clrqjl2gy0002lfspvwv6ixv8","type":"credentials","provider":"credentials"} <--- but doesn;t have accessToken
How can I achieve that,
@Lancashire Heeler account +jwt+ {"providerAccountId":"clrqjl2gy0002lfspvwv6ixv8","type":"credentials","provider":"credentials"} <--- but doesn;t have accessToken
credential login doesn't have accessToken
what are you trying to do
Lancashire HeelerOP
I see, my bad. pretty new at this.
Alright, so basically.
now, you are logged in,
fetchData should work@Ray now, you are logged in, `fetchData` should work
Lancashire HeelerOP
zustand store fetchdata?
clientside fetching should include your cookies
Lancashire HeelerOP
I'm trying to do POST request inside zustand store, but it seems like the API doesn't recognize the header, If im not mistaken I'll try again.
@Ray clientside fetching should include your cookies
Lancashire HeelerOP
So no need to specifically set the header in fetch right?
or external backend
@Ray is it your route handler?
Lancashire HeelerOP
Sorry, I quite not understand what you're reffering to, but below is where my zustand store located.
Here is the API I wanted to access from the store
@Lancashire Heeler Here is the API I wanted to access from the store
ok so it should send the cookies
Lancashire HeelerOP
@Ray, it's working idk what I did wrong before 🥲
Thanks so much @Ray, may you be blessed by success!
@Lancashire Heeler <@743561772069421169>, it's working idk what I did wrong before 🥲
look like you didn't login
@Ray look like you didn't login
Lancashire HeelerOP
probably!
Thanks