[dancer-users] Writing an Auth plugin for SSL client certificates

perlduck newsletter at dirk.my1.cc
Mon Nov 13 20:23:37 GMT 2017


Hi Lennart,

thank you, this looks promising. I will give that a try and see how I 
can combine this approach with the DPAE code because I like (and need) 
its concept of roles and other user details.
The "require_ssl_verified" function at least needs to lookup the given 
user in a DB to see if he's not only authenticated but also a valid user 
for this very application.

Regards
Dirk


Am 13.11.2017 14:42, schrieb Lennart Hengstmengel:
> Hi,
> 
> I would not start with Dancer2::Plugin::Auth::Extensible - it has lots
> of stuff you do not need in your use case - but start with an empty
> plugin. It's really quite simple, you need just one function (beware,
> untested code!):
> 
> package Dancer2::Plugin::Auth::SSLVerify;
> 
> use strict;
> use warnings;
> use utf8;
> 
> use Dancer2::Plugin;
> 
> sub require_ssl_verified {
>     my $dsl     = shift;
>     my $coderef = shift;
>     return sub {
>         my $app     = $dsl->app;
>         my $request = $app->request;
>         my $session = $app->session;
> 
>         my $client_verify = $request->env->{'HTTP_SSL_CLIENT_VERIFY'} 
> // '';
>         my $username = $request->env->{'HTTP_SSL_CLIENT_S_DN_EMAIL'} // 
> '';
>         if ($client_verify eq 'SUCCESS' and $username) {
>             $session->set( logged_in_user => $username );
>             return $coderef->($dsl);
>         } else {
>             return $dsl->redirect( '/not_authorized' ); # or something
>         }
>     };
> 
> 
> }
> 
> register 'require_ssl_verified' => \&require_ssl_verified;
> register_plugin;
> 
> 1;
> 
> 
> Then, you can use this plugin in your route definitions:
> 
> 
> use Dancer2::Plugin::Auth::SSLVerify;
> 
> get '/whatever' => require_ssl_verified sub {
>     # your route logic here.
> 
> };
> 
> 
> Hope this helps.
> 
> Regards,
> Lennart
> 
> 
> On 12-11-17 17:09, perlduck wrote:
>> Hello,
>> 
>> TL;DR
>> 
>> I'd like to write an authentication plugin that behaves like 
>> Dancer2::Plugin::Auth::Extensible but does NOT require a user's 
>> password but instead relies on the SSL variables SSL_CLIENT_VERIFY and 
>> SSL_CLIENT_S_DN_Email.
>> 
>> 
>> Background:
>> 
>> I have a Dancer2 application and currently using 
>> Dancer2::Plugin::Auth::Extensible to authenticate my users with 
>> username/password. I'm currently using two providers (realms), Config 
>> and Database. Config is mainly for testing purpose but I like the idea 
>> of multiple realms. I also need the concept of roles, so DPAE is just 
>> great and everything works like a charm.
>> 
>> Now I want to switch to client certificate authentication. I have set 
>> up an Apache as a proxy to the plackup server. Apache handles the SSL 
>> stuff, sets the variables
>> 
>>   <Location />
>>     RequestHeader set SSL_CLIENT_VERIFY "%{SSL_CLIENT_VERIFY}s"
>>     RequestHeader set SSL_CLIENT_S_DN_Email 
>> "%{SSL_CLIENT_S_DN_Email}s"
>>   </Location>
>> 
>> and then redirects to my Dancer2 app (at 127.0.0.1:5000).
>> 
>> Within my routes I can access those variables with
>> 
>>   my $client_verify = request->env->{'HTTP_SSL_CLIENT_VERIFY'} // '';
>>   my $username = request->env->{'HTTP_SSL_CLIENT_S_DN_EMAIL'} // '';
>> 
>> This works. Apache sets HTTP_SSL_CLIENT_VERIFY to 'SUCCESS' if the 
>> authentication worked. What I now want to achieve is:
>> 
>>     IFF $client_verify eq 'SUCCESS' THEN let the user $username in.
>> 
>> Don't show a /login page. Pick the user's details from the database 
>> (or whatever realm(s) is/are configured). Don't show a /logout page.
>> 
>> In short: allow everything what Dancer2::Plugin::Auth::Extensible 
>> allows but without ever asking for a password or redirecting to a 
>> /login page if the two variables are set (and, of course, $username 
>> can be found in the DB).
>> 
>> A very naive first approach was to use a "before" hook to set the 
>> "logged_in_user" value:
>> 
>>   hook before => sub {
>>       my $client_verify = request->env->{'HTTP_SSL_CLIENT_VERIFY'} // 
>> '';
>>       my $username = request->env->{'HTTP_SSL_CLIENT_S_DN_EMAIL'} // 
>> '';
>>       if ($client_verify eq 'SUCCESS' and $username) {
>>           session logged_in_user => $username;
>>       }
>>   };
>> 
>> This seems to work but looks very dirty to me. So I thought I'd better 
>> write a plugin that behaves like a Dancer2::Plugin::Auth::Extensible 
>> plugin but doesn't require a password and rather uses the two 
>> environment variables instead.
>> 
>> Is Dancer2::Plugin::Auth::Extensible even the right place (base) for 
>> such a plugin?
>> 
>> Cheers
>> 
>> _______________________________________________
>> dancer-users mailing list
>> dancer-users at dancer.pm
>> http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
>> 
> 
> _______________________________________________
> dancer-users mailing list
> dancer-users at dancer.pm
> http://lists.preshweb.co.uk/mailman/listinfo/dancer-users


More information about the dancer-users mailing list