Craig Walker
Craig Walker

Reputation: 51727

Are there any security implications of identifiers in URL path elements?

I'm implementing a Rails app using Devise for most of the user authentication work. One thing I've noticed is that, when passing identifiers around for security-sensitive tasks, they're always done using query string parameters.

For example, the URL included in the password reset email sent to users might look something like this:

http://example.com/users/password/edit?reset_password_token=_aPKoNpLHm7HYs_o4Qex

Devise looks up the user based on the reset_password_token and changes the password when the user resets the form.

I just implemented a similar function that's not handled by Devise. In every email, I include an unsubscribe link. The controller looks up the user based on a unique token and sets their unsubscribe flag to true, even if the user is not logged in.

However, the URL I generate looks like this:

http://example.com/subscription/3e7eb22a268b62d5/edit

This is, basically, the same thing that Devise is doing. The difference is that I include the token in the URL path itself rather than the query string.

In my mind, this is more RESTful, as it points to a specific resource (the subscription in question) that the user then updates (by posting the form to PUT http://example.com/subscription/3e7eb22a268b62d5). Beyond that benefit, I don't see any difference between the two methods.

Is there something reason I'm missing to use a query string parameter over a RESTful URL?

Upvotes: 1

Views: 552

Answers (2)

Thierry Templier
Thierry Templier

Reputation: 202196

Passing token within URL isn't really fine within RESTful services. A better approach would be to send it within the request content. That said, this token is a one-shot one and not really related to authentication, so it's perhaps a bit less annoying... Moreover I guess that this feature needs to be reached from a link (within an email) not from a form submission and that's why such URL parameter is used.

Otherwise, honestly using action (element edit) name within resource path (http://example.com/subscription/3e7eb22a268b62d5/edit) isn't really RESTful ;-) In fact, the action is described by the used method itself. In the case of a method POST, we can also use eventually an additional hint if you want to support several actions.

Regarding the use of the method PUT, it should be used when you want to update the complete representation of your resource. In your case, I think that you're rather in the case of a method POST since you want to execute an action on the subscription (resetting password of a subscription) using a reset password token. Here is the request I would see in your case:

POST http://example.com/subscription/3e7eb22a268b62d5
{
    "reset_password_token": "_aPKoNpLHm7HYs_o4Qex"
}

I provide you two links that could help you designing your request:

Edited following the Craig Walker's comment.

Hope it helps you, Thierry

Upvotes: -1

Will Hartung
Will Hartung

Reputation: 118671

Is there something reason I'm missing to use a query string parameter over a RESTful URL?

Not really. The only real difference between user a query parameter and not is that some intervening systems may not cache URIs with query parameters, so in that scenario embedding an identifier in the base URI is a work around.

That said, that argument is pretty much irrelevant to your use case.

At a high level, REST doesn't care at all, as it considers the URI as a whole (and the query parameter is part of the URI). So, it has no advice on this matter. Both URIs uniquely "name the resource", so REST is happy there.

Idiomatically, embedding the id in the BASE URI is quite popular, and it can be relevant for edge case caching scenarios, so, that's the only real fan waving the flag for that form vs the query parameter.

Cosmetically, many prefer the embedded style.

I'll let you weigh those considerations.

Upvotes: 2

Related Questions