aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.PL2
-rwxr-xr-xlib/Net/MulkyID/Setup.pm49
-rwxr-xr-xsetup.pl1
-rwxr-xr-xwww/authenticate.pl48
-rw-r--r--www/common.pl13
-rw-r--r--www/failed-login.html17
-rw-r--r--www/failed-login.js1
-rwxr-xr-xwww/logged_in_p.pl3
-rwxr-xr-xwww/login.pl42
-rw-r--r--www/provision.js6
-rwxr-xr-xwww/sign.pl5
-rw-r--r--www/successful-login.html17
-rw-r--r--www/successful-login.js1
13 files changed, 171 insertions, 34 deletions
diff --git a/build.PL b/build.PL
index 342fae0..17d2536 100644
--- a/build.PL
+++ b/build.PL
@@ -24,6 +24,8 @@ my $build = Net::MulkyID::Builder->new
"Mail::IMAPTalk" => 0,
"Modern::Perl" => 0,
"Time::HiRes" => 0,
+ "Syntax::Keyword::Junction" => 0,
+ "Net::Google::FederatedLogin" => 0,
},
build_requires => {
"LWP::Simple" => 0,
diff --git a/lib/Net/MulkyID/Setup.pm b/lib/Net/MulkyID/Setup.pm
index b79f96b..acfe018 100755
--- a/lib/Net/MulkyID/Setup.pm
+++ b/lib/Net/MulkyID/Setup.pm
@@ -1,5 +1,5 @@
#! /usr/bin/env perl
-# Copyright 2012, Matthias Andreas Benkard <code@mail.matthias.benkard.de>.
+# Copyright 2012, 2014, Matthias Andreas Benkard <code@mail.matthias.benkard.de>.
package Net::MulkyID::Setup;
@@ -30,13 +30,13 @@ sub prompt($$) {
}
}
-sub makespec($) {
- my ($key) = @_;
+sub makespec($$) {
+ my ($key, $basepath) = @_;
my ($n, $e, @stuff) = $key->get_key_parameters;
return
encode_json({"public-key" => {e => $e->to_decimal, n => $n->to_decimal, algorithm => "RS"},
- "authentication" => "/browserid/authenticate.html",
- "provisioning" => "/browserid/provision.html"});
+ "authentication" => "$basepath/authenticate.html",
+ "provisioning" => "$basepath/provision.html"});
};
sub setup() {
@@ -49,16 +49,29 @@ sub setup() {
do $conffile;
}
- my $configpath = $::MULKONF->{configpath} // "/etc/mulkyid";
- $configpath = prompt("Where shall I put configuration files?", $configpath);
- my $pemfile = $::MULKONF->{pemfile} // "$configpath/rsa2048.pem";
- $pemfile = prompt("Where shall I put the private key?", $pemfile);
+ my $configpath = $::MULKONF->{configpath} // "/etc/mulkyid";
+ my $pemfile = $::MULKONF->{pemfile} // "$configpath/rsa2048.pem";
+ my $auth_type = $::MULKONF->{auth_type} // "imap";
my $aliases_file = $::MULKONF->{aliases_file} // "/etc/aliases";
- $aliases_file = prompt("Where is the aliases file? Type a single dot for none.", $aliases_file);
- my $imap_server = $::MULKONF->{imap_server} // "localhost";
- $imap_server = prompt("What is the IMAP server's address?", $imap_server);
- my $imap_port = $::MULKONF->{imap_port} // 143;
- $imap_port = int(prompt("What is the IMAP server's port?", $imap_port));
+ my $imap_server = $::MULKONF->{imap_server} // "localhost";
+ my $imap_port = $::MULKONF->{imap_port} // 143;
+ my $basepath = $::MULKONF->{basepath} // "/browserid";
+ $configpath = prompt("Where shall I put configuration files?", $configpath);
+ $pemfile = prompt("Where shall I put the private key?", $pemfile);
+ $auth_type = prompt("How will users authenticate? (imap, google)", $auth_type);
+ $basepath = int(prompt("What will be the web-facing base path for IdP files and scripts?", $basepath));
+ for ($auth_type) {
+ when ("imap") {
+ $aliases_file = prompt("Where is the aliases file? Type a single dot for none.", $aliases_file);
+ $imap_server = prompt("What is the IMAP server's address?", $imap_server);
+ $imap_port = int(prompt("What is the IMAP server's port?", $imap_port));
+ }
+ when ("google") {
+ }
+ default {
+ die "Invalid authentication type";
+ }
+ }
say "OK.";
@@ -81,8 +94,7 @@ sub setup() {
} else {
say "Generating private key...";
$key = Crypt::OpenSSL::RSA->generate_key(2048);
- make_path($configpath)
- or die "Could not create directory: $configpath";
+ make_path($configpath);
write_file($pemfile, $key->get_private_key_string())
or die "Could not write private key to $pemfile: $!";
say "Private key saved to: $pemfile";
@@ -90,7 +102,7 @@ sub setup() {
}
# Generate spec file.
- write_file("browserid.json", makespec $key)
+ write_file("browserid.json", makespec($key, $basepath))
or die "Could not write spec to browserid.json: $!";
say "Persona spec file saved to: browserid.json";
@@ -100,7 +112,8 @@ sub setup() {
pemfile => $pemfile,
aliases_file => $aliases_file,
imap_server => $imap_server,
- imap_port => $imap_port
+ imap_port => $imap_port,
+ basepath => $basepath,
};
write_file($conffile, <<EOF
#! /usr/bin/env perl
diff --git a/setup.pl b/setup.pl
index 09f8d20..7ec038b 100755
--- a/setup.pl
+++ b/setup.pl
@@ -1,4 +1,5 @@
#! /usr/bin/env perl
system "perl build.PL";
+system "perl Build installdeps";
system "perl Build";
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 <code@mail.matthias.benkard.de>.
+
+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 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>MulkyID Persona Login</title>
+
+ <script type="text/javascript" src="https://login.persona.org/include.js"></script>
+ <script type="text/javascript" src="https://login.persona.org/authentication_api.js"></script>
+
+ <script type="text/javascript" src="jquery/jquery.js"></script>
+ <script type="text/javascript" src="failed-login.js"></script>
+</head>
+<body>
+ <h1>MulkyID Persona Login</h1>
+
+ <p>Login failure!</p>
+</body>
+</html>
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 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>MulkyID Persona Login</title>
+
+ <script type="text/javascript" src="https://login.persona.org/include.js"></script>
+ <script type="text/javascript" src="https://login.persona.org/authentication_api.js"></script>
+
+ <script type="text/javascript" src="jquery/jquery.js"></script>
+ <script type="text/javascript" src="successful-login.js"></script>
+</head>
+<body>
+ <h1>MulkyID Persona Login</h1>
+
+ <p>Success!</p>
+</body>
+</html>
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();