forked from lix-project/hydra
Add basic Persona support
This allows users to sign in to Hydra using Mozilla Persona accounts. When a user first sign in, a row in the Users table for the given Persona identity (an email address) is created automatically. To do: figure out how to deal with legacy accounts.
This commit is contained in:
parent
b46f2134e0
commit
c08fc6ce1e
|
@ -8,6 +8,8 @@ use Crypt::RandPasswd;
|
||||||
use Digest::SHA1 qw(sha1_hex);
|
use Digest::SHA1 qw(sha1_hex);
|
||||||
use Hydra::Helper::Nix;
|
use Hydra::Helper::Nix;
|
||||||
use Hydra::Helper::CatalystUtils;
|
use Hydra::Helper::CatalystUtils;
|
||||||
|
use LWP::UserAgent;
|
||||||
|
use JSON;
|
||||||
|
|
||||||
|
|
||||||
__PACKAGE__->config->{namespace} = '';
|
__PACKAGE__->config->{namespace} = '';
|
||||||
|
@ -70,6 +72,43 @@ sub logout_GET {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sub persona_login :Path('/persona-login') Args(0) {
|
||||||
|
my ($self, $c) = @_;
|
||||||
|
$c->stash->{json} = {};
|
||||||
|
die if $c->request->method ne "POST";
|
||||||
|
|
||||||
|
my $assertion = $c->req->params->{assertion} or die;
|
||||||
|
|
||||||
|
my $ua = new LWP::UserAgent;
|
||||||
|
my $response = $ua->post(
|
||||||
|
'https://verifier.login.persona.org/verify',
|
||||||
|
{ assertion => $assertion,
|
||||||
|
audience => "http://localhost:3000/"
|
||||||
|
});
|
||||||
|
Catalyst::Exception->throw("Did not get a response from Persona.") unless $response->is_success;
|
||||||
|
|
||||||
|
my $d = decode_json($response->decoded_content) or die;
|
||||||
|
Catalyst::Exception->throw("Persona says: $d->{reason}") if $d->{status} ne "okay";
|
||||||
|
|
||||||
|
my $email = $d->{email} or die;
|
||||||
|
|
||||||
|
my $user = $c->find_user({ username => $email });
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
$c->model('DB::Users')->create(
|
||||||
|
{ username => $email
|
||||||
|
, password => "!"
|
||||||
|
, emailaddress => $email,
|
||||||
|
});
|
||||||
|
$user = $c->find_user({ username => $email }) or die;
|
||||||
|
}
|
||||||
|
|
||||||
|
$c->set_authenticated($user);
|
||||||
|
|
||||||
|
$c->stash->{json}->{result} = "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
sub captcha :Local Args(0) {
|
sub captcha :Local Args(0) {
|
||||||
my ($self, $c) = @_;
|
my ($self, $c) = @_;
|
||||||
$c->create_captcha();
|
$c->create_captcha();
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
<head>
|
<head>
|
||||||
<title>Hydra - [% HTML.escape(title) %]</title>
|
<title>Hydra - [% HTML.escape(title) %]</title>
|
||||||
|
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||||
|
|
||||||
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
|
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
|
||||||
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/jquery-ui.min.js"></script>
|
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/jquery-ui.min.js"></script>
|
||||||
|
|
||||||
|
@ -95,13 +97,47 @@
|
||||||
<small>
|
<small>
|
||||||
<em><a href="http://nixos.org/hydra" target="_new">Hydra</a> [% HTML.escape(version) %] (using [% HTML.escape(nixVersion) %]).</em>
|
<em><a href="http://nixos.org/hydra" target="_new">Hydra</a> [% HTML.escape(version) %] (using [% HTML.escape(nixVersion) %]).</em>
|
||||||
[% IF c.user_exists %]
|
[% IF c.user_exists %]
|
||||||
You are logged in as <tt>[% c.user.username %]</tt>.
|
You are logged in as <tt>[% HTML.escape(c.user.username) %]</tt>.
|
||||||
[% END %]
|
[% END %]
|
||||||
</small>
|
</small>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script src="https://login.persona.org/include.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
navigator.id.watch({
|
||||||
|
loggedInUser: [% c.user_exists ? '"' _ HTML.escape(c.user.username) _ '"' : "null" %],
|
||||||
|
onlogin: function(assertion) {
|
||||||
|
$.post("[% c.uri_for('/persona-login') %]", { assertion: assertion })
|
||||||
|
.done(function(data) {
|
||||||
|
if (data.error)
|
||||||
|
bootbox.alert("Login failed: " + data.error);
|
||||||
|
else
|
||||||
|
window.location.reload();
|
||||||
|
})
|
||||||
|
.fail(function() { bootbox.alert("Server request failed!"); });
|
||||||
|
},
|
||||||
|
onlogout: function() {
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: '/logout',
|
||||||
|
success: function(res, status, xhr) { window.location.reload(); },
|
||||||
|
error: function(xhr, status, err) { alert("Logout failure: " + err); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#persona-signin").click(function() {
|
||||||
|
navigator.id.request();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#persona-signout").click(function() {
|
||||||
|
navigator.id.logout();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -13,8 +13,7 @@ You can <a href="[% c.uri_for('/logout') %]">logout</a> here.
|
||||||
c.uri_for('/register') %]">register</a> first.</p>
|
c.uri_for('/register') %]">register</a> first.</p>
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<br/>
|
<!--
|
||||||
|
|
||||||
<form class="form-horizontal" method="post" action="[% c.uri_for('/login') %]">
|
<form class="form-horizontal" method="post" action="[% c.uri_for('/login') %]">
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
|
@ -38,6 +37,7 @@ c.uri_for('/register') %]">register</a> first.</p>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
-->
|
||||||
|
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[% BLOCK menuItem %]
|
[% BLOCK menuItem %]
|
||||||
<li class="[% IF "${root}${curUri}" == uri %]active[% END %]" [% IF confirmmsg %]onclick="javascript:return confirm('[% confirmmsg %]')"[% END %]>
|
<li class="[% IF "${root}${curUri}" == uri %]active[% END %]" [% IF confirmmsg %]onclick="javascript:return confirm('[% confirmmsg %]')"[% END %]>
|
||||||
<a href="[% uri %]">[% title %]</a>
|
<a [% HTML.attributes(href => uri) %]>[% title %]</a>
|
||||||
</li>
|
</li>
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
|
@ -198,9 +198,13 @@
|
||||||
|
|
||||||
[% IF c.user_exists %]
|
[% IF c.user_exists %]
|
||||||
[% INCLUDE menuItem uri = c.uri_for(c.controller('User').action_for('edit'), [c.user.username]) title = "Preferences" %]
|
[% INCLUDE menuItem uri = c.uri_for(c.controller('User').action_for('edit'), [c.user.username]) title = "Preferences" %]
|
||||||
[% INCLUDE menuItem uri = c.uri_for(c.controller('Root').action_for('logout')) title = "Sign out" %]
|
<li>
|
||||||
|
<a href="#" id="persona-signout">Sign out</a>
|
||||||
|
</li>
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
[% INCLUDE menuItem uri = c.uri_for(c.controller('Root').action_for('login')) title = "Sign in" %]
|
<li>
|
||||||
|
<a href="#" id="persona-signin">Sign in</a>
|
||||||
|
</li>
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
Loading…
Reference in a new issue