How to allow only single page be displayed vie iframe? - php

I have a page in my Laravel project which I need to make available for use throughout iframe. Not the whole app but only one single page available for iframing inside only one trusted domain.
I learned that Laravel has a middleware, which protects the whole app from being displayed via iframe, called FrameGuard
class FrameGuard
{
public function handle($request, Closure $next)
{
$response = $next($request);
$response->headers->set('X-Frame-Options', 'SAMEORIGIN', false);
return $response;
}
}
But this is the framework's middleware, not project files, so can't change it. Even if I had decided to change it I would have to change handle method to
public function handle($request, Closure $next)
{
$response = $next($request);
//$response->headers->set('X-Frame-Options', 'ALLOW-FROM' https://example.com); obsolate
$response->headers->set('Content-Security-Policy' frame-ancestors 'self' https://www.example.com);
return $response;
}
Since it has now a different header would it be the cause of any problems in the future?
Also, if allowing only a single page to be used in iframe programmatically possible do I have to change other configurations like e.g. Nginx settings?
It feels like a lack of information on this topic on the internet. Any thoughts and contributions will be deeply appreciated.

Related

Laravel session in middleware not always set

I have a middleware set on all of my web routes that saves the referer to the session if not set so I am able to log it once my visitor converts.
This works most of the time, meaning that sometimes the referer is one of my own pages that is often somewhere in the middle of the whole customer journey, which absolutely makes no sense to me.
So to clarify: the referer is a page where the middleware should have fired and already saved a valid or empty referer. This page is usually not the beginning or the last page before I log.
My simplified middleware:
public function handle(Request $request, Closure $next)
{
if (!$request->session()->has('data')) {
$request->session()->put('data', ['referer' => $request->header('referer')]);
}
return $next($request);
}

laravel 6 when login go to previous url not working

I'm using Laravel framework my previous version of laravel is 5.8
and in my middleware login
public function handle($request, Closure $next)
{
if(Auth::check())
{
return $next($request);
}
else
{
Session::put('url.intended',URL::previous());
return redirect('/login');
}
}
and this is the controller login controller
if(Session::get('url.intended') <> '')
return Redirect::to(Session::get('url.intended'));
else
return redirect('/');
with this codes in laravel 5.8 everything was working great but when i upgrade to laravel 6 its not working any more i dont know why
any help here thanks
if i came from any link its always redirect me to / link
You should probably be letting the framework handle as much of this as possible. If you must use your own middleware and Controller method still let the framework handle this as it does best.
Dealing with the intended URL is already something the framework is capable of doing itself and checks multiple conditions to figure this out. You can use the guest method of the Redirector to have it do this for you:
return redirect()->guest('login');
This will take care of the redirect to 'login' and set the url.intended in the session as needed.
After login is successful you can redirect them to where they were trying to end up, 'intended', or a fallback url:
return redirect()->intended('/');
This will redirect to what it can find as the 'intended' and if not use a fallback. It will also remove the 'url.intended' key from the session as it is no longer of use. No need to set or check the session yourself.

Laravel localization with url

I am developing a multi-language web app using Laravel framework. So in this app, I have a special condition to do multi-language feature as below.
a user can select from some flags and change the language manually.
It changes his URL to /{lang} .. so, for example, webapp.com/cs - so he will see everything that in Czech language. webapp.com/en - see everything in English.
Chosen localization should be persistent so would not disappear when user change page or something - it should always be in the URL.
I created Route to set locale in session as follows.
Route::get('/{locale}', function ($locale) {
session()->put('locale', $locale);
return back();
});
And created middleware and added it to $middlewareGroups in the http\Kernel as well.
Below is my middleware.
public function handle($request, Closure $next)
{
if (session()->has('locale')) {
app()->setLocale(session('locale'));
}
return $next($request);
}
Localization is going well and it gives correct translations and everything. But what I need is to show in the URL what is the language is. as example webapp.com/cs,webapp.com/en. It would be great if anyone can help me with this problem.
Thanks.
You can try this,
In your every route you can append current local language like this
Route::get('/home/'.app()->getLocale(),'HomeController#index');
and one more thing you should see this
Laravel app()->getLocale() inside routes always print the default "en"
Hope this helps :)

