1

On the page, there will be several posts by a user. Each post has an id # to identify it which is used when editing or deleting the post. With blade, I can make it so that hidden ID div only shows up when the authenticated user is on their own profile (since only they are allowed to edit or delete the posts).

However, I also have a liking feature that also uses that hidden ID div. I don't want someone to view the page source, change the ID, then click the like button. Is there a way to include the ID in the view, but not allow it to be changed?

I could try do to some validation on each like such as match the user, body, time posted, and ID and if that doesn't match then throw an error. Curious if there's a better way.

View:

<div class="post-like">
    <a href="{{ route('post.like', ['postId' => $post->id]) }}" class="post-like-a">Like</a>
</div>

Controller:

The $postId is that hidden ID div

public function getLike($postId)
{
    $post = Post::find($postId);
    if (!$post) {
        return redirect()->back();
    }
    if (Auth::user()->hasLikedPost($post)) {
        return redirect()->back();
    }        
    $like = $post->likes()->create([]);
    Auth::user()->likes()->save($like);
    return redirect()->back();
}
Matt Pierce
  • 807
  • 3
  • 22
  • 45

2 Answers2

1

It's not wise expose users' ID like this, but if you really need it, Laravel provides a way to handle users' action authorization. It can be done using either policies or model scopes.

Alternatively, you can ignore those authorizations and use UUID instead ID. There is a nice package that handles it for you. Basically you'll just need to add a new field to the users' table.

In my applications I use both of them.

henriale
  • 1,012
  • 9
  • 21
0

If I understand your question correctly, here's one idea: you can hide the actual post ID by concatenating your ID with some server-side only "key" and hashing.

For example:

In your app.php you add something like "post_mask_key" => "super_secret_123456"

...and in your code, something like:

$maskedPostId = sha1(\Config::get("app.post_mask_key") . $postId);

Then, share $maskedPostId with your view, which will be embedded into the HTML. The user can try to change it but when it is submitted, you can re-generate the hash easily (since you know both the key and ID server side) and compare the two.

Note: this approach is cryptographically weak but should be sufficient for masking a non-critical item like a post ID.

avip
  • 1,445
  • 13
  • 14
  • What is the typical best practice when needing information such as the user's ID to send to the controller? – Matt Pierce Apr 14 '16 at 20:15
  • There's always a convenience-security trade off which is contextual to application. Generally speaking, it's probably a good idea to mask internal DB IDs - so a UUID would work. You might also want explore using [HMAC signatures](http://security.stackexchange.com/questions/20129/how-and-when-do-i-use-hmac/20301) – avip Apr 14 '16 at 20:29
  • I'll look into your suggestions. I can hide the user's ID from everyone but themselves, so that's ok. Need to figure out UUID for the post id. – Matt Pierce Apr 14 '16 at 20:31
  • You could use [laravel-uuid](https://github.com/webpatser/laravel-uuid) or just [this](http://stackoverflow.com/questions/2040240/php-function-to-generate-v4-uuid) function straight from the PHP manual page comments. You'll likely have to add a field/var to your table/model to store the uuid once it's generated. – avip Apr 14 '16 at 20:37