aboutsummaryrefslogtreecommitdiffstats
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/Mock/OpenIDConnect.pm48
-rw-r--r--t/app/controller/auth_social.t62
2 files changed, 102 insertions, 8 deletions
diff --git a/t/Mock/OpenIDConnect.pm b/t/Mock/OpenIDConnect.pm
index ba7d03b1d..61a67f329 100644
--- a/t/Mock/OpenIDConnect.pm
+++ b/t/Mock/OpenIDConnect.pm
@@ -27,6 +27,11 @@ sub dispatch_request {
return [ 200, [ 'Content-Type' => 'text/html' ], [ 'OpenID Connect login page' ] ];
},
+ sub (GET + /oauth2/v2.0/authorize_google + ?*) {
+ my ($self) = @_;
+ return [ 200, [ 'Content-Type' => 'text/html' ], [ 'OpenID Connect login page' ] ];
+ },
+
sub (GET + /oauth2/v2.0/logout + ?*) {
my ($self) = @_;
return [ 200, [ 'Content-Type' => 'text/html' ], [ 'OpenID Connect logout page' ] ];
@@ -72,6 +77,49 @@ sub dispatch_request {
my $json = $self->json->encode($data);
return [ 200, [ 'Content-Type' => 'application/json' ], [ $json ] ];
},
+
+ sub (POST + /oauth2/v2.0/token_google + ?*) {
+ my ($self) = @_;
+ my $header = {
+ typ => "JWT",
+ alg => "RS256",
+ kid => "XXXfakeKEY1234",
+ };
+ my $now = DateTime->now->epoch;
+ my $payload = {
+ exp => $now + 3600,
+ nbf => $now,
+ locale => 'en-GB',
+ ver => "1.0",
+ iss => 'https://accounts.google.com',
+ sub => "my_google_user_id",
+ aud => "example_client_id",
+ iat => $now,
+ auth_time => $now,
+ given_name => "Andy",
+ family_name => "Dwyer",
+ name => "Andy Dwyer",
+ nonce => 'MyAwesomeRandomValue',
+ hd => 'example.org',
+ };
+ $payload->{email} = 'pkg-tappcontrollerauth_socialt-oidc_google@example.org' if $self->returns_email;
+ $payload->{email_verified} = JSON->true if $self->returns_email;
+ my $signature = "dummy";
+ my $id_token = join(".", (
+ encode_base64($self->json->encode($header), ''),
+ encode_base64($self->json->encode($payload), ''),
+ encode_base64($signature, '')
+ ));
+ my $data = {
+ id_token => $id_token,
+ token_type => "Bearer",
+ not_before => $now,
+ id_token_expires_in => 3600,
+ profile_info => encode_base64($self->json->encode({}), ''),
+ };
+ my $json = $self->json->encode($data);
+ return [ 200, [ 'Content-Type' => 'application/json' ], [ $json ] ];
+ },
}
__PACKAGE__->run_if_script;
diff --git a/t/app/controller/auth_social.t b/t/app/controller/auth_social.t
index 200863029..e56fcda98 100644
--- a/t/app/controller/auth_social.t
+++ b/t/app/controller/auth_social.t
@@ -15,9 +15,12 @@ FixMyStreet::App->log->disable('info');
END { FixMyStreet::App->log->enable('info'); }
my $body = $mech->create_body_ok(2504, 'Westminster City Council');
+my $body2 = $mech->create_body_ok(2508, 'Hackney Council');
my ($report) = $mech->create_problems_for_body(1, $body->id, 'My Test Report');
my $test_email = $report->user->email;
+my ($report2) = $mech->create_problems_for_body(1, $body2->id, 'My Test Report');
+my $test_email2 = $report->user->email;
my $contact = $mech->create_contact_ok(
body_id => $body->id, category => 'Damaged bin', email => 'BIN',
@@ -26,11 +29,21 @@ my $contact = $mech->create_contact_ok(
{ code => 'bin_service', description => 'Service needed', required => 'False' },
]
);
+$mech->create_contact_ok(
+ body_id => $body2->id, category => 'Damaged bin', email => 'BIN',
+ extra => [
+ { code => 'bin_type', description => 'Type of bin', required => 'True' },
+ { code => 'bin_service', description => 'Service needed', required => 'False' },
+ ]
+);
# Two options, incidentally, so that the template "Only one option, select it"
# code doesn't kick in and make the tests pass
my $contact2 = $mech->create_contact_ok(
body_id => $body->id, category => 'Whatever', email => 'WHATEVER',
);
+$mech->create_contact_ok(
+ body_id => $body2->id, category => 'Whatever', email => 'WHATEVER',
+);
my $resolver = Test::MockModule->new('Email::Valid');
my $social = Test::MockModule->new('FixMyStreet::App::Controller::Auth::Social');
@@ -88,6 +101,38 @@ for my $test (
user_extras => [
[westminster_account_id => "1c304134-ef12-c128-9212-123908123901"],
],
+}, {
+ type => 'oidc',
+ config => {
+ ALLOWED_COBRANDS => 'hackney',
+ MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => {
+ anonymous_account => {
+ hackney => 'test',
+ },
+ oidc_login => {
+ hackney => {
+ client_id => 'example_client_id',
+ secret => 'example_secret_key',
+ auth_uri => 'http://oidc.example.org/oauth2/v2.0/authorize_google',
+ token_uri => 'http://oidc.example.org/oauth2/v2.0/token_google',
+ allowed_domains => [ 'example.org' ],
+ }
+ }
+ }
+ },
+ email => $mech->uniquify_email('oidc_google@example.org'),
+ uid => "hackney:example_client_id:my_google_user_id",
+ mock => 't::Mock::OpenIDConnect',
+ mock_hosts => ['oidc.example.org'],
+ host => 'oidc.example.org',
+ error_callback => '/auth/OIDC?error=ERROR',
+ success_callback => '/auth/OIDC?code=response-code&state=login',
+ redirect_pattern => qr{oidc\.example\.org/oauth2/v2\.0/authorize_google},
+ pc => 'E8 1DY',
+ # Need to use a different report that's within Hackney
+ report => $report2,
+ report_email => $test_email2,
}
) {
@@ -100,6 +145,7 @@ for my $state ( 'refused', 'no email', 'existing UID', 'okay' ) {
next if $page eq 'update' && !$test->{update};
subtest "test $test->{type} '$state' login for page '$page'" => sub {
+ my $test_report = $test->{report} || $report;
# Lots of user changes happening here, make sure we don't confuse
# Catalyst with a cookie session user that no longer exists
$mech->log_out_ok;
@@ -115,9 +161,9 @@ for my $state ( 'refused', 'no email', 'existing UID', 'okay' ) {
$mech->delete_user($test->{email});
}
if ($page eq 'my' && $state eq 'existing UID') {
- $report->update({ user_id => FixMyStreet::DB->resultset( 'User' )->find( { email => $test->{email} } )->id });
+ $test_report->update({ user_id => FixMyStreet::DB->resultset( 'User' )->find( { email => $test->{email} } )->id });
} else {
- $report->update({ user_id => FixMyStreet::DB->resultset( 'User' )->find( { email => $test_email } )->id });
+ $test_report->update({ user_id => FixMyStreet::DB->resultset( 'User' )->find( { email => ($report->{test_email} || $test_email) } )->id });
}
# Set up a mock to catch (most, see below) requests to the OAuth API
@@ -139,7 +185,7 @@ for my $state ( 'refused', 'no email', 'existing UID', 'okay' ) {
$mech->get_ok('/my');
} elsif ($page eq 'report') {
$mech->get_ok('/');
- $mech->submit_form_ok( { with_fields => { pc => 'SW1A1AA' } }, "submit location" );
+ $mech->submit_form_ok( { with_fields => { pc => $test->{pc} || 'SW1A1AA' } }, "submit location" );
$mech->follow_link_ok( { text_regex => qr/skip this step/i, }, "follow 'skip this step' link" );
$mech->submit_form(with_fields => {
category => 'Damaged bin',
@@ -150,7 +196,7 @@ for my $state ( 'refused', 'no email', 'existing UID', 'okay' ) {
bin_type => 'Salt bin',
};
} else {
- $mech->get_ok('/report/' . $report->id);
+ $mech->get_ok('/report/' . $test_report->id);
$fields = {
update => 'Test update',
};
@@ -243,17 +289,17 @@ for my $state ( 'refused', 'no email', 'existing UID', 'okay' ) {
}
}
if ($state eq 'existing UID') {
- my $report_id = $report->id;
- $mech->content_contains( $report->title );
+ my $report_id = $test_report->id;
+ $mech->content_contains( $test_report->title );
$mech->content_contains( "/report/$report_id" );
}
- if ($test->{type} eq 'oidc') {
+ if ($test->{type} eq 'oidc' && $test->{password_change_pattern}) {
ok $mech->find_link( text => 'Change password', url_regex => $test->{password_change_pattern} );
}
}
$mech->get('/auth/sign_out');
- if ($test->{type} eq 'oidc' && $state ne 'refused' && $state ne 'no email') {
+ if ($test->{type} eq 'oidc' && $test->{logout_redirect_pattern} && $state ne 'refused' && $state ne 'no email') {
# XXX the 'no email' situation is skipped because of some confusion
# with the hosts/sessions that I've not been able to get to the bottom of.
# The code does behave as expected when testing manually, however.