Middleware for public storage in Laravel

I have this structure: laravel/storage/app/public/images/id_of_user/
Where id of user is the id of the user.
This is my middleware:
public function handle($request, Closure $next)
{
if($request->user_id == Auth::user()->id{
return $next($request);
}
return back();
}
and made a route like this:
Route::group(['middleware' => 'storagemiddleware'], function () {
Route::get('storage/images/{$user_id});
});
This doesn't work, tho. Everyone can still acess to everyones images. I honestly didn't expect this to work since it seems that storage has its own special routes and settings.
What I want is that only the users are allowed to see the content of their folder in their storage.
Any suggestions?
Read through this section of the documentation: https://laravel.com/docs/5.4/filesystem.
If the idea is to keep files accessible only to those you own them, you'll want to put them somewhere in the storage directory and then access them through a controller. Anything in your public directory is just that, public.
You could setup a directory structure like this storage/user_data/<$user_id>/ to keep things separated, then retrieve them from your route and the specified parameter.

Middleware for checking if resource is owned by user

I'm having some trouble making middleware that checks if the user owns the resource being requested.
For example, if the user goes to /playlists/1/edit, and they do not own playlist 1, it should display a 401 error.
Here's what I have so far:
class CheckOwnership {
public function handle(Request $request, Closure $next)
{
if (Playlist::find($request->route()->parameters()['playlists'])->user_id !== $request->user()->id)
{
return response('Unauthorized.', 401);
}
return $next($request);
}
}
This is terrible and only works for the Playlist resource, but I can't find any better way of doing this.
Thanks
This can easily be achieved with the newly added Form Request Validation.
You can see it in detail here (Authorizing Form Requests):
http://laravel.com/docs/5.0/validation#form-request-validation
The example given is actually about a user attempting to edit a comment they own.
Extract:
The form request class also contains an authorize method. Within this
method, you may check if the authenticated user actually has the
authority to update a given resource. For example, if a user is
attempting to update a blog post comment, do they actually own that
comment?
In your case, simply return false from the authorize method if they do no own the Playlist.
Currently, Laravel 5 does not support passing parameters to middlewares. I use sessions instead.
On your playlist controller, fetch the owner of the playlist and store it on a session. Let's say you have a playlists table with columns userID and playlistID.
public function __construct($playlistID){
$owner = Playlist::where('playlistID',$playlistID)->pluck('userID');
Session::put('OWNER',$owner);
$this->middleware('CheckOwnership',['only'=>'edit']); // apply it to edit function only, assuming you are using a route resource
}
Then, simply retrieve it on your middleware handle function.
public function handle(Request $request, Closure $next)
{
if (Session::get('OWNER') != $request->user()->id)
{
return response('Unauthorized.', 401);
}
return $next($request);
}
So far, this is a simple workaround. We have to wait till Otwell considers filter-like middlewares. Hope this helps!
For those using Laravel 8, I recommend using using Policies. This would let you organize authorization logic for specific models (e.x. the Playlist model for #ntzm).
So for example, a PlaylistPolicy class can be generated,
php artisan make:policy PlaylistPolicy --model=Playlist
and then the update function could look like this.
public function update(User $user, Playlist $playlist)
{
return $user->id === $playlist->user_id;
}
There are multiple way of enforcing this policy. If you would like to use middleware, Laravel has the can middleware that can enforce policies, so new middleware won't need to be written. In your route file this would look something like this,
Route::put('playlists/{playlist}/edit', ...)
->middleware(['can:update,playlist']);
Note: If the --model option isn't used, the policy will have to be registered manually, and example policy methods won't be automatically generated.

Categories