From d8907f11f5c255727b8a814746a0114e5c62e30a Mon Sep 17 00:00:00 2001 From: Matthias Andreas Benkard Date: Sun, 4 May 2014 18:35:10 +0200 Subject: Support Google Apps authentication. --- www/authenticate.pl | 48 +++++++++++++++++++++++++++++++++++++++++++++++ www/common.pl | 13 +++++++++++++ www/failed-login.html | 17 +++++++++++++++++ www/failed-login.js | 1 + www/logged_in_p.pl | 3 ++- www/login.pl | 42 +++++++++++++++++++++++++++++++---------- www/provision.js | 6 +++--- www/sign.pl | 5 +++-- www/successful-login.html | 17 +++++++++++++++++ www/successful-login.js | 1 + 10 files changed, 137 insertions(+), 16 deletions(-) create mode 100755 www/authenticate.pl create mode 100644 www/failed-login.html create mode 100644 www/failed-login.js create mode 100644 www/successful-login.html create mode 100644 www/successful-login.js (limited to 'www') diff --git a/www/authenticate.pl b/www/authenticate.pl new file mode 100755 index 0000000..a36ad02 --- /dev/null +++ b/www/authenticate.pl @@ -0,0 +1,48 @@ +#! /usr/bin/env perl +# Copyright 2012, Matthias Andreas Benkard . + +use common::sense; +#use Modern::Perl 2011; +use Modern::Perl; + +use JSON; + +use CGI; +use CGI::Fast; +use CGI::Session; + +use Net::Google::FederatedLogin; + +do "common.pl"; + +while (my $cgi = new CGI::Fast) { + load_config(); + + my $claimed_email = $cgi->param('email'); + + my $g = Net::Google::FederatedLogin->new( + claimed_id => $claimed_email, + return_to => reluri($cgi, 'login.pl'), + extensions => [{ns => 'ax', + uri => 'http://openid.net/srv/ax/1.0', + attributes => {mode => 'fetch_request', + required => 'email', + type => {email => 'http://axschema.org/contact/email'}}}] + ); + + my $cookie = $cgi->cookie('mulkid_session'); + my $session = new CGI::Session("driver:File", $cookie, {Directory=>"/tmp"}); + $session->param('claimed_email', $claimed_email); + if ($cookie) { + print $cgi->redirect(-url => $g->get_auth_url()); + } else { + my $cookie = $cgi->cookie(-name => 'mulkid_session', + -value => $session->id, + -expires => '+1d', + #-secure => 1, + -httponly => 1, + #-domain => '.'.$::MULKONF->{realm} + ); + print $cgi->redirect(-cookie => $cookie, -url => $g->get_auth_url()); + } +} diff --git a/www/common.pl b/www/common.pl index aa86e47..3f3a5b0 100644 --- a/www/common.pl +++ b/www/common.pl @@ -6,6 +6,7 @@ use common::sense; use Modern::Perl; use Mail::ExpandAliases; +use URI; sub load_config() { $::MULKONF = { }; @@ -13,6 +14,8 @@ sub load_config() { } sub email_users($) { + return @_ + if $::MULKONF->{auth_type} eq 'google'; my ($email) = @_; my $alias; if ($email =~ /^(.*?)@/) { $alias = $1; } @@ -25,3 +28,13 @@ sub email_users($) { return ($alias); } } + +sub reluri($$) { + my ($cgi, $x) = @_; + my $uri = URI->new($cgi->url(-full=>1)); + my @path = $uri->path_segments; + pop @path; + push @path, $x; + $uri->path_segments(@path); + return "$uri"; +} diff --git a/www/failed-login.html b/www/failed-login.html new file mode 100644 index 0000000..9838d21 --- /dev/null +++ b/www/failed-login.html @@ -0,0 +1,17 @@ + + + + MulkyID Persona Login + + + + + + + + +

MulkyID Persona Login

+ +

Login failure!

