I am building my WebApps Backend for storing UserDetails and some more items in Strapi.
However, my users won’t be authenticating or performing any operations directly with Strapi.
My WebApp is built using ReactJS and it currently interacts with Asp.Net WebAPI which performs a lot of tasks/operations. Further operations related to User Details and the likes will be stored in Strapi.
So in turn, the request flow would actually go in the manner:
ReactJS => Asp.Net WebAPI => Strapi
Here I wanted to understand if creating the API Tokens as described is sufficient enough or do I need to perform some other operations?
I would say between your ASP.Net WebAPI and Strapi absolutely. We do plan to natively include API tokens (if fact it will become the default and the users-permissions system will an optional plugin) in the future. But in the short term the guide you linked is the best way to get started.
As long as the API tokens are kept server side and not shared in any client side (or client side rendered application like react) it should be fine.
Nope by nature API Tokens don’t expire, you must manually “deauth” them, they are typically used in machine to machine communication (different services/scripts/ect)
@DMehaffy There are cases where security is a concern and API tokens MUST expire, e.g. internet banking… Strapi behaviour regarding ever tokens is correct since there are lots of framworks handling tokens in various ways, but for the above mentioned concern the token management must be deferred to a third party service. Strapi has a built-in mecanism for this case (I can’t find it in docs right now), or the second option is to proxy strapi access like I did in my strapi-access-proxy project.
@SorinGFS API Tokens are an entirely different beast than those tokens used in banking. What I am referring to is similar to say GitHub Personal Access Token.
These are not JWT and generally do not expire unless manually revoked. (Though you could automate it). And should only ever be between to known and secured services and should never be user facing. Typically this would be between two services running in your backend, it’s also quite common between static site builders such as Gatsby, Nuxt.js, and Next.js where the token never leaves the control of the server administrators.
What you are referring to are effectively JWTs or client side tokens.
If you open that link in Introduction you can find this:
The goal is to be able to request API endpoints with a query parameter token that authenticates as a user. eg. /restaurants?token=my-secret-token.
Putting a valid token in url param is a terrible mistake, no matter if that url will be used between APIs or not. Url’s are stored in various places, logs, history, and so on…
I can show you many many security articles about this problem, here is an example:
For the exact same problem Strapi released a bug fix in version 3.2.4.
I do agree putting them in the query string is generally a bad idea if the requests are going over the public internet. (This can be modified in code to instead use a header). As they could be subject to man in the middle attacks (though very rare, but possible).
But again the API tokens are designed to be used between two services typically behind a local LAN and Firewall. A client or user should never see this.
The original author of this discussion has a ASP.net application that accepts his public traffic and is relaying requests to a backend Strapi instance behind his local LAN. The communication channel between his ASP.net application and Strapi is in a trusted zone.
@SorinGFS As @DMehaffy mentioned, mine is a public API built using ASP.Net WebAPI and the backend is built using Strapi. That way, my front end (built using ReactJS) only communicates with WebAPI without having any knowledge of Strapi ever existing.
Earlier, I was using MongoDB (although I am a SQL Server guy), but using Strapi on top of PostgreSQL seems powerful and faster. Best of all, I need not write any specific StoredProcedure or Views. Also, with Strapi, I get an amazing Dashboard kind of way to handle Data.
@DMehaffy If there are any snippets you have for validating the request using Headers, it would be best.
Although, I believe modifying this code should be more than enough to extract the token from Header.
Replacing ctx.request.query.token to ctx.request.header.token:
if ((ctx.request && ctx.request.header && ctx.request.header.authorization) ||
(ctx.request && ctx.request.header && ctx.request.header.token)) {
// init `id` and `isAdmin` outside of validation blocks
let id;
let isAdmin;
if (ctx.request && ctx.request.header && ctx.request.header.token) {
// find the token entry that match the token from the request
const [token] = await strapi.query('token').find({token: ctx.request.header.token});
if (!token) {
throw new Error(`Invalid token: This token doesn't exist`);
} else {
if (token.user && typeof token.token === 'string') {
id = token.user.id;
}
isAdmin = false;
}
//delete ctx.request.query.token;
}
}
Not MongoDB, but Mongoose is the performance problem. Strapi uses mongoose instead of mongoDb’s node native driver which is at least 3 times faster than mongoose. Moreover, mongoose strips out the whole potential of mongoDb as Alexandre Karan explains in this article … I’m an msSql guy too, but in for no-sql I prefer mongoDb with node native driver.