用户认证返回JWT Token但未存储至数据库问题排查求助
tokens Table in AdonisJS Hey there! Let's break down why your JWT token isn't showing up in the tokens table, and walk through practical fixes tailored to different use cases.
Why This Happens
The core reason: AdonisJS's default JWT authentication is stateless. When you call auth.attempt() with the default jwt guard, it generates a self-contained JWT token that doesn't require database storage. The server validates the token using your app's secret key directly—no database lookup is needed for basic validation. That's exactly why your tokens table stays empty after successful auth.
If you need tokens to persist in the database (for example, to support token revocation later), you have two solid options:
Option 1: Switch to the Database Guard (Auto-Saves Tokens)
This is the simplest way to get tokens stored in the tokens table, as AdonisJS handles all storage logic automatically.
Update your authentication configuration
Openconfig/auth.jsand set the default guard todatabase, then configure the guard details:module.exports = { guard: 'database', // Swap from 'jwt' to 'database' guards: { database: { driver: 'database', provider: { driver: 'lucid', model: 'App/Models/User', }, table: 'tokens', // Link to your existing tokens table expiry: '30d' // Set your preferred token lifespan }, // Keep the jwt guard if you need it for other use cases jwt: { driver: 'jwt', provider: { driver: 'lucid', model: 'App/Models/User', }, secret: Env.get('APP_KEY'), } } }Adjust your
autenticarmethod
With the database guard,auth.attempt()automatically saves the token to thetokenstable. Update your method to use proper error handling and extract the token value:async autenticar({ request, auth }) { const { email, password } = request.all(); const retorno = {}; try { // Database guard handles token storage behind the scenes const token = await auth.attempt(email, password); const user = await User.findBy('email', email); retorno.token = token.token; retorno.user = user.username; retorno.id = user.id; } catch (error) { retorno.data = "E-mail ou senha Incorretos"; } return retorno; }This setup is ideal if you need to revoke tokens later (e.g., when a user logs out), since you can mark tokens as revoked directly in the database.
Option 2: Manually Store JWT Tokens (Keep JWT Guard)
If you want to retain the stateless benefits of JWT but still log tokens to the database, you'll need to manually create records in the tokens table.
Create a Token Model
First, ensure you have aTokenmodel linked to yourtokenstable:// app/Models/Token.js 'use strict' const Model = use('Model') class Token extends Model { user() { return this.belongsTo('App/Models/User') } } module.exports = TokenModify your auth method to save tokens
Update yourautenticarmethod to save the generated JWT to the database after callingauth.attempt():async autenticar({ request, auth }) { const { email, password } = request.all(); const retorno = {}; try { const token = await auth.attempt(email, password); const user = await User.findBy('email', email); // Manually create a token record in the database await user.tokens().create({ token: token.token, type: 'jwt', // Label the token type for clarity is_revoked: false, // Mark as active expiry: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000) // 30-day expiry }) retorno.token = token.token; retorno.user = user.username; retorno.id = user.id; } catch (error) { retorno.data = "E-mail ou senha Incorretos"; } return retorno; }Note: With this approach, you'll need to add custom logic to check if a token is revoked (since JWT itself doesn't track database state). Use this if you just need to log tokens for auditing, not for active revocation.
Final Notes
Pick Option 1 if you need full control over token lifecycle (revocation, expiry checks via database). Choose Option 2 if you want the efficiency of stateless JWT but need to keep a record of issued tokens.
内容的提问来源于stack exchange,提问作者di0n