+ + diff --git a/www/failed-login.js b/www/failed-login.js new file mode 100644 index 0000000..3618002 --- /dev/null +++ b/www/failed-login.js @@ -0,0 +1 @@ +navigator.id.raiseAuthenticationFailure(); diff --git a/www/logged_in_p.pl b/www/logged_in_p.pl index 2e648fc..73c9d1c 100755 --- a/www/logged_in_p.pl +++ b/www/logged_in_p.pl @@ -4,6 +4,7 @@ use common::sense; use Modern::Perl; +use syntax 'junction'; use JSON; @@ -35,7 +36,7 @@ while (my $cgi = new CGI::Fast) { my $email = $cgi->param('email') or die "No email address supplied"; my $session_user = $session->param('user'); - if ($session_user ~~ [email_users($email)]) { + if (any(email_users($email)) eq $session_user) { say encode_json({logged_in_p => 1}); } else { say encode_json({logged_in_p => 0}); diff --git a/www/login.pl b/www/login.pl index 9e0467e..a2f06c4 100755 --- a/www/login.pl +++ b/www/login.pl @@ -12,11 +12,12 @@ use CGI::Fast; use CGI::Session; use Mail::IMAPTalk ; +use Net::Google::FederatedLogin; #use IO::Socket::SSL; do "common.pl"; -sub check_password($$) { +sub check_imap_password($$) { my ($user, $password) = @_; #my $socket = IO::Socket::SSL->new('imap.googlemail.com:imaps'); @@ -38,7 +39,7 @@ sub check_password($$) { while (my $cgi = new CGI::Fast) { - load_config(); + load_config; my $cookie = $cgi->cookie('mulkid_session'); my $session; @@ -58,17 +59,38 @@ while (my $cgi = new CGI::Fast) { -cookie => $cookie); } - my $email = $cgi->param('email') or die "No email address provided"; - my $password = $cgi->param('password') or die "Empty password"; + my $email = $cgi->param('email') or die "No email address provided"; - for my $user (email_users($email)) { - #say STDERR "Trying user: $user"; - if (check_password($user, $password)) { - $session->param('user', $user); - say encode_json({user => $user}); + for ($::MULKONF->{auth_type}) { + when ('imap') { + my $password = $cgi->param('password') or die "Empty password"; + for my $user (email_users($email)) { + #say STDERR "Trying user: $user"; + if (check_imap_password($user, $password)) { + $session->param('user', $user); + #say encode_json({user => $user}); + print $cgi->redirect(-url => reluri($cgi, 'successful-login.html')); + exit 0; + } + } + } + when ('google') { + my $g = Net::Google::FederatedLogin->new( + cgi => $cgi, + return_to => $cgi->url() + ); + $g->verify_auth or die "Could not verify the OpenID assertion!"; + my $ext = $g->get_extension('http://openid.net/srv/ax/1.0'); + my $verified_email = $ext->get_parameter('value.email'); + $session->param('user', $verified_email); + #say encode_json({user => $user}); + print $cgi->redirect(-url => reluri($cgi, 'successful-login.html')); exit 0; } + default { + die "Invalid auth_type. Check MulkyID configuration!"; + } } - die "Could not authenticate with mail server."; + die "Could not authenticate."; } diff --git a/www/provision.js b/www/provision.js index 5441bce..4113be0 100644 --- a/www/provision.js +++ b/www/provision.js @@ -10,7 +10,7 @@ jQuery(function($) { $.ajax({ type: 'POST', crossDomain: true, - url: '/browserid/logged_in_p.pl', + url: 'logged_in_p.pl', dataType: 'json', data: { email: email }, success: function(data, status, xhr) { @@ -19,7 +19,7 @@ jQuery(function($) { console.log('* Not logged in.'); return navigator.id.raiseProvisioningFailure('user is not authenticated as target user'); } else { - thunk(); + return thunk(); } }, error: function(data, status, xhr) { @@ -40,7 +40,7 @@ jQuery(function($) { dataType: 'json', data: { email: email, pubkey: JSON.stringify(pubkey), duration: cert_duration }, success: function(data, status, xhr) { - console.log('Success!'); + console.log('Success!'); console.log(data); navigator.id.registerCertificate(data.signature); }, diff --git a/www/sign.pl b/www/sign.pl index a0fd11f..b16ff86 100755 --- a/www/sign.pl +++ b/www/sign.pl @@ -4,6 +4,7 @@ use common::sense; use Modern::Perl; +use syntax 'junction'; use JSON; @@ -85,8 +86,8 @@ while (my $cgi = new CGI::Fast) { my $domain; if ($email =~ /^(.*?)@(.*)/) { $domain = $2; } - die "User is not authorized to use this email address" - unless ($session_user ~~ [email_users($email)]); + die "User $session_user is not authorized to use this email address ($email)" + unless any(email_users($email)) eq $session_user; my $sig = sign $key, decode_json($user_pubkey), $email, $duration, $domain; say encode_json({signature => $sig}); diff --git a/www/successful-login.html b/www/successful-login.html new file mode 100644 index 0000000..4f0886c --- /dev/null +++ b/www/successful-login.html @@ -0,0 +1,17 @@ + + + + MulkyID Persona Login + + + + + + + + +

MulkyID Persona Login

+ +

Success!

+ + diff --git a/www/successful-login.js b/www/successful-login.js new file mode 100644 index 0000000..bad7e39 --- /dev/null +++ b/www/successful-login.js @@ -0,0 +1 @@ +navigator.id.completeAuthentication(); -- cgit v1.2.3