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

perlduck newsletter at dirk.my1.cc
Sun Nov 12 16:09:45 GMT 2017


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



More information about the dancer-users mailing list