JWT Tokens (Session Management)
Verify JWT tokens issued by user wallet apps for API authentication.
Overview
While Cashu tokens are used for tickets and transferable access, JWT tokens are for:
- API authentication (user's wallet issues the token, you verify it)
- Session management
- Short-lived access tokens
- Stateless authentication
Important: In most cases, JWT tokens are issued by the user's wallet app and verified by your business. You don't typically issue JWTs yourself - the user's wallet does this after authentication.
Primary Use Case: Verifying JWT Tokens
The main use of JWT tokens in Portal is verification. After a user authenticates through their wallet app, they receive a JWT token from their wallet. Your business then verifies this token to authenticate API requests.
Verifying JWT Tokens
const publicKey = 'your-service-public-key';
const token = 'jwt-token-from-user';
try {
const claims = await client.verifyJwt(publicKey, token);
console.log('Token is valid for user:', claims.target_key);
// Grant access
} catch (error) {
console.error('Invalid or expired token');
// Deny access
}
Advanced: Issuing JWT Tokens (Less Common)
In some cases, you may want to issue JWT tokens yourself (e.g., for service-to-service authentication):
const targetPubkey = 'user-public-key';
const durationHours = 24; // Token valid for 24 hours
const jwtToken = await client.issueJwt(targetPubkey, durationHours);
console.log('JWT:', jwtToken);
However, in most authentication flows, the user's wallet app will issue the JWT token after they approve the authentication request.
API Authentication Middleware
async function authenticateRequest(req, res, next) {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return res.status(401).json({ error: 'No token provided' });
}
const token = authHeader.substring(7);
try {
const claims = await portalClient.verifyJwt(
process.env.SERVICE_PUBKEY,
token
);
req.userPubkey = claims.target_key;
next();
} catch (error) {
return res.status(401).json({ error: 'Invalid token' });
}
}
// Protected route
app.get('/api/user/data', authenticateRequest, (req, res) => {
res.json({ userPubkey: req.userPubkey, data: '...' });
});
Typical Authentication Flow with JWTs
- User initiates authentication through your app
- User's Nostr wallet app generates and signs a JWT
- JWT is sent to your application
- Your application verifies the JWT using Portal
- Grant API access based on verified identity
Best Practices
- Verify, don't issue: Let user wallets issue tokens, you just verify them
- Check expiration: Validate JWT expiration times
- Secure transmission: Always use HTTPS
- Don't log tokens: Never log tokens in production
- Use for APIs: Perfect for stateless API authentication
Next: Relay Management