Forem Creators and Builders

James Robb
James Robb

Posted on

Read only frontend tokens

Right now I need a reverse proxy setup just for using the dev.to API. I use elm on the frontend and just compile a static site consisting of an index.html and bundle.js and make requests on the frontend as required. I would like to have something like a public read only token though so that I could send frontend XHR requests directly to the API and can thus remove the extra step of having a seperate reverse proxy setup.

I reached out to the DEV Community Team on the 19/06/2021 and they liked the idea but suggested opening this topic for conversation here for the community to provide feedback on this.

I was thinking of something along the lines of the anon key that supabase exposes for such use cases as the best example of what I am looking for. Basically something that just lets me use the API to read data without worrying about exposing the key to mallicious users who mess with admin settings or something.

Happy to discuss further in the comments if there are any open questions regarding the suggestion, otherwise please either upvote or comment your ideas related to this topic below, thanks!

Discussion (8)

Collapse
rhymes profile image
rhymes

Hi James, interesting idea as @ben said! The reason why we're not allowing CORS authenticated API operations is because we don't want to encourage people hardcoding their API keys into public frontends.

By adding "frontend read only" keys we'll need to associate each key to the allowed operations. Though that won't stop people using a "read/write key" on a frontend, so we'd be probably back to square one unless I'm mistaken. But it's also true that, with the appropriate messaging and checks, we should also trust people to know what they're doing, including embedding a read and write key in a publicly available frontend.

Even if we didn't require them to hardcode them, they would eventually need to store such token in the browser and there isn't a really secure way to do it.

Anyway, there are a few avenues to explore, thanks for the idea!

Collapse
jamesrweb profile image
James Robb Author • Edited

Hi @rhymes , for SupaBase they allow such operations, you are right, maybe it wasn't the best example but maybe my response to Ben is clearer?

I agree about discouraging using such api key mixing in terms of admin ones being used on frontend or visa versa but maybe something like JWT auth would give you the option to somehow validate the key isn't too powerful by including the data about the key for example in the hashed value. Then requests could be validated without concern that someone used the wrong key or a too powerful one for example.

I think it's an interesting topic and a good idea to deep dive in the future either way because different people have different needs and flexibility in this regard would be great if possible but I see the challenges also as you mentioned about finding a balance.

I would appreciate at least the GET routes for resources being open though because for me it would resolve my issue and such routes shouldn't cause too much concern, right?

Collapse
rhymes profile image
rhymes

Supabase still requires the user to login though - supabase.io/docs/guides/with-react... - the auth anonymous key is just an identifier (makes it easy to understand which client is accessing the server). The user itself has to authenticate, once they're logged in, they can access their own data.

They also say:

Now that we have the API credentials in place, let's create a helper file to initialize the Supabase client. These variables will be exposed on the browser, and that's completely fine since we have Row Level Security enabled on our Database.

If you look at their auth guide - supabase.io/docs/guides/auth - you'll see how they are using OAuth to authenticate the user.

Supabase has three level of security we don't have in our API v0:

  1. anon key to identify the client for all endpoints (we only require the key for certain endpoints, the public ones don't require a key)
  2. row level security which allows to restrict the blast radius in case the key is compromised with which the owner can literally decide to which tables and which rows to expose to the idenitifed user (we have none of that)
  3. OAuth login to identify the user (we don't have that either)

Basically, Supabase has a far more granular authentication system that we have, that's why you can embed the api key in the JS client, because the API key isn't the only key needed to open the doors. In our case, the key is the only gate and if the gate is open, all exposed data is accessible.

something like JWT auth would give you the option to somehow validate the key isn't too powerful by including the data about the key for example in the hashed value

To be fair, JWT isn't much more secure than anything else, the problem is always where the data is stored on the client, as local storage is accessible by any script running on your browser. These are good explanations: dev.to/rdegges/please-stop-using-l... and cryto.net/%7Ejoepie91/blog/2016/06...

I think it's an interesting topic and a good idea to deep dive in the future either way because different people have different needs and flexibility in this regard would be great if possible but I see the challenges also as you mentioned about finding a balance.

Definitely, there are many avenues on how to evolve Forem's API authentication, perhaps for v1 :)

Thank you for your rekindling the conversation!

Thread Thread
jamesrweb profile image
James Robb Author • Edited

Thanks so much for the detailed reply, I really enjoyed the JWT posts you shared especially.

Some open questions:

  • Are there plans for v1 already?
  • Could this be added to the roadmap if one exists at least to ideate solutions like the ones we outlines to decide what one would be best for the v1 API and to build a rough timeline?

Did you see my comment to ben regarding the organisation route vs user route and the possibility of opening that single route potentially as a temporary solution for me to access posts from the frontend, would that be possible in v0 as a patch for example or would we need to wait for v1 either way and if so, could you elaborate? I really appreciate your detail dude, really nice stuff :)

Thread Thread
rhymes profile image
rhymes

Hi James, thanks for the ideas! We don't have an ETA for the v1. Our product team will evaluate feature proposals. I posted some ideas about v1 last year and that sparked a discussion:

I don't think we should have "temporary" routes. The organization endpoint does not require authentication because it only returns published articles. /api/articles/me/* all require authentication as they were initially added for OAuth based purposes where the app impersonates the user.

If you require published articles of a single user without authentication, you can use dev.to/api/articles?username=rhymes for example :) See the username param in docs.forem.com/api/#tag/articles

Thread Thread
jamesrweb profile image
James Robb Author

Hi @rhymes , thanks for the feedback. I agree that the articles route solves part of the issue but the /me also returns user and org info, flare info etc.

Either way, a token to use on the frontend for any read only route at least would be great if a solution could be found to access these extra pieces of information such as those mentioned above.

Thanks for your patience and time so far, I look forward to seeing v1 get worked out sooner than later and as always I am happy to help if necessary!

Collapse
ben profile image
Ben Halpern

This is interesting. We crossed one bridge a while back when we adjusted CORS so that the base endpoints could be read on the frontend, but if I understand this correctly, this is a way to read certain authenticated endpoints on the frontend?

@rhymes you should probably follow this discussion most closely.

Collapse
jamesrweb profile image
James Robb Author • Edited

Indeed, for example /api/articles/me/published requires the api-key header but actually this endpoint from what I know is just a getter where no data or admin concerns need exist since there is no PUT, POST or DELETE possible and so why stop users just calling it since it seems safe to do so.

If you must authenticate such cases then why not with a frontend read only token on such routes as an example.

I also noticed that for /api/organizations/{username}/articles no authentication is required so why not also for users?