W
Wasp-lang•2mo ago
Sven

what are key steps on protecting SaaS endpoint used to retrieve valuable data from a chrome ext.

I am gonna make a chrome extension. I want to use an endpoint from my saas to retrieve valuable data through my chrome extension. Well do you guys have any recommendation on how to 1st of all make an auth system and 2nd of protect my SaaS endpoint such that only users with a subscription can use it. Maybe using slme token.
7 Replies
kapa.ai
kapa.ai•2mo ago
Hi @Sven. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Sure, I can provide some guidance based on the information available in the knowledge sources. 1. Authentication System: You can implement an authentication system that connects your Chrome extension with your SaaS backend. Here's a suggested flow: - Users click on the extension icon and are prompted to log in through a popup if they aren't already authenticated. - Upon logging in, the credentials are sent to your SaaS's authentication API. - The API returns a token upon successful authentication, which the extension then stores securely. - This token is used for subsequent API calls to authenticate the user. You can use JWT (JSON Web Tokens) for this purpose. When the user logs in, generate a JWT key and store it in local storage. This JWT can contain some user ID. On each request to your custom API, send that JWT in the headers. Check it on each request. Here's a sample code for generating JWT:
// generateJwt.ts
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' });
}
}

// generateJwt.ts
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' });
}
}

2. Protecting SaaS Endpoint: To ensure that only users with a subscription can use your SaaS endpoint, you can add a role field to your User entity. In your queries/actions, check the value of that role and based on that make a decision if they should be able to execute that query/action or not. If they are not allowed, you can throw HttpError 403 or something like that. You can check the open-saas template (https://opensaas.sh/) for an example of this. 3. Securing Communication: As long as you're using HTTPS, the communication between the Chrome extension and the SaaS backend is as secure as it reasonably needs to be. Please note that these are general recommendations and you might need to adjust them based on your specific use case and requirements. Sources: Discord Support Thread (https://discord.com/channels/686873244791210014/1223328118278983680), [Discord Support Thread](https://discord.com/channels/686873244791210014/121173 ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @Sven, 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?
Sven
Sven•2mo ago
Sure, I can provide some guidance based on the information available in the knowledge sources. Authentication System: You can implement an authentication system that connects your Chrome extension with your SaaS backend. Here's a suggested flow:
Users click on the extension icon and are prompted to log in through a popup if they aren't already authenticated. Upon logging in, the credentials are sent to your SaaS's authentication API. The API returns a token upon successful authentication, which the extension then stores securely. This token is used for subsequent API calls to authenticate the user. You can use JWT (JSON Web Tokens) for this purpose. When the user logs in, generate a JWT key and store it in local storage. This JWT can contain some user ID. On each request to your custom API, send that JWT in the headers. Check it on each request. Here's a sample code for generating JWT:
// generateJwt.ts
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' });
}
}

// generateJwt.ts
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' });
}
}

Sven
Sven•2mo ago
2. Protecting SaaS Endpoint: To ensure that only users with a subscription can use your SaaS endpoint, you can add a role field to your User` entity. In your queries/actions, check the value of that role and based on that make a decision if they should be able to execute that query/action or not. If they are not allowed, you can throw HttpError 403 or something like that. You can check the open-saas template (https://opensaas.sh/) for an example of this. Securing Communication: As long as you're using HTTPS, the communication between the Chrome extension and the SaaS backend is as secure as it reasonably needs to be.
Open SaaS
Free, open-source SaaS boilerplate starter for React & NodeJS.
Filip
Filip•2mo ago
Hey @Sven. We've already had a user ask us about communication between their chrome extensino and SaaS app. Can you take a look at that chat and see whether you find anything useful: https://discord.com/channels/686873244791210014/1223328118278983680/1223328118278983680
Sven
Sven•2mo ago
Insaw But it is a really chaotic thread and also not really following up on my application
Filip
Filip•2mo ago
It seems like it matches your use case exactly, but I could be wrong. The thread talks about authenticating thourgh a Chrome extension. If that's what you need, I suggest you follow it and ask when you run into specific roadblocks that aren't mentioned there 🙂
Sven
Sven•2mo ago
alright ill check
Want results from more Discord servers?
Add your server