How to generate Authorization header JWT token for custom API endpoint?

I've created operation which generates JWT token which is sent to my chrome extension.
action generateExtensionToken {
fn: import { generateExtensionToken } from "@src/auth/extensionAuth",
entities: [User]
}
...
api improve {
fn: import { improve } from "@src/api/improve",
httpRoute: (POST, "/spellxy/improve"),
auth: true
}
action generateExtensionToken {
fn: import { generateExtensionToken } from "@src/auth/extensionAuth",
entities: [User]
}
...
api improve {
fn: import { improve } from "@src/api/improve",
httpRoute: (POST, "/spellxy/improve"),
auth: true
}
The main goal is to access context.user for my custom API endpoint to verify if the user has a paid plan. I've tried many combinations, using userId, username, and even config.auth.jwtSecret instead of my JWT_SECRET_KEY in env.server, but none of these work with auth:true for api endpoint in a Postman request that includes a generated bearer token.
import jwt from 'jsonwebtoken';
import { HttpError } from 'wasp/server';
import { config } from 'wasp/server';

export const generateExtensionToken = async (args, context) => {
if (!context.user) {
throw new HttpError(401, 'Not authorized');
}

const token = jwt.sign({ userId: context.user.id }, config.auth.jwtSecret, { expiresIn: '1y' });

return { token };
};
import jwt from 'jsonwebtoken';
import { HttpError } from 'wasp/server';
import { config } from 'wasp/server';

export const generateExtensionToken = async (args, context) => {
if (!context.user) {
throw new HttpError(401, 'Not authorized');
}

const token = jwt.sign({ userId: context.user.id }, config.auth.jwtSecret, { expiresIn: '1y' });

return { token };
};
What's the right format to sign a JWT token for it to work with a custom API endpoint to access context.user? EDIT: I used the client-side sessionId for a custom API endpoint; however, some questions still remain
38 Replies
kapa.ai
kapa.ai2d ago
Hi @sion0921. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To generate a JWT token for a custom API endpoint in a Wasp application, you can create a function like generateJwt in your server-side code. This function will handle user authentication and JWT creation. Here's an example of how you might implement this function:
import * as jwt from 'jsonwebtoken';
import { Request, Response } from 'express';

async function authenticateUser(username: string, password: string): Promise<{ isAuthenticated: boolean; userId?: string }> {
// TODO: Implement actual user authentication logic here
// This should fetch the user's ID from the database based on the provided username and password
// For demonstration, assuming authentication is successful and returning a mock user ID
return { isAuthenticated: true, userId: 'user123' };
}

export async function generateJwt(req: Request, res: Response): Promise<void> {
const { username, password } = req.body;
try {
const authResult = await authenticateUser(username, password);
if (!authResult.isAuthenticated) {
res.status(401).json({ error: 'Invalid credentials' });
return;
}

// User payload for JWT
const userPayload = { username, userId: authResult.userId };

// Retrieve the secret key from environment variables
const secretKey = process.env.JWT_SECRET_KEY;

if (!secretKey) {
throw new Error('JWT secret key is missing');
}

// Token options
const options = { expiresIn: '1h' }; // Token expires in 1 hour

// Generate the JWT
const token = jwt.sign(userPayload, secretKey, options);

// Send the JWT back to the client
res.json({ token });
} catch (error) {
console.error('Error generating JWT token:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
import * as jwt from 'jsonwebtoken';
import { Request, Response } from 'express';

async function authenticateUser(username: string, password: string): Promise<{ isAuthenticated: boolean; userId?: string }> {
// TODO: Implement actual user authentication logic here
// This should fetch the user's ID from the database based on the provided username and password
// For demonstration, assuming authentication is successful and returning a mock user ID
return { isAuthenticated: true, userId: 'user123' };
}

export async function generateJwt(req: Request, res: Response): Promise<void> {
const { username, password } = req.body;
try {
const authResult = await authenticateUser(username, password);
if (!authResult.isAuthenticated) {
res.status(401).json({ error: 'Invalid credentials' });
return;
}

// User payload for JWT
const userPayload = { username, userId: authResult.userId };

// Retrieve the secret key from environment variables
const secretKey = process.env.JWT_SECRET_KEY;

if (!secretKey) {
throw new Error('JWT secret key is missing');
}

// Token options
const options = { expiresIn: '1h' }; // Token expires in 1 hour

// Generate the JWT
const token = jwt.sign(userPayload, secretKey, options);

// Send the JWT back to the client
res.json({ token });
} catch (error) {
console.error('Error generating JWT token:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
This function first authenticates the user. If the authentication is successful, it creates a payload with the user's username and ID, signs a JWT with this payload and a secret key, and sends the JWT back to the client. You can then define this function as an API endpoint in your main.wasp file:
api generateJwt {
fn: import { generateJwt } from "@src/server/api/generateJwt.js",
entities: [User],
httpRoute: (POST, "/api/generate-jwt")
}
api generateJwt {
fn: import { generateJwt } from "@src/server/api/generateJwt.js",
entities: [User],
httpRoute: (POST, "/api/generate-jwt")
}
To use this API endpoint, you can send a POST request to /api/generate-jwt with the user's credentials in the request body. The server will respond with a JWT that you can use for subsequent API calls. Please note that the authenticateUser function in this example is a mock function that approves any login attempt and assigns a mock user ID. You should replace this with your actual user authentication logic. Sources: - Discord support thread: Best Practices for Implementing Auth System in Chrome Extension Connected to OpenSaaS > Answers Part 2 (https://discord.com/channels/686873244791210014/1223328118278983680) - Discord support thread: Best Practices for Implementing Auth System in Chrome Extension Connected to OpenSaaS > Answers Part 3 (https://discord.com/channels/686873244791210014/1223328118278983680) ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @sion0921, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
sion0921
sion09212d ago
Kapa, I've updated the original post. Can you regenerate your answer? @kapa.ai I've updated the original post. Can you regenerate your answer?
kapa.ai
kapa.ai2d ago
Let me check the knowledge base for you. One moment! :books: ---------------------- I'm sorry, but I can't provide the help you're looking for. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @sion0921, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
sion0921
sion09212d ago
help? @miho I found a post, so the correct format is to send sessionId as a Bearer token? How long before it expires?
import { getSessionId } from "wasp/client/api";
import { getSessionId } from "wasp/client/api";
Sven
Sven2d ago
is your questoin solved?
sion0921
sion09212d ago
Ill get back to you when I test it**
MEE6
MEE62d ago
Wohooo @sion0921, you just became a Waspeteer level 1!
sion0921
sion09212d ago
@Sven Hell yea! It did work
No description
Sven
Sven2d ago
niceee could you provide me maybe the code snippets on how you just did it? i have been struggling with this for really long
sion0921
sion09212d ago
Sure
Sven
Sven2d ago
goat man 🐐
sion0921
sion09212d ago
@Sven Question, are you working on a chrome extension as well?
Sven
Sven2d ago
yessss
sion0921
sion09212d ago
Aight, then I got ya Basically, whenever a user installs an extension, they must log in to use it
sion0921
sion09212d ago
No description
Want results from more Discord servers?
Add your server