PHP verify that user has access to content - php

I am building an ACL plugin to my framework / application.
The previous ACL applications i have worked with has a controller / action verification meaning that it checks if the user has access to both the controller and the view.
Now in many applications a user can have access to both the controller and the view but still not have acess to the content.
Forexample:
user1 has access to the controller: games and the view: play but not have access to the id: 1
My first idea was to check the $_GET variable but this is not sufficient since it is impossible to know what the variable that the content is looking for.
So my question is how would you verify that the user has access to the content of the view?

Well, you do know the id of the content in your Controller and you do know the user trying to access it. Just add contentId to your ACL check routine? You just have to add more ACL data, current implementation with just controller and method isn't enough in these cases.
e.g. $acl->userIsAllowedTo('view', 1, 'gamescontroller') or so.

Related

CakePHP: How to use a function with a model in every controller?

I have a project which includes admin and user section. Both section use the same controllers, just different functions and templates (ex: viewAdmin() and viewUser()). In function beforeRender() of every controllers, I set variable $admin as true for admin functions and false for user functions.
For authentication, I use Shibboleth. Shibboleth uses data from LDAP, while user types were saved in SQL-Database, that means while it can check if the login and password are false, it can't check if the user is admin or not. An user can go to ADMIN section as long as they use the right action (ex: go to the link http://example.com/tool/viewAdmin).
To prevent this, I will have to:
Load model Users
Compare the environment variable uid (login name) with the "login" columns in Users table in my SQL-Database
See the "type" column in Users table to know if user is admin or not.
Compare the result with value of $admin and redirect to an error page when necessary.
The problem is: I don't want to repeat those steps for EVERY controllers.
Currently I have 2 ideas:
Write a function in UsersController, and use it in every controllers.
Create a component and load it in every controllers.
Both methods require me changing code in all controllers. I would like to hear a better way with less work, perhaps by changing app.php or bootstrap.php.
Any suggestion is appreciated.
To share methods in CakePHP controllers you can do:
Create component and include in controller
Or create method in AppController and use it in child controllers
Or PHP way create Trait.
But when you authorize users, then all user data is stored in session, incl. is user roles (example admin, regular, member,.. )
Use the official CakePHP authentication plugin and extend the LDAP adapter with the additional code check you need. This is very easy to do and also a very clean way of solving the problem. Disclaimer: I'm one of the authors of the authentication plugin. https://github.com/cakephp/authentication
Or if you want to stay agnostic to any framework, use my library that is based on the authentication plugin and was decoupled from any framework but still works just nice with Cake https://github.com/Phauthentic/authentication.

Bypassing Controller Authentication

I'm currently writing a share-once functionality for a logged-in user to send a one-time link to another person (with no prior user account).
At the moment, I have a base controller which verifies user/password credentials, and handles authentication and all my controllers extend from that base controller.
To handle the one-time-share, I:
Generate a unique id
Insert the id with a date field set to NULL in
the db
Send the user a link to a controller that takes as parameter
the unique id
When the link is accessed, if the unique id exists and
if the date is NULL then I show the user the correct view and set the
date field to whatever TIMESTAMP happens to be at that moment.
This works, but...
I have another controller (/media), whose task is to retrieve an image from a secure path, and outputs it as an image. In the one-time view, I'm accessing the image like:
<img src="/media/image-id" />
Because that controller extends from the base controller which handles logins, the one-time user without an account is denied access.
I don't want to lose this level of security, but I'd need to have a way in order to allow the one time users access to the content.
What approach should I take in order to circumvent controller security for one-time users?
Thank you for any insight!
S.
It's kind of hard to say without seeing how you've organized your base controller or the controllers which extend from it. All we could really do is guess. Have you tried making a temporary session that will allow the user to authenticate to base controller? By that I mean, set up a session which limits their access based on what the link is? That way your security system is still being used and you don't have to do any hack work.

CakePHP ACL generating different links for different groups

