Cataly...essive(3pm)

okay bestie, welcome to the Cataly...essive(3pm) page from the User Contributed Perl Documentation crew πŸ’…βœ¨ this is the one about making one authenticate() call do the most, fr fr.

πŸ’– NAME πŸ’–

Catalyst::Authentication::Realm::Progressive β€” Authenticate against multiple realms. That's the whole vibe: multiple realms, one progressive queen πŸ‘‘.

✨ SYNOPSIS ✨

So this Realm lets an app make a single authenticate() call, and during that call multiple realms get used and tried incrementally until one of them pulls off a successful authentication. Slay.

A simple use case? A Temporary Password that looks and acts exactly like a regular password. You can authenticate against multiple realms without changing the authentication code at all. Iconic.

Another use might be supporting a legacy website authentication system: try the current auth system first, and if that fails, attempt authentication against the legacy system. Very main character of it.

πŸ¦‹ EXAMPLE πŸ¦‹

If your app has multiple realms to authenticate β€” say a temporary password realm and a normal realm β€” you can configure the progressive realm as the default, and tell it to iteratively call the temporary realm and then the normal realm. Like this:

        __PACKAGE__->config(
           'Plugin::Authentication' => {
               default_realm => 'progressive',
               realms => {
                   progressive => {
                       class => 'Progressive',
                       realms => [ 'temp', 'normal' ],
                       # Modify the authinfo passed into authenticate by merging
                       # these hashes into the realm's authenticate call:
                       authinfo_munge => {
                           normal => { 'type' => 'normal' },
                           temp   => { 'type' => 'temporary' },
                       }
                   },
                   normal => {
                       credential => {
                           class => 'Password',
                           password_field => 'secret',
                           password_type  => 'hashed',
                           password_hash_type => 'SHA-1',
                       },
                       store => {
                           class      => 'DBIx::Class',
                           user_model => 'Schema::Person::Identity',
                           id_field   => 'id',
                       }
                   },
                   temp => {
                       credential => {
                           class => 'Password',
                           password_field => 'secret',
                           password_type  => 'hashed',
                           password_hash_type => 'SHA-1',
                       },
                       store => {
                           class    => 'DBIx::Class',
                           user_model => 'Schema::Person::Identity',
                           id_field   => 'id',
                       }
                   },
               }
           }
        );

Then, in your controller code, to attempt authentication against both realms you just have to do a simple authenticate call:

        if ( $c->authenticate({ id => $username, password => $password }) ) {
            if ( $c->user->type eq 'temporary' ) {
                # Force user to change password
            }
        }

No cap, that's the whole point: one call, multiple realm attempts, and it returns after the first successful authentication call is done.

🌸 CONFIGURATION 🌸

πŸŽ€ realms πŸŽ€

An array reference consisting of each realm to attempt authentication against, in the order listed. Keep it valid, bestie.

⚠️ If the realm does not exist, calling authenticate will die. Do not skip this β€” the die is real.

πŸŽ€ authinfo_munge πŸŽ€

A hash reference keyed by realm names, with values being hash references to merge into the authinfo call that is subsequently passed into the realm's authenticate method. This is useful if your store uses the same class for each realm, separated by some other token. In the EXAMPLE authinfo_mungesection, the 'realm' is a column on "Schema::Person::Identity" that will be either 'temp' or 'local', to ensure the query to fetch the user finds the right Identity record for that realm. Obsessed with a clean lookup.

πŸ”₯ METHODS πŸ”₯

🧚 new ($realmname, $config, $app) 🧚

Constructs an instance of this realm. Standard construction behavior, no drama.

🧚 authenticate 🧚

This method iteratively calls each realm listed in the "realms" configuration key. It returns after the first successful authentication call is done. So yeah, it stops at the first W and doesn't keep going.

πŸ‘‘ AUTHORS πŸ‘‘

  • J. Shirley "<jshirley@cpan.org>"
  • Jay Kuri "<jayk@cpan.org>"

These two gave us this realm, and we thank them for their service 🫢.

Copyright (c) 2008 the aforementioned authors. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

That's the legal tea, and it's giving classic Perl license energy.


okay bestie, that's the page! footer sign-off: source/version perl v5.40.1, dated 2026-05-22, for Cataly...essive(3pm) β€” mwah πŸ’‹βœ¨

πŸ“¦ where this page comes from