Home > Software design >  How can I prevent a user from accessing a route via URL parameters?
How can I prevent a user from accessing a route via URL parameters?

Time:10-13

I'm writing an Express application that creates and exports a document based on the selections a user makes from two dropdowns. The dropdown values are passed as route parameters after a button is pressed, then necessary functions are called within the route method to create the document and send it back to the user.

How can I prevent a user (if possible) from calling/accessing this route by manually inputting route parameters into the URL bar? They should only be able to access the route from the button press.

Below is some general code for the functionality of my application...

Code for grabbing/sending values after button click:

export.onclick = function() {
    let index1 = dropdown1.value;
    let index2 = dropdown2.value;

    fetch('/'   index1   '/'   index2)
    // Convert response to blob object for download
}

Route Code:

app.get('/:index1/:index2', function (req, res) {
    // Call functions to create document
    // Return document back to user
});

The dropdowns are dynamically populated using data obtained from the response of an API. The value of each dropdown option represents the index of that option. The user being able to input random indices allows for invalid input; however, there are not necessarily boundaries to the inputs as the dropdowns are dynamically populated based on various user restrictions. For this reason, preventing the user from being able to access the route by inputting parameters in my mind would be ideal.

CodePudding user response:

You can't take away the ability to enter an URL into the browsers address bar but you can decide to just not handle the resulting GET request in your backend. Instead you can listen for a POST request.

app.post('/:index1/:index2', function (req, res) {
    // Call functions to create document
    // Return document back to user
});
export.onclick = async function() {
    let index1 = dropdown1.value;
    let index2 = dropdown2.value;

    const response = await fetch(`/${index1}/${index2}`, {
      method : 'POST'
    });
}

This is by no means a security feature, the user would still be able to create a POST request manually if she knows what she's doing and/or using a request client like POSTMAN or similar.

But why ?

It seems to me this could be a XY Problem. Why do you want to prevent the user to manually type in an URL into his address bar ? Could it harm your server/business in any way ? If yes, then you have a different, bigger problem at hand.

CodePudding user response:

add a token to protect your get request on the server side

like this

app.get('/:index1/:index2', function (req, res) {
    if (req.query.token !== 'foo') {
      // invalid the request
    }
    // Call functions to create document
    // Return document back to user
});

to send request to the url you will need the token

/:index1/:index2?token=foo

or just add the token on the request header

Then the following question could be

Do i need a dynamic token to secure the /:index1/:index2 API?

if no, then the user still can type the URL with this fixed token

if yes, you will need another API to generate the token on the "button page"

fetch('/get_new_token')
// get the token via this API
const token = ...

export.onclick = function() {
    let index1 = dropdown1.value;
    let index2 = dropdown2.value;

    fetch('/'   index1   '/'   index2   '?token='   token)
    // Convert response to blob object for download
}

you can use a key to encrypt your token

or add a signature into your token for verifying the token did not modified

and if you want your token will expire after a timestamp

add a timestamp info into the token

then verify the timestamp on the service side

  • Related