Using CakePHP 2.0's ACL I have created 2 groups. One is admin and one is visitors. Right now admin can add and upload images and visitors can just view the images, if they click add or delete, it won't let them do anything. What's the best way to remove these links for visitor group? If I check which group they belong to using if/else statement, would that be the best solution?
To hide links that lead to actions a user is not authorized to perform, the views must somehow be aware of the user permissions.
You could check these permissions by checking the group a user belongs to, but this would mean that you wouldn't rely on the ACL permissions anymore. So any ACL permission update would have to be reported in code. Not very handy.
Then what else ? An approach is to check the user permissions in the controller, typically during login, and then keep these permissions in session.
The permissions in session can then be checked in the views to hide or show some parts of the views. You can find an example of this method here:
But for links specifically, you can go a little further and avoid to write the tests in views. I personnaly use a helper that inherits from the HtmlHelper and overrides the link() method.
Basically it works on the same idea: inside the overriden link() method, the permission on the target action is checked and the helper return the link, or nothing if the user is not allowed to access the target action.
If you want to try my code, you can use my Acl plugin
In your AppController, set the permissions:
var $components = array(..., 'Acl.AclManager');
function beforeFilter()
{
...
//you can put it here as the permissions check is performed only once per session
$this->AclManager->set_session_permissions();
...
}
And in your views, use the AclHtmlHelper
$this->AclHtml->link(...);
A general remark on the principle this method is based on though: all permissions are checked during login. If you have many actions in your application, this can considerably slow down the login.
A more effective approach could be to check the user permission for each actions only when it is required, meaning when the link() method is called. But this would mean that the helper would have to check the Acl permission itself, and this would somehow break the MVC model. And in the core lib, the Acl check is highly coupled to a component.

Can I rely on a CodeIgniter URI to check for a login?

Lets say I have the url http://localhost/home and this is the standard url of a page.
When a user logs in they are redirected to http://localhost/admin/home.
This URL without any routing is actually more like http://localhost/admin/panel/index/home.
Where admin is a folder, panel a controller, index a function and home an extension to give the view.
Can I theoretically check if a user is logged in depending on if the rsegment(2) is equal to 'admin'? or can a user fake the url somehow to break the system.
NB: The panel controller (inside the admin folder) has in its index function an actual login check I wan curious as to if a user would be able to trick the system into not running the index function, or is that secure.
No, You cannot rely on URI to check if a user is logged in.
You have to use an authentication library like TankAuth, or IonAuth.
Also if you need more options you can visit How should I choose an authentication library for CodeIgniter?.
I advise you to read Phil Sturgeon's Post on CI Base Classes. Class inheritance is key for maintaining who can access your controllers and who cannot. The URL contains no kinds of checks itself, but you know it calls a controller. The basic premise is:
If you create a controller called MY_Admin_Controller and all of your administrative controllers inherit from it and you perform the administrative check in MY_Admin_Controller, then you keep your system DRY (Don't Repeat Yourself) because you don't have to check whether or not that user should have access in every single controller. Only Once, and the controllers will inherit that check.
or can a user fake the url somehow to break the system.[?]
Sure, the URL is the most easy part that can be send to a server, you only need a browser with an address bar - which now as I write it, every browser has ;)
Whaaa?
Your route will point to a controller, if that controller is not secure then its open to public access.

Creating a User Login System: Put logic in Code or Database

I am trying to create a login system thats generic so that it can be adapted for use in various apps. I decided that 2 main "parts" of the system will be User Meta Data & Roles/Resources/ACL.
1. Metadata
I thought of keeping most data like what meta data are available for users in the database, so that admins can manage them using some GUI.
Problem is how can I then configue how I want inputs to render (textbox, checkbox, radios etc.). Then another problem is validation, filters.
2. ACL
I think for simple ACL it will work fine. But suppose I want say users to be able to modify posts they own. In Zend_ACL that is accomplished with Assertions. I thought that will make a "simple" login system overlly complex? Also it will be hard to build I suppose?
Currently I have my database like
Logging in users: I recommend using a separate controller (call it Auth for instance) that has loginAction and logoutAction. Zend_Auth (Zend_Auth using database) will check the database for the right credentials. Once the user is verified, you will save it in the global accessible place(the Zend_Auth class has methods to do this). This is also a good moment to query which roles the user has and store them.
Metadata part of your application: I'm not sure what the question is exactly but I assume you want to store dynamic information about user and have a GUI for admins to manage this. Why you would render different types of controls? Validating the information can be done by defining a lot of the most common metadata (like Twitter) and create rules for them. In the save action for the metadata you would validate using these rules.
ACL: Resources rarely change, you are better off putting them in a configuration file (for speed). You should give a lot thought to resources: what are they exactly to you? Controllers? Modules? Create a plugin that will preDispatch every request checking the role of the logged in user against the requested resource. E.g.:
$action = $request->getActionName();
$controller = $request->getControllerName();
// role, resource, privilage
if (!$acl->isAllowed($user->role, $controller, $action) {
//go to access denied page!
}
Now that Zend_ACL is used for the global access rules, you are better off checking for specific access inside the action itself (like if ($loggedInUser == $article->author) {//edit the article};).
Also don't forget Zend_ACL can be integrated with Zend_Navigation to hide menu items users are not allowed to use (and more).

Categories