N
Nuxt2mo ago
Spctr

JWT issue

I have a problem with my backend or frontend that I don't have a cookie parameter on prod
3 Replies
kapa.ai
kapa.ai2mo ago
Hi @Spctr. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Based on the information provided in the knowledge sources, I can offer some insights into JWT and cookie issues in Nuxt applications, though the specific details of your production environment are not available. Here are some potential considerations: 1. Cookie Domain Configuration: Ensure that your cookie domain is properly configured for your production environment. In the Session config, you might need to adjust the domain setting:
'domain' => env('SESSION_DOMAIN', 'domain.de'), // for production
'domain' => env('SESSION_DOMAIN', 'domain.de'), // for production
Stack Overflow Post > Laraval Santcum 419 "CSRF token missmatch" error with nuxt Part 1 (https://stackoverflow.com/questions/78543475) 2. CORS and Same-Site Policy: Make sure your CORS settings and Same-Site cookie policy are correctly set for your production environment. The same_site option in your session configuration might need adjustment:
'same_site' => env('SESSION_SAME_SITE', 'lax'),
'same_site' => env('SESSION_SAME_SITE', 'lax'),
Stack Overflow Post > Laraval Santcum 419 "CSRF token missmatch" error with nuxt Part 1 (https://stackoverflow.com/questions/78543475) 3. Server-Side Cookie Handling: If you're setting cookies on the server-side, ensure you're using the correct methods. In Nuxt, you can use setCookie from the h3 package in your API routes:
import { defineEventHandler, setCookie } from "h3";

export default defineEventHandler(async (event) => {
setCookie(event, "name", "value", { maxAge: 60 * 60 * 24 * 7 });
// Your logic here
});
import { defineEventHandler, setCookie } from "h3";

export default defineEventHandler(async (event) => {
setCookie(event, "name", "value", { maxAge: 60 * 60 * 24 * 7 });
// Your logic here
});
Examples (https://h3.unjs.io/examples/handle-cookie) 4. Environment Variables: Double-check that your environment variables are correctly set in your production environment. You can use a .env file in development, but make sure to set the corresponding variables in your production environment:
NITRO_API_TOKEN="your_production_token"
NITRO_API_TOKEN="your_production_token"
Guide > Local development (https://nitro.unjs.io/guide/configuration#local-development) 5. Runtime Config: Ensure you're using useRuntimeConfig correctly in your server routes to access any configuration that might affect your JWT or cookie handling:
export default defineEventHandler(async (event) => {
const config = useRuntimeConfig(event)
// Use config here
})
export default defineEventHandler(async (event) => {
const config = useRuntimeConfig(event)
// Use config here
})
Docs > Guide > Directory-structure > server > Recipes > Runtime Config (https://nuxt.com/docs/guide/directory-structure/server#runtime-config) If none of these suggestions resolve your issue, you may need to provide more specific details about your backend and frontend setup, including any error messages you're seeing, to diagnose the problem further. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@320895029008793600> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Spctr
SpctrOP2mo ago
This are all the steps it takes ... maybe it's a nest issue I made but I don't know login:
// frontend - nuxt3

async login() {
try {
const { $config } = useNuxtApp();
const login = await axios.post(`${$config.public.backendServer}/api/auth/login`, {
username: this.username,
password: this.password,
}, {withCredentials: true});

if (login.status === 200) {
const { access_token } = login.data; // get access token

if (access_token) {
localStorage.setItem('token', access_token); // save token
}
this.$router.push('/dashboard');
}
} catch (error) {
this.errorMessage = translate('error.login');
}
}
// frontend - nuxt3

async login() {
try {
const { $config } = useNuxtApp();
const login = await axios.post(`${$config.public.backendServer}/api/auth/login`, {
username: this.username,
password: this.password,
}, {withCredentials: true});

if (login.status === 200) {
const { access_token } = login.data; // get access token

if (access_token) {
localStorage.setItem('token', access_token); // save token
}
this.$router.push('/dashboard');
}
} catch (error) {
this.errorMessage = translate('error.login');
}
}
// backend nest

@Post('login')
async loginUser(@Body() body: { username: string; password: string }, @Res() res: Response) {
const { username, password } = body;

const account: Account | null = await this.accountsService.findUserByUsername(username);

if (!account) {
return res.status(401).json({ message: 'Invalid credentials' });
}

const passwordMatches: boolean = bcrypt.compareSync(password, account.passwordHash);

if (!passwordMatches) {
return res.status(401).json({ message: 'Invalid credentials' });
}

const jwt: string = this.jwtService.sign({
username: account.username,
role: account.role,
id: account.id
});
res.cookie('dtn_jwt', jwt, {
httpOnly: true,
secure: true,
maxAge: 10 * 60 * 1000
});

return res.status(200).json({ message: 'Login successful', account: account, access_token: jwt }); // ✅ goes here
}
// backend nest

@Post('login')
async loginUser(@Body() body: { username: string; password: string }, @Res() res: Response) {
const { username, password } = body;

const account: Account | null = await this.accountsService.findUserByUsername(username);

if (!account) {
return res.status(401).json({ message: 'Invalid credentials' });
}

const passwordMatches: boolean = bcrypt.compareSync(password, account.passwordHash);

if (!passwordMatches) {
return res.status(401).json({ message: 'Invalid credentials' });
}

const jwt: string = this.jwtService.sign({
username: account.username,
role: account.role,
id: account.id
});
res.cookie('dtn_jwt', jwt, {
httpOnly: true,
secure: true,
maxAge: 10 * 60 * 1000
});

return res.status(200).json({ message: 'Login successful', account: account, access_token: jwt }); // ✅ goes here
}
// frontend - nuxt3 [ /middleware/routeProtection.ts ]

async function isUserAuthenticated(): Promise<any> {
const { user, setUser } = useUserStore();
if (user.value) {
return { user: user.value };
}

try {
const { $config } = useNuxtApp();
// ✅ sends request to the backend [ nest ]
const response = await axios.get(`${$config.public.backendServer}/api/auth/verify`, { withCredentials: true });
user.value = response.data.user;
return { user: response.data.user };
} catch (error) {
return { user: null };
}
}
// frontend - nuxt3 [ /middleware/routeProtection.ts ]

async function isUserAuthenticated(): Promise<any> {
const { user, setUser } = useUserStore();
if (user.value) {
return { user: user.value };
}

try {
const { $config } = useNuxtApp();
// ✅ sends request to the backend [ nest ]
const response = await axios.get(`${$config.public.backendServer}/api/auth/verify`, { withCredentials: true });
user.value = response.data.user;
return { user: response.data.user };
} catch (error) {
return { user: null };
}
}
// backend - nest

@Get('verify')
async verifyToken(@Req() req: Request, @Res() res: Response) {
try {
const token = req.headers.cookie.split('=')[1]; // ❌ finds no .cookie? and goes into catch()
if (!token) {
return res.status(401).json({ message: 'Not authenticated' });
}

const decoded = this.jwtService.verify(token);
const user: Account | null = await this.accountsService.findUserByUsername(decoded.username);

if (!user) {
return res.status(401).json({ message: 'User not found' });
}

return res.status(200).json({ user });
} catch (error) {
return res.status(401).json({ message: 'Invalid token' });
}
}
// backend - nest

@Get('verify')
async verifyToken(@Req() req: Request, @Res() res: Response) {
try {
const token = req.headers.cookie.split('=')[1]; // ❌ finds no .cookie? and goes into catch()
if (!token) {
return res.status(401).json({ message: 'Not authenticated' });
}

const decoded = this.jwtService.verify(token);
const user: Account | null = await this.accountsService.findUserByUsername(decoded.username);

if (!user) {
return res.status(401).json({ message: 'User not found' });
}

return res.status(200).json({ user });
} catch (error) {
return res.status(401).json({ message: 'Invalid token' });
}
}
I've uploaded my project into a Container and now I have the problem that my req.headers looks different then on localhost development.
// prod

{
host: '<url>:4005',
connection: 'keep-alive',
pragma: 'no-cache',
'cache-control': 'no-cache',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36',
accept: 'application/json, text/plain, */*',
origin: 'http://<url>:3005',
referer: 'http://<url>:3005/',
'accept-encoding': 'gzip, deflate',
'accept-language': 'de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7'
}



// localhost

{
host: 'localhost:4000',
connection: 'keep-alive',
pragma: 'no-cache',
'cache-control': 'no-cache',
'sec-ch-ua-platform': '"Windows"',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36',
accept: 'application/json, text/plain, */*',
'sec-ch-ua': '"Chromium";v="130", "Google Chrome";v="130", "Not?A_Brand";v="99"',
'sec-ch-ua-mobile': '?0',
origin: 'http://localhost:3005',
'sec-fetch-site': 'same-site',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
referer: 'http://localhost:3005/',
'accept-encoding': 'gzip, deflate, br, zstd',
'accept-language': 'de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7',
cookie: '<token>'
}
// prod

{
host: '<url>:4005',
connection: 'keep-alive',
pragma: 'no-cache',
'cache-control': 'no-cache',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36',
accept: 'application/json, text/plain, */*',
origin: 'http://<url>:3005',
referer: 'http://<url>:3005/',
'accept-encoding': 'gzip, deflate',
'accept-language': 'de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7'
}



// localhost

{
host: 'localhost:4000',
connection: 'keep-alive',
pragma: 'no-cache',
'cache-control': 'no-cache',
'sec-ch-ua-platform': '"Windows"',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36',
accept: 'application/json, text/plain, */*',
'sec-ch-ua': '"Chromium";v="130", "Google Chrome";v="130", "Not?A_Brand";v="99"',
'sec-ch-ua-mobile': '?0',
origin: 'http://localhost:3005',
'sec-fetch-site': 'same-site',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
referer: 'http://localhost:3005/',
'accept-encoding': 'gzip, deflate, br, zstd',
'accept-language': 'de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7',
cookie: '<token>'
}
Want results from more Discord servers?
Add your server