What is the simplest way to safely manage client backend calls and sensitive data in Razor Pages?
Hi all! I’m working on a simple practice document editor web app using Razor Pages for practice, where users can edit and save plaintext documents (my goal is to basically make a rudimentary clone of Google Docs). My application has three pages, starting with a login page. After logging in, users see a landing page with a list of document names. Clicking a name opens the editor, which has a textarea for input and a "Save" button, along with a modal to prompt saving if they attempt to leave without saving.
Currently, I’m stuck on how best to structure the PageView/PageModel and associated JS script file for the PageView to handle these types of backend calls efficiently on the client JS. My goals are to:
- Make a backend call to save changes, which I believe would require both the document ID and textarea content on the front end so the method knows which document is being saved.
- Decide where to store the document ID for safe access on the front-end PageView so I can use it in a fetch call—such as in a hidden div or an HTML data attribute—and understand best practices around storing IDs or other sensitive data in the front end.
- Implement fetch GET/POST requests to a Page Handlers without causing a page redirect.
What is the standard approach here for something like this in Razor Pages? Specifically, what kind of sensitive data should be on the front end to make a secure backend API call, and what’s the best way to structure this in Razor Pages? Or is there some other established design patter to do something like this?
Thank you!
(This question also applies to other applications with concurrent backend calls and user operations, such as social media sites like Instagram and Reddit and design tools like Canva and Photoshop. I feel there’s a knowledge gap in efficiently implementing these features and properly referring to this type of architecture.)
3 Replies
If I understand correctly, you wanted to secure the data being transferred over the rest API calls? It is the same as how a password or any forms are being posted to the server. Encode or encrypt the request body. U can have custom headers for IDs and pass them if you don't want them to be part of the URL. But I'm not sure whether it deviates the rest design
Thank you for responding! And yes, that was one part of my question. The other is, well, I guess I am just not sure how something like this would be structured within the context of the Razor Pages framework. In a way that is best practice.
When someone clicks on a document and it opens in the editor page, I guess my other question is would I even need the ID of which doc needs to be saved? If the id is just part of the query string parameters when the user opens it in the editor, or it’s assigned and bound to a pagemodel page property, can I just do a fetch API calls to the PageModel with the text content or nothing at all, and this use this.ID to reference to the page Id loaded on the page?
Or if I would need the ID on the page, do I pass it in the request body like you mentioned and pull it in the client side JS for api calls?
Not sure which way is best
Make a backend call to save changes, which I believe would require both the document ID and textarea content on the front end so the method knows which document is being saved.
If your UI and API are truly separated, you could use JS to do a GET
on the API, first, and have it return the list of documents. If you're worried about permissions and/or who should be able to access what document, you could implement rbac (via opal) and have your API reference that to validate who should have access to what.
Decide where to store the document ID for safe access on the front-end PageView so I can use it in a fetch call
As eluded to in my first blurb, you should only "store" it after the first GET
call; as for "where" to store it, not sure.
Specifically, what kind of sensitive data should be on the front end to make a secure backend API call,
Basically, all you need is the JWT (assuming you're using something like MSAL).
If you have a true separation of concerns, you can put something between the UI and API to validate that your calls came from a valid/trusted source; for example, if you're using Azure, you could put APIM in-between the UI and the API and have APIM include an origin-validation
header value that your API processes (APIM can validate the JWT).
So, for example, the UI generates a request, then sends it to the vanity name of your API. APIM is set to receive the requests on that name. It receives the request, validates the JWT, and creates a secure header (e.g.: X-Origin-Validation
) using an encryption key stored in Azure Key Vault and then forwards the entire request to your API (including the header it just created). Your API, upon receiving the request, first checks the X-Origin-Validation
header (using the same encryption key from Azure Key Vault) and continues processing the request, if the validation passes; otherwise, it should throw and not continue the request.
https://github.com/Azure/api-management-policy-snippets