Merge pull request #841 from pingiun/github-login

Implement GitHub logins
This commit is contained in:
Eelco Dolstra
2021-01-05 14:51:51 +01:00
committed by GitHub
5 changed files with 78 additions and 10 deletions

View File

@ -30,6 +30,8 @@ sub noLoginNeeded {
return $whitelisted ||
$c->request->path eq "api/push-github" ||
$c->request->path eq "google-login" ||
$c->request->path eq "github-redirect" ||
$c->request->path eq "github-login" ||
$c->request->path eq "login" ||
$c->request->path eq "logo" ||
$c->request->path =~ /^static\//;

View File

@ -4,6 +4,7 @@ use utf8;
use strict;
use warnings;
use base 'Hydra::Base::Controller::REST';
use File::Slurp;
use Crypt::RandPasswd;
use Digest::SHA1 qw(sha1_hex);
use Hydra::Helper::Nix;
@ -154,6 +155,67 @@ sub google_login :Path('/google-login') Args(0) {
doEmailLogin($self, $c, "google", $data->{email}, $data->{name} // undef);
}
sub github_login :Path('/github-login') Args(0) {
my ($self, $c) = @_;
my $client_id = $c->config->{github_client_id} or die "github_client_id not configured.";
my $client_secret = $c->config->{github_client_secret} // do {
my $client_secret_file = $c->config->{github_client_secret_file} or die "github_client_secret nor github_client_secret_file is configured.";
my $client_secret = read_file($client_secret_file);
$client_secret =~ s/\s+//;
$client_secret;
};
die "No github secret configured" unless $client_secret;
my $ua = new LWP::UserAgent;
my $response = $ua->post(
'https://github.com/login/oauth/access_token',
{
client_id => $client_id,
client_secret => $client_secret,
code => ($c->req->params->{code} // die "No token."),
}, Accept => 'application/json');
error($c, "Did not get a response from GitHub.") unless $response->is_success;
my $data = decode_json($response->decoded_content) or die;
my $access_token = $data->{access_token} // die "No access_token in response from GitHub.";
$response = $ua->get('https://api.github.com/user/emails', Accept => 'application/vnd.github.v3+json', Authorization => "token $access_token");
error($c, "Did not get a response from GitHub for email info.") unless $response->is_success;
$data = decode_json($response->decoded_content) or die;
my $email;
foreach my $eml (@{$data}) {
$email = $eml->{email} if $eml->{verified} && $eml->{primary};
}
die "No primary email for this GitHub profile" unless $email;
$response = $ua->get('https://api.github.com/user', Authorization => "token $access_token");
error($c, "Did not get a response from GitHub for user info.") unless $response->is_success;
$data = decode_json($response->decoded_content) or die;
doEmailLogin($self, $c, "github", $email, $data->{name} // undef);
$c->res->redirect($c->uri_for($c->res->cookies->{'after_github'}));
}
sub github_redirect :Path('/github-redirect') Args(0) {
my ($self, $c) = @_;
my $client_id = $c->config->{github_client_id} or die "github_client_id not configured.";
my $after = "/" . $c->req->params->{after};
$c->res->cookies->{'after_github'} = {
name => 'after_github',
value => $after,
};
$c->res->redirect("https://github.com/login/oauth/authorize?client_id=$client_id&scope=user:email");
}
sub captcha :Local Args(0) {
my ($self, $c) = @_;