---
name: "Catalyst::Authentication::Credential::Remote"
section: "3pm"
platform: "linux"
package: "libcatalyst-plugin-authentication-perl"
version: "0.10024-1"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/Catalyst::Authentication::Credential::Remote"
---

# Catalyst::Authentication::Credential::Remote(3pm)

Let the webserver (e.g. Apache) authenticate Catalyst application users

## NAME

Catalyst::Authentication::Credential::Remote - Let the webserver (e.g. Apache) authenticate Catalyst application users

## SYNOPSIS

```
    # in your MyApp.pm
    __PACKAGE__->config(
        'Plugin::Authentication' => {
            default_realm => 'remoterealm',
            realms => {
                remoterealm => {
                    credential => {
                        class        => 'Remote',
                        allow_regexp => '^(user.*|admin|guest)$',
                        deny_regexp  => 'test',
                    },
                    store => {
                        class => 'Null',
                        # if you want to have some additional user attributes
                        # like user roles, user full name etc. you can specify
                        # here the store where you keep this data
                    }
                },
            },
        },

    );

    # in your Controller/Root.pm you can implement "auto-login" in this way
    sub begin : Private {
        my ( $self, $c ) = @_;
        unless ($c->user_exists) {
            # authenticate() for this module does not need any user info
            # as the username is taken from $c->req->remote_user and
            # password is not needed
            unless ($c->authenticate( {} )) {
              # return 403 forbidden or kick out the user in other way
            };
        }
    }
    # or you can implement in any controller an ordinary login action like this
    sub login : Global {
        my ( $self, $c ) = @_;
        $c->authenticate( {} );
    }
```

## DESCRIPTION

This module allows you to authenticate the users of your Catalyst application on underlaying webserver. The complete list of authentication method available  via this module depends just on what your webserver (e.g. Apache, IIS, Lighttpd) is able to handle.

Besides the common methods like HTTP Basic and Digest authentication you can also use sophisticated ones like so called "integrated authentication" via NTLM or Kerberos (popular in corporate intranet applications running in Windows Active Directory environment) or even the SSL authentication when users  authenticate themself using their client SSL certificates.

The main idea of this module is based on a fact that webserver passes the name of authenticated user into Catalyst application as REMOTE\_USER variable (or in  case of SSL client authentication in other variables like SSL\_CLIENT\_S\_DN on Apache + mod\_ssl) - from this point referenced as WEBUSER.  This module simply takes this value - perfoms some optional checks (see below) - and if everything is OK the WEBUSER is declared as authenticated on  Catalyst level. In fact this module does not perform any check for password or  other credential; it simply believes the webserver that user was properly  authenticated.

## CONFIG

### class

This config item is **REQUIRED**.

**class** is part of the core Catalyst::Plugin::Authentication module, it  contains the class name of the store to be used.

The classname used for Credential. This is part of Catalyst::Plugin::Authentication and is the method by which Catalyst::Authentication::Credential::Remote is loaded as the credential validator. For this module to be used, this must be set to 'Remote'.

### source

This config item is **OPTIONAL** - default is REMOTE\_USER.

**source** contains a name of a variable passed from webserver that contains the  user identification.

Supported values: REMOTE\_USER, SSL\_CLIENT\_\*, CERT\_\*, AUTH\_USER

**BEWARE:** Support for using different variables than REMOTE\_USER does not work  properly with Catalyst 5.8004 and before (if you want details see source code).

Note1: Apache + mod\_ssl uses SSL\_CLIENT\_S\_DN, SSL\_CLIENT\_S\_DN\_\* etc. (has to be  enabled by 'SSLOption +StdEnvVars') or you can also let Apache make a copy of  this value into REMOTE\_USER (Apache option 'SSLUserName SSL\_CLIENT\_S\_DN').

Note2: Microsoft IIS uses CERT\_SUBJECT, CERT\_SERIALNUMBER etc. for storing info about client authenticated via SSL certificate. AUTH\_USER on IIS seems to have the same value as REMOTE\_USER (but there might be some differences I am not aware of).

