The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
# ABSTRACT: Guide for authenticating and authorizing against a PlugAuth server
# VERSION
# PODNAME: PlugAuth::Guide::Client


__END__
=pod

=head1 NAME

PlugAuth::Guide::Client - Guide for authenticating and authorizing against a PlugAuth server

=head1 VERSION

version 0.26

=head1 DESCRIPTION

This document contains some common recipes for using interacting as a client
in various environments with a L<PlugAuth> server.

This document assumes a PlugAuth server listening on http://localhost:3000 with
users C<primus> (an administrator) with password "spark" and C<optimus> (a user) with
password "matrix".  The resource.txt file for the server looks like this:

 / (accounts): primus
 /user (change_password): primus
 /user/#u (change_password): #u
 /some/user/resource (GET): optimus

For details on setting up a PlugAuth server using the default plugins, see
L<PlugAuth::Guide::Server>.  All of these examples are included with the 
L<PlugAuth> distribution in example directory.

=head2 From a L<Clustericious> service using L<Clustericious::Plugin::PlugAuth>.

Any Clustericious service can be integrated with PlugAuth using the Clustericious
L<PlugAuth|Clustericious::Plugin::PlugAuth> plugin.  Here is an example Routes
module

 package ExampleAppExample::Routes;
 
 use Clustericious::RouteBuilder;
 
 get '/' => sub { shift->render_text('hello') };
 
 authenticate;
 authorize;
 
 get '/some/user/resource' => sub { shift->render_text('hello') };

And example configuration to go along with it.

 ---
 url: http://localhost:3001
 plug_auth:
   url: http://localhost:3000

This will configure the example application to listen on localhost port 3001 and
to use the PlugAuth server listening on localhost port 3000.  You can start this
service by using the daemon command

 % perl ExampleAppExample.pl daemon -l http://localhost:3001

And test it by navigating your browser to http://localhost:3001/some/user/resource .
The web browser should prompt you for a username and password, and accept the 
credentials for C<optimus>.

For more details see L<Clustericious::Plugin::PlugAuth>.

=head2 From Perl using L<PlugAuth::Client>

L<PlugAuth::Client> can be used to authenticate against a L<PlugAuth> server from
a Perl script or module.  L<PlugAuth::Client> needs a configuration file, just like
PlugAuth.  You can use the same configuration file as you use for the server,
although the only configuration item you need is C<url>:

 ---
 url: http://localhost:3000

First you will need t ocreate an instance of PlugAuth::Client:

 use strict;
 use warnings;
 use v5.10;
 use PlugAuth::Client;
 
 my $client = PlugAuth::Client->new;

Then you should specify your credentials using the C<login> method.  C<login> doesn't
connect to the L<PlugAuth> server itself, but it does remember the credentials and use
it on the next call that you make to the L<PlugAuth> server.

 print "user: ";
 my $username = <STDIN>;
 print "pass: ";
 my $password = <STDIN>;
 
 chomp $username;
 chomp $password;
 
 $client->login($username, $password);

Obviously in a production environment you should hide the password when prompting for
a password, but for this example, it will be helpful to see the credentials at the shell.

To check that the credentials are correct, you can use the auth method:

 if($client->auth)
 {
   say "$username is authenticated";
 }
 else
 {
   say "AUTH FAILED";
 }

And to check that you are authorized for a particular resource, use the authz method:

 if($client->authz($username, 'GET', '/some/user/resource'))
 {
   say "$username is authorized to GET /some/user/resource";
 }
 else
 {
   say "AUTHZ FAILED";
 }

Here we run this example script using bogus credentials:

 % perl client.pl
 user: bogus
 pass: bogus
 AUTH FAILED
 AUTHZ FAILED

Next, try the user administrator credentials.  Note that although primus is an 
administrator for users we did not give him permission to get the resource
/some/user/resource, so the authorization fails.

 % perl client.pl
 user: primus
 pass: spark
 primus is authenticated
 AUTHZ FAILED

Finally, providing the credentials for optimus should pass both authentication
and authorization.

 % perl client.pl
 user: optimus
 pass: matrix
 optimus is authenticated
 optimus is authorized to GET /some/user/resource

There are a number of other features that can be accessed using this interface.
Please see L<PlugAuth::Client> for details.

=head2 From the command line using L<plugauthclient> and L<plugauthpasswd>.

