Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending POST Request to Secured Action

I have an action that takes POST data secured by sfGuard. This means that if the user is not logged in, the POST data will be sent to the log in form. Ordinarily, this is not a problem, the user continues to log in, and has to submit the data again.

Unfortunately, the log in form seems to be using the POST data as if it was submitted with the form itself. This means that it is complaining that the required username and password fields are missing, and it complains that it is missing a CSRF token. This last problem does not go away, after submitting the form, meaning the user cannot log in, anyway.

The user should not be presented with the form if not logged in, but it might be possible for the user to log out with the form still open. So I am asking in the interest of keeping the interface watertight and error-free.

Is this a shortcoming of sfGuard, can it be avoided, or am I doing something wrong altogether?

To clarify, the route looks like this:

add_subgroup:
  url:      /group/:id/add
  class:    sfPropelRoute
  options:
    model:  Group
    type:   object
  param:    { module: subgroups, action: create }
  requirements:
    group_id: \d+
    sf_method: [post]

The form used to submit the request is as follows:

<form action="<?php echo url_for('add_subgroup', $group) ?>" method="post">
  <input type="hidden" name="group_id" value="<?php echo $group->getId() ?>" />
  <input type="text" name="subgroup_id" />
  <input type="submit" class="button" value="Add" />
</form>
like image 831
Druckles Avatar asked Aug 17 '11 16:08

Druckles


1 Answers

It is a shortcoming of sfGuard, because the signin action will check for a POST request, and if so bind the form.

From the code in BasesfGuardActions.class.php:

if ($request->isMethod('post'))
{
  $this->form->bind($request->getParameter('signin'));

I'm personally not a big fan of forwarding between actions in symfony, and just like in this case, I think it's more appropriate to redirect than forward. This also solves your problem because this will result in a new GET request. You can accomplish this behavior by extending sfGuardBasicSecurityFilter.

class mySecurityFilter extends sfGuardBasicSecurityFilter
{

  protected function forwardToLoginAction()
  {
    $context = $this->getContext();
    // If you want to redirect back to the original URI (note: original POST data will be lost)
    $context->getUser()->setReferer($context->getRequest()->getUri());
    $url = sfConfig::get('sf_login_module') . '/' . sfConfig::get('sf_login_action');
    $context->getController()->redirect($url);
    throw new sfStopException();
  }

}

Now in app/myapp/config/filters.yml

security:
  class: mySecurityFilter
like image 117
Gerry Avatar answered Oct 18 '22 17:10

Gerry