### deny\_regexp

This config item is **OPTIONAL** - no default value.

**deny\_regexp** contains a regular expression used for check against WEBUSER  (see details below)

### allow\_regexp

This config item is **OPTIONAL** - no default value.

**deny\_regexp** contains a regular expression used for check against WEBUSER.

Allow/deny checking of WEBUSER values goes in this way:

1\) If **deny\_regexp** is defined and WEBUSER matches deny\_regexp then  authentication FAILS otherwise continues with next step. If deny\_regexp is not  defined or is an empty string we skip this step.

2\) If **allow\_regexp** is defined and WEBUSER matches allow\_regexp then  authentication PASSES otherwise FAILS. If allow\_regexp is not  defined or is an empty string we skip this step.

The order deny-allow is fixed.

### cutname\_regexp

This config item is **OPTIONAL** - no default value.

If param **cutname\_regexp** is specified we try to cut the final usename passed to Catalyst application as a substring from WEBUSER. This is useful for  example in case of SSL authentication when WEBUSER looks like this  'CN=john, OU=Unit Name, O=Company, C=CZ' - from this format we can simply cut pure usename by cutname\_regexp set to 'CN=(.\*), OU=Unit Name, O=Company, C=CZ'.

Substring is always taken as '$1' regexp substring. If WEBUSER does not match cutname\_regexp at all or if '$1' regexp substring is empty we pass the original WEBUSER value (without cutting) to Catalyst application.

### username\_field

This config item is **OPTIONAL** - default is *username*

The key name in the authinfo hash that the user's username is mapped into. This is useful for using a store which requires a specific unusual field name for the username.  The username is additionally mapped onto the *id* key.

## METHODS

### new ( $config, $app, $realm )

Instantiate a new Catalyst::Authentication::Credential::Remote object using the configuration hash provided in `$config`. In case of invalid value of any  configuration parameter (e.g. invalid regular expression) throws an exception.

### authenticate ( $realm, $authinfo )

Takes the username form WEBUSER set by webserver, performs additional  checks using optional allow\_regexp/deny\_regexp configuration params, optionaly  takes substring from WEBUSER and the sets the resulting value as a Catalyst username.

## COMPATIBILITY

It is **strongly recommended** to use this module with Catalyst 5.80005 and above as previous versions have some bugs related to `$c`-\>engine-\>env and do not  support `$c`-\>req-\>remote\_user.

This module tries some workarounds when it detects an older version and should work as well.

## USING WITH A REVERSE PROXY

If you are using a reverse proxy, then the WEBUSER will not be directly accessible by the Catalyst server.  To use remote authentication, you will have to modify the web server to set a header containing the WEBUSER.  You would then need to modify the PSGI configuration to map the header back to the WEBUSER variable.

For example, in Apache you would add the configuration

```
  RequestHeader unset X-Forwarded-User
  RewriteEngine On
  RewriteCond %{LA-U:REMOTE_USER} (.+)
  RewriteRule . - [E=RU:%1]
  RequestHeader set X-Forwarded-User %{RU}e
```

You then need to create a Plack::Middleware module to map the header back to the WEBUSER:

```
  package Plack::Middleware::MyRemote;
  use parent qw( Plack::Middleware );
  use Plack::Util;
  sub call {
      my ($self, $env) = @_;
      my $user = $env->{HTTP_X_FORWARDED_USER} // "";
      $env->{REMOTE_USER} = $user
        if ($user && ($user ne '(null)'));
      my $res = $self->app->($env);
      return $res;
  }
  1;
```

Finally, you need to modify *myapp.psgi* to use the custom middleware:

```
  use strict;
  use warnings;
  use MyApp;
  use Plack::Builder;
  my $app = Drain->apply_default_middlewares(Drain->psgi_app);
  builder {
     enable "Plack::Middleware::MyRemote";
     $app;
  };
```