The L<PlugAuth::Client> distribution installs two programs for interacting with a
PlugAuth server from the command line.  L<plugauthclient> is a thin wrapper around
the Perl and RESTful APIs provided by L<PlugAuth>.  As in the previous example, we
need a configuration file in ~/etc/PlugAuth.conf, but only the url needs to be 
specified for the client.  Once that is setup we can check authentication and
authorization, just like we could via the Perl API.

 % plugauthclient auth
 Username for  at localhost :  [default joe] bogus
 Password: 
 [ERROR] 2012/11/30 12:17:16 Client.pm (733) Error trying to GET http://user:*****@localhost:3000/auth : 403 Forbidden
 [ERROR] 2012/11/30 12:17:16 Client.pm (737) not ok
 [ERROR] 2012/11/30 12:17:16 Command.pm (253) Forbidden
 % plugauthclient auth
 Username for  at localhost :  [default joe] optimus
 Password: 
 --- ok
 % plugauthclient authz primus GET /some/user/resource
 [ERROR] 2012/11/30 12:19:11 Client.pm (733) Error trying to GET http://localhost:3000/authz/user/primus/GET/some/user/resource : 403 Forbidden
 [ERROR] 2012/11/30 12:19:11 Client.pm (737) unauthorized : primus cannot GET /some/user/resource
 [ERROR] 2012/11/30 12:19:11 Command.pm (253) Forbidden
 % plugauthclient authz optimus GET /some/user/resource
 --- ok

L<plugauthpasswd> provides a mechanism for changing your password:

 % plugauthpasswd
 Username:  [default joe] optimus
 Old Password:
 New Password:
 Verify New Password:
 --- ok

=head2 From another language using a WWW library

The RESTful API for L<PlugAuth> is documented in L<PlugAuth::Routes>.  For authentication
simply make a HTTP GET request to http://localhost:3000/auth using HTTP BASIC authentication.
To check authorization make a HTTP GET request to
http://localhost:3000/authz/user/I<username>/I<action>/I<resource> .  For example to check
that C<optimus> can GET on the resource /some/user/resource, the constructed resource would
be http://localhost:3000/authz/user/primus/GET/some/user/resource .  All routes in the RESTful
API return standard HTTP status codes.

=head2 From a sh script using wget

If you do not have L<PlugAuth::Client> installed and cannot install it, you can use C<wget>
or C<curl>.  Because L<PlugAuth> uses standard HTTP status codes, C<wget> will return non
zero on failure and you can construct an if around it.

 #!/bin/sh
 
 USER=$1
 PASS=$2
 WGET="wget -q -O /dev/null"
 
 if $WGET http://${USER}:${PASS}@localhost:3000/auth ; then
   echo "$USER is authenticate"
 else
   echo "AUTH FAILED"
 fi
 
 if $WGET http://localhost:3000/authz/user/${USER}/GET/some/user/resource ; then
   echo "$USER is authorized to GET /some/user/resource"
 else
   echo "AUTHZ FAILED"
 fi

Here we pass it bogus credentials

 % sh client.sh bogus bogus
 AUTH FAILED
 AUTHZ FAILED

And here we pass it good credentials

 % sh client.sh optimus matrix
 optimus is authenticate
 optimus is authorized to GET /some/user/resource

=head2 From PAM (Pluggable Authentication Module)

There is a L<PAM module that will authenticate against a HTTP server 
using HTTP Basic authentication on 
git|https://github.com/beatgammit/pam-http>. It is licensed under the 
MIT License and is based on work by Kragen Sitaker.  I had to install 
C<libpam0g-dev> and C<libcurl4-openssl-dev> on my Debian system in order 
for it to build for me.

 % git clone git://github.com/beatgammit/pam-http.git
 % cd pam-http
 % make
 % sudo cp mypam.so /lib/security

Add these two lines to the top of your /etc/pam.d/common-auth (or other) config:

 auth sufficient mypam.so url=http://localhost:3000/auth
 account sufficient mypam.so

C<sufficient> means that it will fallback on your existing passwd file or whatever
authentication mechanism is configured already.  Change the C<url> argument
to the URL for your L<PlugAuth> server.

There are numerous caveats here.  PlugAuth usually runs as an unprivileged 
user which means it binds to an unprivileged port, and if an unauthorized 
user sets up their own PlugAuth service before the "correct" PlugAuth server 
starts, authentication could be subverted.  Encryption, such as SSL should 
be used if you are authenticating against a L<PlugAuth> server over the 
network, but pam-http as written does not check the authenticity of the 
PlugAuth server's SSL certificate.  Unix accounts require more information 
than just authentication, which is not provided by L<PlugAuth>, so something 
like LDAP may be more appropriate.  None of these things are insurmountable 
if you take the time to fix them, but care needs to be taken.

=head1 SEE ALSO

L<PlugAuth>, 
L<PlugAuth::Client>, 
L<Authen::Simple::PlugAuth>

=head1 AUTHOR

Graham Ollis <gollis@sesda3.com>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2012 by NASA GSFC.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut