Update
The new Authentication tutorial is now available on CPAN. The Authorization tutorial is also on CPAN. Please use that instead of the example below.
The most up-to-date version is always on SVN. Use pod2html from your Perl's bin directory to convert it to HTML.
Authentication and authorization example
If you are implementing authentication and authorization in your Catalyst application, you may be having some difficulty recently. Authentication and Authorization is now implemented differently than is shown in the Catalyst::Manual::Tutorial (5.701003). Until related documentation has been updated, I hope that this will help you apply authentication and authorization to your own application.
This is not a full fledged tutorial and I do not presume to have a high level knowledge of all related components. What I am presenting here, however, is what worked for me. For familiarity, I'm basing this example directly on the MyApp tutorial from the Catalyst::Manual documentation. So, if you are familiar with that then the changes here should be clear and easily carried over into your own custom application as needed.
As always, feel free to request additional help in #catalyst, which is where I received the help I needed to implement this myself. My hope is that my presentation here is adequate enough that you will be able to implement this on your own with little stress. Only a few small changes are needed.
In short, the changes consist of the following:
- Add a many_to_many relationship to your Users class.
- Reconfigure your myapp.yml configuration.
- Remove Authentication::Store::DBIC / Authentication::Credential::Password from MyApp.pm
See the brief list of suggested reading material (cpan docs) at the end of this document.
Database
First, if you follow the Authentication tutorial's example, you have a database like the following.
CREATE TABLE users (id INTEGER PRIMARY KEY, username TEXT, password TEXT, email_address TEXT, first_name TEXT, last_name TEXT, active INTEGER);
CREATE TABLE roles (id INTEGER PRIMARY KEY, role TEXT);
CREATE TABLE user_roles (user_id INTEGER, role_id INTEGER, PRIMARY KEY (user_id, role_id));
You do not need to alter anything in your database.
Classes
If you've created your DBIx schema according to the same documentation, it should result in the following classes.
User class
package MyAppDB::User;
use base qw/DBIx::Class/;
__PACKAGE__->load_components(qw/PK::Auto Core/);
__PACKAGE__->table('users');
__PACKAGE__->add_columns(qw/id username password email_address first_name last_name/);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many(map_user_role => 'MyAppDB::UserRole', 'user_id');
1;
The only thing you will need to change in your User class is to add a second relationship below has_many. This new line will be a many_to_many relationship that says User can have many Roles and they will be identified by the role field in the map_user_roles relation. So, add the following:
__PACKAGE__->many_to_many( roles => 'map_user_role', 'role' );
Role class
package MyAppDB::Role;
use base qw/DBIx::Class/;
__PACKAGE__->load_components(qw/PK::Auto Core/);
__PACKAGE__->table('roles');
__PACKAGE__->add_columns(qw/id role/);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many(map_user_role => 'MyAppDB::UserRole', 'role_id');
1;
Nothing needs to change in your Role class.
UserRole class
package MyAppDB::UserRole;
use base qw/DBIx::Class/;
__PACKAGE__->load_components(qw/PK::Auto Core/);
__PACKAGE__->table('user_roles');
__PACKAGE__->add_columns(qw/user_id role_id/);
__PACKAGE__->set_primary_key(qw/user_id role_id/);
__PACKAGE__->belongs_to(user => 'MyAppDB::User', 'user_id');
__PACKAGE__->belongs_to(role => 'MyAppDB::Role', 'role_id');
1;
Nothing needs to be changed in your UserRole class.
MyApp.pm
Your MyApp.pm should currently include the following:
use Catalyst qw/
. . .
Authentication
Authentication::Store::DBIC
Authentication::Credential::Password
Authorization::Roles
Authorization::ACL
. . .
/;
You can change this to read as follows:
use Catalyst qw/
. . .
Authentication
Authorization::Roles
Authorization::ACL
. . .
/;
myapp.yml
If you stored your configuration in YAML (myapp.yml), it probably includes the following:
authentication:
dbic:
user_class: MyAppDB::User
user_field: username
password_field: password
authorization:
dbic:
role_class: MyAppDB::Role
role_field: role
role_rel: map_user_role
user_role_user_field: user_id
You'll need to change it to look like the following. Notice that configuration is no longer stored under authentication->dbic and authorization->dbic, but that the authorization details are now placed under authentication->realms->default->store. Also note that some of the fields have changed slightly. (Do not copy and paste the YAML content as proper indentation is crucial).
authentication:
realms:
default:
credential:
class: Password
password_field: password
password_type: clear
store:
class: DBIx::Class
user_class: DB::User
id_field: id
role_relation: roles
role_field: role
In this new YAML configuration...
user_classrefers to MyAppDB::User, up above.
id_fieldThe field your user is identified by in your Users table.
role_relationThe name of the the many_to_many relationship we defined in MyAppDB::User
role_fieldThe name of the field in the Roles table that identifies the text names of your roles (ie 'admin').
Suggested reading
Showing changes from previous revision. Removed | Added

