Even after setting auth:true in api end point in main.wasp api end point is not secure.

I can still call my api simply from http://localhost:3000/api/custom-api-endpoint-with-parameters and it shows api response with data. How to solve this and make it secure?
13 Replies
kapa.ai
kapa.ai4d ago
Hi @Killshot. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To secure your API endpoint in Wasp, you need to ensure that the auth field is set to true in your API declaration in the main.wasp file. This will enable authentication and provide a context.user object. If you do not wish to attempt to parse the JWT in the Authorization Header, you should set this to false. Here is an example of how to set it:
api fooBar {
fn: import { fooBar } from "@src/apis",
httpRoute: (GET, "/foo/bar"),
entities: [Task],
auth: true,
middlewareConfigFn: import { apiMiddleware } from "@src/apis"
}
api fooBar {
fn: import { fooBar } from "@src/apis",
httpRoute: (GET, "/foo/bar"),
entities: [Task],
auth: true,
middlewareConfigFn: import { apiMiddleware } from "@src/apis"
}
In the above example, auth: true means that the API endpoint is secured and requires authentication. However, setting auth: true only means that the endpoint expects an authenticated user. If you want to enforce that the endpoint can't be accessed without authentication, you need to check the context.user in your API's NodeJS implementation. If context.user is not present, it means the request is not authenticated, and you should return an error. Here is an example of how to do it:
export const fooBar = (req, res, context) => {
if (!context.user) {
throw new HttpError(401) // Unauthenticated
}
// Rest of your code
};
export const fooBar = (req, res, context) => {
if (!context.user) {
throw new HttpError(401) // Unauthenticated
}
// Rest of your code
};
In the above example, if context.user is not present, an HTTP 401 error is thrown, indicating that the request is not authenticated. Please refer to the following sources for more information: - API Reference (https://wasp-lang.dev/docs/advanced/apis#api-reference) - Defining the API's NodeJS Implementation (https://wasp-lang.dev/docs/advanced/apis#defining-the-apis-nodejs-implementation) - Updating Operations to Check Authentication (https://wasp-lang.dev/docs/tutorial/auth#updating-operations-to-check-authentication) ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @Killshot, 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?
Vinny (@Wasp)
Vinny (@Wasp)2d ago
can you share the relevant code from your API as well as its definition in your main wasp config file?
martinsos
martinsos19h ago
@Killshot check out the docs here: https://wasp-lang.dev/docs/advanced/apis#api-reference -> auth: true does not mean it will not allow unauthenticated users, but that it will check if there is an authenticated user and if so, provide it for you in context.user. You are then to implement the checkyourself -> you can do if (!context.user) or whatever you want to check. auth: true "just" detects logged in user if there is such and provides it to you so you can implement your custom logic.
Custom HTTP API Endpoints | Wasp
In Wasp, the default client-server interaction mechanism is through Operations. However, if you need a specific URL method/path, or a specific response, Operations may not be suitable for you. For these cases, you can use an api. Best of all, they should look and feel very familiar.
martinsos
martinsos19h ago
Ha, actually Kapa already have a good answer, I missed it! Yeah, Kappa already said it correctly. But @Killshot , what is true is that this is confusing. auth: true does sound a bit too much like auth is required. We have a GH issue here to give it some better name: https://github.com/wasp-lang/wasp/issues/1133, and I will also link it to this discord convo.
Killshot
Killshot18h ago
Is this syntax correct or am i messing somethng up?
import axios from 'axios';
import { HttpError } from 'wasp/server';

export const getRandomDogImage = async (args, context) => {
// Check if the user is authenticated
if (!context.user) {
throw new HttpError(401, 'User not authenticated');
}

try {

const response = await axios.get('https://dog.ceo/api/breeds/image/random');


if (response.status === 200 && response.data.message) {
return { imageUrl: response.data.message };
} else {
throw new Error('Invalid response from Dog API');
}
} catch (error) {
console.error('Error fetching dog image:', error);
throw new HttpError(500, 'Failed to fetch dog image');
}
};
import axios from 'axios';
import { HttpError } from 'wasp/server';

export const getRandomDogImage = async (args, context) => {
// Check if the user is authenticated
if (!context.user) {
throw new HttpError(401, 'User not authenticated');
}

try {

const response = await axios.get('https://dog.ceo/api/breeds/image/random');


if (response.status === 200 && response.data.message) {
return { imageUrl: response.data.message };
} else {
throw new Error('Invalid response from Dog API');
}
} catch (error) {
console.error('Error fetching dog image:', error);
throw new HttpError(500, 'Failed to fetch dog image');
}
};
This is my main.wasp configuration for same test API --
api randomDogImage {
fn: import { getRandomDogImage } from "@src/appapis/apis.js",
httpRoute: (GET, "/api/random-dog"),
auth: true,
}
api randomDogImage {
fn: import { getRandomDogImage } from "@src/appapis/apis.js",
httpRoute: (GET, "/api/random-dog"),
auth: true,
}
@martinsos
martinsos
martinsos16h ago
@Killshot this looks good to me, at first glance! Why are you asking though, are you referring to your usage of auth: true and then if (!context.user)? If so, that part makes sense to me. Now only authenticated users should be able to run that api. Or do you have some issue still, is that why you are asking?
Killshot
Killshot16h ago
Yeah, so even after making sure i have auth:true in main.wasp for this relevant part and context.user check in api code, i am now consistently getting 401 error even though i am logged in via Google Oauth, i did logout and log in again and still same issue. am i missing something in cookies or session settings?
martinsos
martinsos15h ago
@Killshot ooooh wait, I have an idea -> how are you doing those API requests? Are you doing it as specified here https://wasp-lang.dev/docs/advanced/apis#using-the-api-from-the-client ? By importing api from wasp/client/api? Because this api is provided by wasp and will therefore do these calls correctly, with the authentication set correctly. If you do it on your own, with axios directly or fetch or something like that, you will not have auth credentials set during that call.
Killshot
Killshot15h ago
Ohh that solves it and even makes sense i guess. I was doing it directly via axios
martinsos
martinsos15h ago
Ahh sorry about that @Killshot . Is there a place in docs we could have made this clearer maybe? I understand that this is easy mistake to do.
Killshot
Killshot15h ago
I did use search feature and might have even went through this without realizing it. My bad @martinsos
martinsos
martinsos15h ago
You are not the first one to stubmle on it though. I created an issue for it here now https://github.com/wasp-lang/wasp/issues/2350 , we really should figure out a way to make it harder for people to make this mistake. It is just too easy to just go with axios or fetch and forget about this. I wrote down some ideas in that issue.
Killshot
Killshot6h ago
Appreciate it boss, I guess a disclaimer of some kind in our own opensaas docs would have solved it for me seconds. Not much just a description of how one would need custom API endpoints and then linking them to this https://wasp-lang.dev/docs/advanced/apis#using-the-api-from-the-client wasp generic docs regarding calling api from client side. I did check this out https://docs.opensaas.sh/guides/authorization/#server-side-authorization but it didn't solve it completely.
Custom HTTP API Endpoints | Wasp
In Wasp, the default client-server interaction mechanism is through Operations. However, if you need a specific URL method/path, or a specific response, Operations may not be suitable for you. For these cases, you can use an api. Best of all, they should look and feel very familiar.
OpenSaaS.sh
Authorization
Open SaaS is a free, open-source, full-stack SaaS starter kit for React + NodeJS.
Want results from more Discord servers?
Add your server