Dancer-Plugin-Auth-Github

 view release on metacpan or  search on metacpan

lib/Dancer/Plugin/Auth/Github.pm  view on Meta::CPAN


our $VERSION = '0.04';

my $client_id;
my $client_secret;
my $scope = "";
my $github_redirect_url = 'https://github.com/login/oauth/authorize/';
my $github_post_url = 'https://github.com/login/oauth/access_token/';
my $github_auth_failed = '/auth/github/failed';
my $github_auth_success = '/';
my $state_salt = "RandomSalt";

#A method to initializa everything
register 'auth_github_init' => sub {
	my $config = plugin_setting;
	
	$client_id 		  = $config->{client_id};
    $client_secret    = $config->{client_secret};
    	
	for my $param (qw/client_id client_secret/) {
        croak "'$param' is expected but not found in configuration" 
            unless $config->{$param};
    }
	#sthe following configs are optional.
 	if($config->{scope}) {
		$scope = $config->{scope};
	}
	#these configs have default values.
	if($config->{github_auth_failed})
	{
		$github_auth_failed = $config->{github_auth_failed};
	}
	if($config->{github_auth_success})
	{
		$github_auth_success = $config->{github_auth_success};
	}
	debug 'Loaded config..';
};
#returns the url you need to redirect to to authenticate on github
register 'auth_github_authenticate_url'  => sub {
	my $generate_state = sha256_hex($client_id.$client_secret.$state_salt);
	return "$github_redirect_url?&client_id=$client_id&scope=$scope&state=$generate_state";
};
#registers this as a callback url
get '/auth/github/callback' => sub {
	my $generate_state = sha256_hex($client_id.$client_secret.$state_salt);
	my $state_received = params->{'state'};
	if($state_received eq $generate_state) { 
		my $code                   = params->{'code'};
		my $browser                = LWP::UserAgent->new;
		my $resp                   = $browser->post($github_post_url,
		[
		client_id                  => $client_id,
		client_secret              => $client_secret, 
		code                       => $code,
		state                      => $state_received
		]);
		die "error while fetching: ", $resp->status_line
		unless $resp->is_success;
		
		my %querystr = parse_query_str($resp->decoded_content);
		my $acc = $querystr{access_token};
		
		if($acc) {
			my $jresp  = $browser->get("https://api.github.com/user?access_token=$acc");
			my $json = decode_json($jresp->decoded_content);
			session 'github_user' => $json;
			session 'github_access_token' => $acc;
			#session 'logged_in' => true;
			redirect $github_auth_success;
			return;
		} 
	}
	redirect $github_auth_failed;
};

#helper method to parse query string.
sub parse_query_str {
	my $str = shift;
	my %in = ();
	if (length ($str) > 0){
	      my $buffer = $str;
	      my @pairs = split(/&/, $buffer);
	      foreach my $pair (@pairs){
	           my ($name, $value) = split(/=/, $pair);
	           $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
	           $in{$name} = $value; 
	      }
	 }
	return %in;
}
register_plugin;

1; # End of Dancer::Plugin::Auth::Github
__END__
=head1 NAME

Dancer::Plugin::Auth::Github - Authenticate with Github

=head1 SYNOPSIS

    package YourDancerApplication;

    use Dancer ':syntax';
    use Dancer::Plugin::Auth::Github;

    #You must use a session backend. 
    #You should be able to use any backend support by dancer.
    set 'session'      => 'Simple';
    
    #make sure you call this first.
    #initializes the config
    auth_github_init();

    hook before => sub {
        #we don't want to be in a redirect loop
        return if request->path =~ m{/auth/github/callback};
        if (not session('github_user')) {
            redirect auth_github_authenticate_url;
        }
    };

    #by default success will redirect to this route
    get '/' => sub {
        "Hello, ".session('github_user')->{'login'};
        #For all the github_user properties



( run in 1.798 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )