I am currently dealing with a project that has strong requirements on how the user authorizations are given amount the users.
If you are familiar with the symphony 1.4 jobeet tutorial you should have seen first authorizations and then a quick introduction to the sfGuardUserPlugin. Let’s get around that first:
Credentials
They are a nice way to define borders to you application. You can place them on every action very easily by editing the security.yml file of the zone where you are setting your rights.
[yml]
all:
is_secure: false
new:
is_secure: true
credentials: manager
create:
is_secure: true
credentials: manager
[/yml]
Here I simply said that my module is accessible for everyone, except the new and create actions where the user needs to be logged and evermore he need to have the manager credential.
The action workflow checks the needed credentials just before loading the action, and if the user has it, it executes the actions, if not, a 403 page is given. The function of the user that is used is called hasCredential.
The first thing you have to know is that credentials are given to the sf_user, even if he is not logged. This means that thay are session dependent and cannot be persists amount sessions. Given credentials are not mean to be stored in your database.
Permissions
They came with the sfGuarduserPlugin. The plugin gives you the sfGuardSecurityUser, which extends the sf_user and which can be persisted. You can also give to him permissions or groups. Groups can have permissions in such a way that a user automatically gets the permissions of his group.
Moreover, the User, Groups and Permissions can be stored in your database.
[php]
// add a group
$sfGuardSecurityUser->addGroupByName(‘manager’);
// add permission
$sfGuardSecurityUser->addPermissionByName(‘manager’);
// get permissions (direct permissions and also group permissions)
$sfGuardSecurityUser->getAllPermissions();
[/php]
The matter now is that the controller workflow does not use the permissions in order to compare them to the needed credentials for an action.
How to check credentials using the permissions
If we want to combine the nice yaml credential description and the powerful permission system, we need to override the hasCredential method.
The cool thing here is that the instance of the user used in this case is the myUser class defined in your application folder. This way our can override the method in a non-obtrusive manner:
[php]
// /apps/frontend/lib/myUser.class.php
class myUser extends sfGuardSecurityUser {
public function hasCredential($credential, $useAnd = true) {
// combine the credential and the permission check
return (parent::hasCredential($credential, $useAnd) || parent::hasPermission($credential));
}
}
[/php]
Upgrade the 403 page
What I like to do sometimes is to tell the user what credentials he misses. In order to do that, we will need to change the secure function that redirects to the 403 page.
Go to the sfGuardPlugin and look for the sfGuardAuthActions.class.php file :
[php]
// /plugins/sfDoctrineGuardPlugin/modules/sfGuardAuth/actions/actions.class.php
class sfGuardAuthActions extends BasesfGuardAuthActions
{
public function executeSecure($request) {
parent::executeSecure($request);
// retrieve the needed credentials
$this->credentials = $this->getContext()->getActionStack()->getFirstEntry()->getActionInstance()->getCredential();
// make sure the credentials are an array (in case of unique non-array credential)
if(!is_array($this->credentials))
$this->credentials = array($this->credentials);
}
}
[/php]
You noticed here that I use the first controller called in the action stack. You have to do that in order to retrieve credentials of the first action that tried to reach the user. If not, you will only retrieve the credentials of the current controller which does not have any.
You now have the credentials that you can display in your template.
[php]
// /plugins/sfDoctrineGuardPlugin/modules/sfGuardAuth/tempates/secureSuccess.php
You have to meet the following requirements to have access to this action:
<ul>
<?php foreach($credentials as $credential): ?>
<li>
<?php switch ($credential){
case ‘manager’:
echo ‘You need to be a manager’;
break;
}?>
</li>
<?php endforeach;?>
</ul>
[/php]
And voila, you have now a nice and powerful user authorization management on your symphony website.

6 thoughts on “Symfony 1.4 vs. sfGuardUserPlugin : understand credentials and permissions

  1. On How to check credentials using the permissions:

    The above method gives warnings… its better to check for is_string as in

    public function hasCredential($credential, $useAnd = true) { //credentials and permissions are not the same … now we can use permissions like credentials

    class myUser extends sfGuardSecurityUser
    {
    public function hasCredential($credential, $useAnd = true) {
    if ($p = parent::hasCredential($credential, $useAnd)) { return $p;}
    if (is_string($credential) && ($p = parent::hasPermission($credential))) { return $p;};
    return $p;
    }
    }

    1. This is easier of course

      class myUser extends sfGuardSecurityUser
      {
      public function hasCredential($credential, $useAnd = true) {
      return (parent::hasCredential($credential, $useAnd) || (is_string($credential) && parent::hasPermission($credential)));
      }
      }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s