aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/FixMyStreet/App/Controller/Auth
diff options
context:
space:
mode:
Diffstat (limited to 'perllib/FixMyStreet/App/Controller/Auth')
-rw-r--r--perllib/FixMyStreet/App/Controller/Auth/Profile.pm7
-rw-r--r--perllib/FixMyStreet/App/Controller/Auth/Social.pm34
2 files changed, 31 insertions, 10 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Auth/Profile.pm b/perllib/FixMyStreet/App/Controller/Auth/Profile.pm
index a89c6f539..a5dc5d3e7 100644
--- a/perllib/FixMyStreet/App/Controller/Auth/Profile.pm
+++ b/perllib/FixMyStreet/App/Controller/Auth/Profile.pm
@@ -188,9 +188,10 @@ sub generate_token : Path('/auth/generate_token') {
if ($c->get_param('generate_token')) {
my $token = mySociety::AuthToken::random_token();
- $c->user->set_extra_metadata('access_token', $token);
+ my $u = FixMyStreet::DB->resultset("User")->new({ password => $token });
+ $c->user->set_extra_metadata('access_token', $u->password);
$c->user->update;
- $c->stash->{token_generated} = 1;
+ $c->stash->{token_generated} = $c->user->id . '-' . $token;
}
my $action = $c->get_param('2fa_action') || '';
@@ -224,7 +225,7 @@ sub generate_token : Path('/auth/generate_token') {
}
$c->stash->{has_2fa} = $has_2fa ? 1 : 0;
- $c->stash->{existing_token} = $c->user->get_extra_metadata('access_token');
+ $c->stash->{existing_token} = $c->user->get_extra_metadata('access_token') ? 1 : 0;
}
__PACKAGE__->meta->make_immutable;
diff --git a/perllib/FixMyStreet/App/Controller/Auth/Social.pm b/perllib/FixMyStreet/App/Controller/Auth/Social.pm
index 06e67573f..ce94fe256 100644
--- a/perllib/FixMyStreet/App/Controller/Auth/Social.pm
+++ b/perllib/FixMyStreet/App/Controller/Auth/Social.pm
@@ -6,7 +6,7 @@ BEGIN { extends 'Catalyst::Controller'; }
use Net::Facebook::Oauth2;
use Net::Twitter::Lite::WithAPIv1_1;
-use OIDC::Lite::Client::WebServer::Azure;
+use OIDC::Lite::Client::WebServer::AuthCodeFlow;
use URI::Escape;
use mySociety::AuthToken;
@@ -167,7 +167,7 @@ sub oidc : Private {
my $config = $c->cobrand->feature('oidc_login');
- OIDC::Lite::Client::WebServer::Azure->new(
+ OIDC::Lite::Client::WebServer::AuthCodeFlow->new(
id => $config->{client_id},
secret => $config->{secret},
authorize_uri => $config->{auth_uri},
@@ -179,7 +179,9 @@ sub oidc_sign_in : Private {
my ( $self, $c ) = @_;
$c->detach( '/page_error_403_access_denied', [] ) if FixMyStreet->config('SIGNUPS_DISABLED');
- $c->detach( '/page_error_400_bad_request', [] ) unless $c->cobrand->feature('oidc_login');
+
+ my $cfg = $c->cobrand->feature('oidc_login');
+ $c->detach( '/page_error_400_bad_request', [] ) unless $cfg;
my $oidc = $c->forward('oidc');
my $nonce = $self->generate_nonce();
@@ -190,6 +192,15 @@ sub oidc_sign_in : Private {
extra => {
response_mode => 'form_post',
nonce => $nonce,
+ # auth_extra_params provides a way to pass custom parameters
+ # to the OIDC endpoint for the intial authentication request.
+ # This allows, for example, a custom scope to be used,
+ # or the `hd` parameter which customises the appearance of
+ # the login form.
+ # This is primarily useful for Google G Suite authentication - see
+ # available parameters here:
+ # https://developers.google.com/identity/protocols/oauth2/openid-connect#authenticationuriparameters
+ %{ $cfg->{auth_extra_params} || {} } ,
},
);
@@ -201,14 +212,14 @@ sub oidc_sign_in : Private {
# The OIDC endpoint may require a specific URI to be called to log the user
# out when they log out of FMS.
- if ( my $redirect_uri = $c->cobrand->feature('oidc_login')->{logout_uri} ) {
+ if ( my $redirect_uri = $cfg->{logout_uri} ) {
$redirect_uri .= "?post_logout_redirect_uri=";
$redirect_uri .= URI::Escape::uri_escape( $c->uri_for('/auth/sign_out') );
$oauth{logout_redirect_uri} = $redirect_uri;
}
# The OIDC endpoint may provide a specific URI for changing the user's password.
- if ( my $password_change_uri = $c->cobrand->feature('oidc_login')->{password_change_uri} ) {
+ if ( my $password_change_uri = $cfg->{password_change_uri} ) {
$oauth{change_password_uri} = $oidc->uri_to_redirect(
uri => $password_change_uri,
redirect_uri => $c->uri_for('/auth/OIDC'),
@@ -279,6 +290,7 @@ sub oidc_callback: Path('/auth/OIDC') : Args(0) {
eval {
$id_token = $oidc->get_access_token(
code => $c->get_param('code'),
+ redirect_uri => $c->uri_for('/auth/OIDC')
);
};
if ($@) {
@@ -294,10 +306,18 @@ sub oidc_callback: Path('/auth/OIDC') : Args(0) {
# check that the nonce matches what we set in the user session
$c->detach('/page_error_500_internal_error', ['invalid id_token']) unless $id_token->payload->{nonce} eq $c->session->{oauth}{nonce};
+ if (my $domains = $c->cobrand->feature('oidc_login')->{allowed_domains}) {
+ # Check that the hd payload is present in the token and matches the
+ # list of allowed domains from the config
+ my $hd = $id_token->payload->{hd};
+ my %allowed_domains = map { $_ => 1} @$domains;
+ $c->detach('oauth_failure') unless $allowed_domains{$hd};
+ }
+
# Some claims need parsing into a friendlier format
- # XXX check how much of this is Westminster/Azure-specific
- my $name = join(" ", $id_token->payload->{given_name}, $id_token->payload->{family_name});
+ my $name = $id_token->payload->{name} || join(" ", $id_token->payload->{given_name}, $id_token->payload->{family_name});
my $email = $id_token->payload->{email};
+
# WCC Azure provides a single email address as an array for some reason
my $emails = $id_token->payload->{emails};
if ($emails && @$emails) {