aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Benkard <matthias.benkard@egym.de>2015-04-13 14:16:43 +0000
committerMatthias Andreas Benkard <code@mail.matthias.benkard.de>2015-04-23 21:55:01 +0200
commitfaea34e5c94922645b337bdeb5db32871eb1fde9 (patch)
treec5456c78967238b87a7195ce078ea4ee5edd83a8
parent39f38b65fd828c1dd29361a7d61d8685834cf229 (diff)
Support Google OpenID Connect.
-rw-r--r--build.PL6
-rwxr-xr-xwww/authenticate.pl31
-rwxr-xr-xwww/login.pl53
-rw-r--r--www/provision.js2
4 files changed, 69 insertions, 23 deletions
diff --git a/build.PL b/build.PL
index 17d2536..6e008d3 100644
--- a/build.PL
+++ b/build.PL
@@ -25,7 +25,11 @@ my $build = Net::MulkyID::Builder->new
"Modern::Perl" => 0,
"Time::HiRes" => 0,
"Syntax::Keyword::Junction" => 0,
- "Net::Google::FederatedLogin" => 0,
+ "OIDC::Lite" => 0,
+ "OIDC::Lite::Client::WebServer" => 0,
+ "OIDC::Lite::Model::IDToken" => 0,
+ "LWP::UserAgent" => 0,
+ "HTTP::Request" => 0
},
build_requires => {
"LWP::Simple" => 0,
diff --git a/www/authenticate.pl b/www/authenticate.pl
index ed0fb95..3c865ac 100755
--- a/www/authenticate.pl
+++ b/www/authenticate.pl
@@ -10,7 +10,8 @@ use JSON;
use CGI;
use CGI::Fast;
-use Net::Google::FederatedLogin;
+use OIDC::Lite;
+use OIDC::Lite::Client::WebServer;
do "common.pl";
@@ -21,23 +22,31 @@ while (my $cgi = new CGI::Fast) {
my $realdomain = $::MULKONF->{real_domain};
my $claimed_email = $cgi->param('email');
- $claimed_email =~ s/\@$fakedomain/\@$realdomain/ if $fakedomain;
+ $claimed_email =~ s/\@$fakedomain/\@$realdomain/ if $fakedomain && $claimed_email;
given (my $_ = $::MULKONF->{auth_type}) {
when ('imap') {
print $cgi->redirect(reluri($cgi, "authenticate-with-password.html?email=$claimed_email"));
}
when ('google') {
- 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 $oidc_client = OIDC::Lite::Client::WebServer->new(
+ id => $::MULKONF->{'google_oauth2_client_id'},
+ secret => $::MULKONF->{'google_oauth2_client_secret'},
+ authorize_uri => 'https://accounts.google.com/o/oauth2/auth',
+ access_token_uri => 'https://accounts.google.com/o/oauth2/token'
);
- print $cgi->redirect($g->get_auth_url());
+ # FIXME: Make `state` a unique, random session token! (Maybe a
+ # signed, timestamped web token, so stateless?)
+ print $cgi->redirect($oidc_client->uri_to_redirect(
+ redirect_uri => reluri($cgi, 'login.pl'),
+ scope => 'openid email',
+ state => '',
+ extra => {
+ access_type => 'online',
+ login_hint => $claimed_email,
+ response_type => 'code'
+ }
+ ));
}
default {
die "Invalid auth_type! " . $::MULKONF->{auth_type};
diff --git a/www/login.pl b/www/login.pl
index 363f243..fe1729d 100755
--- a/www/login.pl
+++ b/www/login.pl
@@ -16,9 +16,15 @@ use CGI::Fast;
use CGI::Cookie;
use Mail::IMAPTalk ;
-use Net::Google::FederatedLogin;
#use IO::Socket::SSL;
+use OIDC::Lite;
+use OIDC::Lite::Client::WebServer;
+use OIDC::Lite::Model::IDToken;
+
+use LWP::UserAgent;
+use HTTP::Request;
+
do "common.pl";
sub check_imap_password($$) {
@@ -72,18 +78,45 @@ while (my $cgi = new CGI::Fast) {
die "Could not authenticate.";
}
when ('google') {
- my $g = Net::Google::FederatedLogin->new(
- cgi => $cgi,
- return_to => reluri($cgi, "login.pl")
+ my $code = $cgi->param('code') or die "Authorization code is missing.";
+ my $oidc_client = OIDC::Lite::Client::WebServer->new(
+ id => $::MULKONF->{'google_oauth2_client_id'},
+ secret => $::MULKONF->{'google_oauth2_client_secret'},
+ authorize_uri => 'https://accounts.google.com/o/oauth2/auth',
+ access_token_uri => 'https://accounts.google.com/o/oauth2/token'
);
- $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');
- my $fakedomain = $::MULKONF->{fake_domain};
- my $realdomain = $::MULKONF->{real_domain};
+
+ # Acquire access token.
+ my $token = $oidc_client->get_access_token(
+ code => $code,
+ redirect_uri => reluri($cgi, 'login.pl')
+ );
+ unless ($token) {
+ my $oidc_response = $oidc_client->last_response;
+ die "Could not acquire access token: " . $oidc_response->code . " (" . $oidc_response->content . ")";
+ }
+
+ # Extract ID token.
+ my $id_token = OIDC::Lite::Model::IDToken->load($token->id_token);
+
+ # Acquire user information.
+ my $userinfo_request = HTTP::Request->new(GET => 'https://www.googleapis.com/oauth2/v3/userinfo');
+ $userinfo_request->header(Authorization => "Bearer " . $token->access_token);
+ my $userinfo_response = LWP::UserAgent->new->request($userinfo_request);
+ unless ($userinfo_response->is_success) {
+ die "Could not acquire user information: " . $userinfo_response->code . " (" . $userinfo_response->content . ")";
+ }
+ my $userinfo = decode_json($userinfo_response->content);
+
+ # Verify e-mail and sign user's identity assertion.
+ unless ($userinfo->{'email_verified'}) {
+ die "User email is not verified."
+ }
+ my $verified_email = $userinfo->{'email'};
+ my $fakedomain = $::MULKONF->{'fake_domain'};
+ my $realdomain = $::MULKONF->{'real_domain'};
$verified_email =~ s/\@$realdomain/\@$fakedomain/ if $fakedomain;
print $cgi->redirect(-cookie => cookie_for_user($verified_email), -url => reluri($cgi, 'successful-login.html'));
- exit 0;
}
default {
die "Invalid auth_type. Check MulkyID configuration!";
diff --git a/www/provision.js b/www/provision.js
index 4113be0..ad6971e 100644
--- a/www/provision.js
+++ b/www/provision.js
@@ -36,7 +36,7 @@ jQuery(function($) {
$.ajax({
type: 'POST',
crossDomain: true,
- url: '/browserid/sign.pl',
+ url: 'sign.pl',
dataType: 'json',
data: { email: email, pubkey: JSON.stringify(pubkey), duration: cert_duration },
success: function(data, status, xhr) {