[Catalyst] Securing a connection

Jesse Sheidlower jester at panix.com
Tue May 14 17:37:04 GMT 2013


I've recently upgraded my Cat to 5.9, and in the process decided to
switch from the deprecated Catalyst::Plugin::RequireSSL to
C::ActionRole::RequireSSL. Somewhere along the line, something stopped
working in my secure-connection activity, and no one found an answer in
some IRC chat so I thought I'd try here, with an additional question or
two.

For debugging purposes now I'm just trying the most basic thing--making
my login secure. If I go to http://example.com/myapp, I get routed to
http://example.com/myapp/login (not https, which is what I expect, since
the Does('RequireSSL') is in the login method). When I enter
login/password info, the app crashes with a "Cannot secure request on
POST" error. (I don't understand this error anyway--why can't you secure
a POST, or what are you supposed to do so that login or other sensitive
info is going over https?)

Apart from login, the only things I want to be secure are viewing and
editing of user info. In production I'm running under nginx/FastCGI, and
it's mostly how I've been testing this too (on a VM). Oh, if I manually
enter an https address, it works, so it doesn't seem to be a server
problem.

Thanks for any ideas. This isn't something that I thought should be so
hard....

Code below. The (straightforward) login method, from my User controller:

use parent qp/Catalyst::Controller::ActionRole/;
# ....
sub login :Path('/login') Does('RequireSSL') {
  my ($self, $c) = @_;

  # Get the username and password from form
  my $username = $c->request->params->{username} || "";
  my $password = $c->request->params->{password} || "";

  # If the username and password values were found in form
  if ($username && $password) {
    # Attempt to log the user in
    if ($c->authenticate({ login => $username, password => $password }))
  {
      # If successful, then let them use the application
      $c->user->last_login(\'now()');
      $c->user->update;

      if ( $c->req->address =~ $c->config->{permanent_login_regex} ) {
      $c->session->{remember_me} = 1;
      }

      my $redirect = $c->session->{orig_uri} || $c->uri_for('/');
      $c->session->{orig_uri} = undef;
      $c->response->redirect( $redirect );
      return;
    } else {
      $c->stash->{message} = "You have entered an invalid
      username/password combination";
    }
  }

  # If either of above don't work out, send to the login page
  $c->stash->{title} = "Application login";
  $c->stash->{template} = 'login.tt';
}

I'm not going to bother showing my auto() methods, though they're here
if anyone cares: http://paste.scsys.co.uk/248078 The main thing is that
if there's no user, it redirects to /login (not just forwards there).

The login form is the usual:

  <form method="post" action=" [% c.uri_for('/login') %] " name="login">

And here's the (messy, sorry) debug output, from the testing server (and
thus not able to use SSL, but still showing the 500 error on the POST.

[info] *** Request 1 (0.167/s) [21253] [Tue May 14 11:57:37 2013] ***
[debug] Path is "/"
[debug] "GET" request for "/" from "127.0.0.1"
[debug] Created session "7f752088d13d623783c5d2904a51fa33fc41b2ae"
[debug] ***Root::auto User not found, forwarding to /login
[debug] Redirecting to "http://localhost:3000/login"
[debug] Response Code: 302; Content-Type: text/html; charset=utf-8;
Content-Length: 306
[info] Request took 0.063867s (15.658/s)
.------------------------------------------------------------+-----------.
| Action                                                     |
Time      |
+------------------------------------------------------------+-----------+
| /auto                                                      |
0.056214s |
| /end                                                       |
0.000609s |
|  -> /render                                                |
0.000358s |
'------------------------------------------------------------+-----------'

[info] *** Request 2 (0.182/s) [21253] [Tue May 14 11:57:42 2013] ***
[debug] Path is "login"
[debug] "GET" request for "login" from "127.0.0.1"
[warn] Would've redirected to SSL
[debug] Rendering template "login.tt"
[debug] Found sessionid "7f752088d13d623783c5d2904a51fa33fc41b2ae" in
cookie
[debug] Restored session "7f752088d13d623783c5d2904a51fa33fc41b2ae"
[debug] Response Code: 200; Content-Type: text/html; charset=utf-8;
Content-Length: 2347
[info] Request took 0.047926s (20.866/s)
.------------------------------------------------------------+-----------.
| Action                                                     |
Time      |
+------------------------------------------------------------+-----------+
| /auto                                                      |
0.001897s |
| /user/auto                                                 |
0.000134s |
| /user/login                                                |
0.000239s |
| /end                                                       |
0.037722s |
|  -> /render                                                |
0.036557s |
|   -> NewWords::View::TT->process                           |
0.035981s |
'------------------------------------------------------------+-----------'

[info] *** Request 3 (0.115/s) [21253] [Tue May 14 11:57:57 2013] ***
[debug] Path is "login"
[debug] "POST" request for "login" from "127.0.0.1"
[debug] Body Parameters are:
.-------------------------------------+--------------------------------------.
| Parameter                           |
Value                                |
+-------------------------------------+--------------------------------------+
| password                            |
testpassword                         |
| submit                              |
Login                                |
| username                            |
testuser                             |
'-------------------------------------+--------------------------------------'
[warn] Would've redirected to SSL
[debug] Found sessionid "7f752088d13d623783c5d2904a51fa33fc41b2ae" in
cookie
[debug] Restored session "7f752088d13d623783c5d2904a51fa33fc41b2ae"
[error] Cannot secure request on POST
[debug] Redirecting to "http://localhost:3000/"
[debug] Response Code: 500; Content-Type: text/html; charset=utf-8;
Content-Length: 154248
[info] Request took 0.123818s (8.076/s)
.------------------------------------------------------------+-----------.
| Action                                                     |
Time      |
+------------------------------------------------------------+-----------+
| /auto                                                      |
0.001568s |
| /user/auto                                                 |
0.000078s |
| /user/login                                                |
0.045757s |
| /end                                                       |
0.000485s |
|  -> /render                                                |
0.000258s |
'------------------------------------------------------------+-----------'



More information about the Catalyst mailing list