Skip to content
Snippets Groups Projects
Commit 03ecd4a2 authored by Guillaume ROUSSE's avatar Guillaume ROUSSE
Browse files

add CSRF token at email challenge step

parent 3440d6c8
No related branches found
No related tags found
No related merge requests found
......@@ -119,6 +119,39 @@ sub check_token {
return 1;
}
=head2 check_csrf_token()
Check if provided anti-CSRF token, as I<token> parameter, matches expected
one, abort otherwise.
=cut
sub check_csrf_token {
my ($self, %args) = @_;
my $provided_token = $self->param('token');
return $self->abort(
status => 403,
log_message => sprintf("missing anti-CSRF token for action %s", $self->current_route()),
user_message => "missing CSRF token"
) if !$provided_token;
my $expected_token = $self->csrf_token();
return $self->abort(
status => 403,
log_message => sprintf(
"invalid anti-CSRF token for action %s: %s instead of expected %s",
$self->current_route(),
$provided_token,
$expected_token,
),
user_message => "invalid CSRF token"
) if $provided_token ne $expected_token;
return 1;
}
sub get_sp {
my ($self, %args) = @_;
......
......@@ -28,6 +28,8 @@ sub run {
return if !$self->check_authentication();
}
return if !$self->check_csrf_token();
my $entityid = $self->param('entityid');
my $email = $self->param('email');
......
......@@ -20,7 +20,7 @@ plan(skip_all => 'live database required') unless
$ENV{TEST_DB_NAME} &&
$ENV{TEST_DB_TYPE};
plan tests => 10;
plan tests => 11;
sub named_subtest {
my ($name, $code, @args) = @_;
......@@ -224,10 +224,25 @@ named_subtest "email selection page, valid entityid" => sub {
html_ok($res) or diag_file($res, $test_dir);
};
named_subtest "challenge page, missing entityid" => sub {
named_subtest "challenge page, missing CSRF token" => sub {
my $t = get_test_object(test => $_[0]);
$t->get_ok('/step3')
->status_is(403)
->text_is('html head title' => 'eduGAIN Access Check', 'expected title')
->content_like(qr/Error:[\n\s]+missing CSRF token/, 'expected error message');
my $res = $t->tx()->res();
html_ok($res) or diag_file($res, $test_dir);
};
named_subtest "challenge page, missing entityid" => sub {
my $t = get_test_object(test => $_[0]);
# neutralize CSRF token check, as we short-circuit the form
$t->app()->hook(before_dispatch => sub { $_[0]->session(csrf_token => 'foo') });
$t->get_ok('/step3' => form => {token => 'foo'})
->status_is(200)
->text_is('html head title' => 'eduGAIN Access Check', 'expected title')
->content_like(qr/Error:[\n\s]+missing parameter 'entityid'/, 'expected error message');
......@@ -239,7 +254,10 @@ named_subtest "challenge page, missing entityid" => sub {
named_subtest "challenge page, invalid entityid" => sub {
my $t = get_test_object(test => $_[0]);
$t->get_ok('/step3' => form => {entityid => 'foo'})
# neutralize CSRF token check, as we short-circuit the form
$t->app()->hook(before_dispatch => sub { $_[0]->session(csrf_token => 'foo') });
$t->get_ok('/step3' => form => {token => 'foo', entityid => 'foo'})
->status_is(200)
->text_is('html head title' => 'eduGAIN Access Check', 'expected title')
->content_like(qr/Error:[\n\s]+invalid parameter 'entityid'/, 'expected error message');
......@@ -251,7 +269,10 @@ named_subtest "challenge page, invalid entityid" => sub {
named_subtest "challenge page, valid entityid, missing email" => sub {
my $t = get_test_object(test => $_[0]);
$t->get_ok('/step3' => form => {entityid => 'https://sp.renater.fr/'})
# neutralize CSRF token check, as we short-circuit the form
$t->app()->hook(before_dispatch => sub { $_[0]->session(csrf_token => 'foo') });
$t->get_ok('/step3' => form => {token => 'foo', entityid => 'https://sp.renater.fr/'})
->status_is(200)
->text_is('html head title' => 'eduGAIN Access Check', 'expected title')
->content_like(qr/Error:[\n\s]+missing parameter 'email'/, 'expected error message');
......@@ -263,7 +284,10 @@ named_subtest "challenge page, valid entityid, missing email" => sub {
named_subtest "challenge page, valid entityid, invalid email" => sub {
my $t = get_test_object(test => $_[0]);
$t->get_ok('/step3' => form => {entityid => 'https://sp.renater.fr/', email => 'foo'})
# neutralize CSRF token check, as we short-circuit the form
$t->app()->hook(before_dispatch => sub { $_[0]->session(csrf_token => 'foo') });
$t->get_ok('/step3' => form => {token => 'foo', entityid => 'https://sp.renater.fr/', email => 'foo'})
->status_is(200)
->text_is('html head title' => 'eduGAIN Access Check', 'expected title')
->content_like(qr/Error:[\n\s]+invalid parameter 'email'/, 'expected error message');
......
[% WRAPPER index.html.tt2 %]
<form class="wizard clearfix" action="[% c.url_for('step3') %]" method="get">
<input type="hidden" name="token" value="[% c.csrf_token() %]">
<div class="steps clearfix">
<ol>
<li class="done">[% c.loc("Select your service provider") %]</li>
......
[% WRAPPER index.html.tt2 %]
<form class="wizard clearfix" action="[% c.url_for('step3') %]" method="get">
<input type="hidden" name="token" value="[% c.csrf_token() %]">
<div class="steps clearfix">
<ol>
<li class="done">[% c.loc("Select your service provider") %]</li>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment