How do I prevent my client token from being exposed to the browser?
Unanswered
Northern Mockingbird posted this in #help-forum
Northern MockingbirdOP
In order to update my sanity content, I placed a 'token' inside the 'createClient' function:
When I patch() an update to Sanity, I get this error on the console:
Visiting that Link I read that a recommendation is
So my attempt at that was to create an /api route in the /app directory:
...and fetch that from within the sanity client
The error I'm getting is:
export const client = createClient({
apiVersion,
dataset,
projectId,
useCdn,
token: process.env.NEXT_PUBLIC_SANITY_TOKEN
});When I patch() an update to Sanity, I get this error on the console:
You have configured Sanity client to use a token in the browser. This may cause unintentional security issues. See https://www.sanity.io/help/js-client-browser-token for more information and how to hide this warning.Visiting that Link I read that a recommendation is
Making the backend fetch the data from the Sanity APIsSo my attempt at that was to create an /api route in the /app directory:
./app/api/sanity/route.js
_____
import { NextResponse } from 'next/server';
export async function GET(req) {
try {
const token = process.env.SANITY_SECRET_TOKEN;
return NextResponse.json(token);
} catch (error) {
console.log(error);
return NextResponse.json({ error: 'Failed to fetch token' });
}
}...and fetch that from within the sanity client
export const client = createClient({
apiVersion,
dataset,
projectId,
useCdn,
token: () => fetch('/api/sanity').then((res) => res.json()),
});The error I'm getting is:
Error: Unauthorized - Session not found35 Replies
Northern MockingbirdOP
One of my components is client-side rendered and calls a function that uses the
client to fetch and patch an updateInteresting.. so if I do that, it will then be safe to have my
token value in the createClient ?@Northern Mockingbird Interesting.. so if I do that, it will then be safe to have my `token` value in the `createClient` ?
yes like this
process.env.SANITY_SECRET_TOKEN without NEXT_PUBLIC_and only use the client on server side
Northern MockingbirdOP
Ok let me give that shot
Actually.. before I do.
This is the function that is being called in my client-side component:
What would that be like in an API route?
I do have an API route for handling revalidation of documents by type...
Would I just handle the
This is the function that is being called in my client-side component:
export async function updateAmountInStock(items) {
items.forEach(async (item) => {
const sanityProduct = await client.fetch(
`*[_type == 'storeItem' && title == "${item.description}"][0]`
);
await client
.patch(sanityProduct._id)
.dec({ amountInStock: item.quantity })
.commit();
});
}What would that be like in an API route?
I do have an API route for handling revalidation of documents by type...
export async function POST(req) {
try {
const { isValidSignature, body } = await parseBody(
req,
process.env.SANITY_REVALIDATE_SECRET
);
if (!isValidSignature) {
const message = 'Invalid signature';
return new Response(JSON.stringify({ message, isValidSignature, body }), {
status: 401,
});
}
if (!body?._type) {
const message = 'Bad Request';
return new Response({ message, body }, { status: 400 });
}
console.log(`${body._type} revalidated`);
revalidateTag(body._type);
return NextResponse.json({ body });
} catch (err) {
console.error(err);
return new Response(err.message, { status: 500 });
}
}Would I just handle the
client login below that second if-statement?if you move it to a file with
'use server' on top, then you can import it and use it on the client componentNorthern MockingbirdOP
I have
updateAmountInStock defined in ./rootDir/lib which is where I put a couple of patch() functionsAh.. hmm
@Northern Mockingbird I have `updateAmountInStock` defined in ./rootDir/lib which is where I put a couple of `patch()` functions
create a
action.ts in your lib folder and put 'use server' on top of the file then export updateAmountInStockNorthern MockingbirdOP
Alright that's clear instructions. Doing this and will test it out
I placed 'use server' at the top of the file exporting that update method and tested it in my app by performing the action that calls it.
Got this error:
Looking into it..
Got this error:
To use Server Actions, please enable the feature flag in your Next.js configLooking into it..
@Northern Mockingbird I placed 'use server' at the top of the file exporting that update method and tested it in my app by performing the action that calls it.
Got this error:
To use Server Actions, please enable the feature flag in your Next.js config
Looking into it..
oh what version of next are you using?
Northern MockingbirdOP
v13.4.19
put this in your
next.config.js/** @type {import('next').NextConfig} */
const config = {
experimental: {
serverActions: true,
},
}
module.exports = configNorthern MockingbirdOP
I think I got it.
Oh you replied first
Oh you replied first
thanks, yeah I had just found that somewhere
I sent the error to you just in case I couldn't find an answer quick. Sorry about that. Under time pressure atm
Northern MockingbirdOP
Interestingly it worked until I removed NEXTPUBLIC from the env variable name of the token.
Simply putting
But removing NEXTPUBLIC is making it throw an error when I try to perform the action in my app.
It's probably fine to keep it right? If the browser warning goes away?
(I could check manually if the key is exposed but I'd have to look into seeing how)
Simply putting
updateAmountInStock as a server action worked, and the browser did not throw the warning telling me my token key is exposed.But removing NEXTPUBLIC is making it throw an error when I try to perform the action in my app.
It's probably fine to keep it right? If the browser warning goes away?
(I could check manually if the key is exposed but I'd have to look into seeing how)
Changed
NEXT_PUBLIC_SANITY_TOKEN to SANITY_SECRET_TOKEN, that isso what is the variable name for the token?
NEXT_PUBLIC_SANITY_TOKEN or SANITY_SECRET_TOKEN?Northern MockingbirdOP
NEXT_PUBLIC_SANITY_TOKEN was it's name originally.I tested what you told me to do in two steps:
1) keep everything the same, just add 'use server' to the update method
2) rename
NEXT_PUBLIC_SANITY_TOKEN to SANITY_SECRET_TOKENI did #1 and then performed the action in my app (it's a cart checkout feature that usually gives me that token exposure warning when I do it). It worked fine and the warning didn't appear.
Then I did #2 but that actually causes the error when I try to do the cart checkout
so you might be using it on client side on cart checkout
NEXTPUBLIC will make the variable available on browser which is not good for your case
Northern MockingbirdOP
I see.. ok. I'll have to do some digging then.
But so far this has been great help and your replies are quick and clear. Thanks man. If I need help I'll message here again if that's fine with you.
But so far this has been great help and your replies are quick and clear. Thanks man. If I need help I'll message here again if that's fine with you.
yes sure. check the code on cart checkout
do the same
updateAmountInStockNorthern MockingbirdOP
Yeah oddly enough it's throwing an error from just navigating to the /cart page (which is not even the page containing the component that called
And it also errors when I go to the /studio
updateAmountInStock)And it also errors when I go to the /studio
what is the error?
Northern MockingbirdOP
Okay! Nevermind! It was erroring because I was still referencing
process.env.SANITY_SECRET_TOKEN somewhereI took care of it. It's working now
Thanks Ray, you're the man
no prob