cms icon indicating copy to clipboard operation
cms copied to clipboard

CMS Password Reset flow Broken with Eloquent driver

Open SuryaWebfox opened this issue 7 months ago • 2 comments

Bug description

I migrated my users in Statamic 5 to use the eloquent driver, as described in the docs. When using the "Forgot Password" form on the CMS login form, I got an error after submitting

Route [password.reset] not defined.

How to reproduce

  • Use the eloquent driver for your users and follow the documentation on https://statamic.dev/tips/storing-users-in-a-database
  • Go to /cp and click "Forgot password?"
  • Fill out the form and submit

Logs


Environment

Environment
Application Name: Kwetta
Laravel Version: 12.15.0
PHP Version: 8.4.3
Composer Version: 2.8.5
Environment: staging
Debug Mode: ENABLED
URL: kwetta.gil.testsite.kiwi.nz
Maintenance Mode: OFF
Timezone: UTC
Locale: en

Cache
Config: CACHED
Events: NOT CACHED
Routes: NOT CACHED
Views: CACHED

Drivers
Broadcasting: log
Cache: file
Database: mysql
Logs: stack / single
Mail: log
Queue: sync
Session: file

Storage
public/storage: LINKED

Statamic
Addons: 2
Sites: 1
Stache Watcher: Disabled (auto)
Static Caching: Disabled
Version: 5.56.0 PRO

Statamic Addons
statamic/eloquent-driver: 4.21.2
statamic/ssg: 3.1.1

Statamic Eloquent Driver
Asset Containers: eloquent
Assets: eloquent
Blueprints: file
Collection Trees: eloquent
Collections: eloquent
Entries: eloquent
Forms: eloquent
Global Sets: eloquent
Global Variables: eloquent
Navigation Trees: eloquent
Navigations: eloquent
Revisions: eloquent
Sites: eloquent
Taxonomies: eloquent
Terms: eloquent
Tokens: eloquent

Installation

Fresh statamic/statamic site via CLI

Additional details

No response

SuryaWebfox avatar May 26 '25 00:05 SuryaWebfox

Can you provide your config/auth.php and config/statamic/users.php config files?

duncanmcclean avatar May 26 '25 08:05 duncanmcclean

auth.php

<?php

use App\Models\User;

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Defaults
    |--------------------------------------------------------------------------
    |
    | This option defines the default authentication "guard" and password
    | reset "broker" for your application. You may change these values
    | as required, but they're a perfect start for most applications.
    |
    */

    'defaults' => [
        'guard'     => env('AUTH_GUARD', 'web'),
        'passwords' => env('AUTH_PASSWORD_BROKER', 'users'),
    ],

    /*
    |--------------------------------------------------------------------------
    | Authentication Guards
    |--------------------------------------------------------------------------
    |
    | Next, you may define every authentication guard for your application.
    | Of course, a great default configuration has been defined for you
    | which utilizes session storage plus the Eloquent user provider.
    |
    | All authentication guards have a user provider, which defines how the
    | users are actually retrieved out of your database or other storage
    | system used by the application. Typically, Eloquent is utilized.
    |
    | Supported: "session"
    |
    */

    'guards' => [
        'web' => [
            'driver'   => 'session',
            'provider' => 'users',
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | User Providers
    |--------------------------------------------------------------------------
    |
    | All authentication guards have a user provider, which defines how the
    | users are actually retrieved out of your database or other storage
    | system used by the application. Typically, Eloquent is utilized.
    |
    | If you have multiple user tables or models you may configure multiple
    | providers to represent the model / table. These providers may then
    | be assigned to any extra authentication guards you have defined.
    |
    | Supported: "statamic", "database", "eloquent"
    |
    */

    'providers' => [
//        'users' => [
//            'driver' => 'statamic',
//        ],

        'users' => [
            'driver' => 'eloquent',
            'model'  => env('AUTH_MODEL', User::class),
        ],

        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Resetting Passwords
    |--------------------------------------------------------------------------
    |
    | These configuration options specify the behavior of Laravel's password
    | reset functionality, including the table utilized for token storage
    | and the user provider that is invoked to actually retrieve users.
    |
    | The expiry time is the number of minutes that each reset token will be
    | considered valid. This security feature keeps tokens short-lived so
    | they have less time to be guessed. You may change this as needed.
    |
    | The throttle setting is the number of seconds a user must wait before
    | generating more password reset tokens. This prevents the user from
    | quickly generating a very large amount of password reset tokens.
    |
    */

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table'    => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'),
            'expire'   => 60,
            'throttle' => 60,
        ],

        'activations' => [
            'provider' => 'users',
            'table'    => env('AUTH_ACTIVATION_TOKEN_TABLE', 'password_activation_tokens'),
            'expire'   => 4320,
            'throttle' => 60,
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Password Confirmation Timeout
    |--------------------------------------------------------------------------
    |
    | Here you may define the amount of seconds before a password confirmation
    | window expires and users are asked to re-enter their password via the
    | confirmation screen. By default, the timeout lasts for three hours.
    |
    */

    'password_timeout' => env('AUTH_PASSWORD_TIMEOUT', 10800),

];

users.php

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | User Repository
    |--------------------------------------------------------------------------
    |
    | Statamic uses a repository to get users, roles, groups, and their
    | relationships from specified storage locations. The file driver
    | gets it from disk, while the eloquent driver gets from a DB.
    |
    | Supported: "file", "eloquent"
    |
    */

    'repository' => 'eloquent',

    'repositories' => [

        'file' => [
            'driver' => 'file',
            'paths' => [
                'roles' => resource_path('users/roles.yaml'),
                'groups' => resource_path('users/groups.yaml'),
            ],
        ],

        'eloquent' => [
            'driver' => 'eloquent',
        ],

    ],

    /*
    |--------------------------------------------------------------------------
    | Avatars
    |--------------------------------------------------------------------------
    |
    | User avatars are initials by default, with custom options for services
    | like Gravatar.com.
    |
    | Supported: "initials", "gravatar", or a custom class name.
    |
    */

    'avatars' => 'initials',

    /*
    |--------------------------------------------------------------------------
    | New User Roles
    |--------------------------------------------------------------------------
    |
    | When registering new users through the user:register_form tag, these
    | roles will automatically be applied to your newly created users.
    |
    */

    'new_user_roles' => [
        //
    ],

    /*
    |--------------------------------------------------------------------------
    | New User Groups
    |--------------------------------------------------------------------------
    |
    | When registering new users through the user:register_form tag, these
    | groups will automatically be applied to your newly created users.
    |
    */

    'new_user_groups' => [
        //
    ],

    /*
    |--------------------------------------------------------------------------
    | Registration form honeypot field
    |--------------------------------------------------------------------------
    |
    | When registering new users through the user:register_form tag,
    | specify the field to act as a honeypot for bots
    |
    */

    'registration_form_honeypot_field' => null,

    /*
    |--------------------------------------------------------------------------
    | User Wizard Invitation Email
    |--------------------------------------------------------------------------
    |
    | When creating new users through the wizard in the control panel,
    | you may choose whether to be able to send an invitation email.
    | Setting to true will give the user the option. But setting
    | it to false will disable the invitation option entirely.
    |
    */

    'wizard_invitation' => true,

    /*
    |--------------------------------------------------------------------------
    | Password Brokers
    |--------------------------------------------------------------------------
    |
    | When resetting passwords, Statamic uses an appropriate password broker.
    | Here you may define which broker should be used for each situation.
    | You may want a longer expiry for user activations, for example.
    |
    */

    'passwords' => [
        'resets' => 'users',
        'activations' => 'activations',
    ],

    /*
    |--------------------------------------------------------------------------
    | Database
    |--------------------------------------------------------------------------
    |
    | Here you may configure the database connection and its table names.
    |
    */

    'database' => config('database.default'),

    'tables' => [
        'users' => 'users',
        'role_user' => 'role_user',
        'roles' => false,
        'group_user' => 'group_user',
        'groups' => false,
    ],

    /*
    |--------------------------------------------------------------------------
    | Authentication Guards
    |--------------------------------------------------------------------------
    |
    | By default, Statamic will use the `web` authentication guard. However,
    | if you want to run Statamic alongside the default Laravel auth
    | guard, you can configure that for your cp and/or frontend.
    |
    */

    'guards' => [
        'cp' => 'web',
        'web' => 'web',
    ],

    /*
    |--------------------------------------------------------------------------
    | Impersonation
    |--------------------------------------------------------------------------
    |
    | Here you can configure if impersonation is available, and what URL to
    | redirect to after impersonation begins.
    |
    */

    'impersonate' => [
        'enabled' => env('STATAMIC_IMPERSONATE_ENABLED', true),
        'redirect' => env('STATAMIC_IMPERSONATE_REDIRECT', null),
    ],

    /*
    |--------------------------------------------------------------------------
    | Default Sorting
    |--------------------------------------------------------------------------
    |
    | Here you may configure the default sort behavior for user listings.
    |
    */

    'sort_field' => 'email',
    'sort_direction' => 'asc',

];

SuryaWebfox avatar Jun 04 '25 02:06 SuryaWebfox

@SuryaWebfox Have you followed step 12 of the linked documentation page? We had this issue of a missing route, but it was caused by us skipping the last step of adding a notification method to your User model. Once you add that, you should be fine.

public function sendPasswordResetNotification($token)
{
    $this->notify(new \Statamic\Notifications\PasswordReset($token));
}

daun avatar Jul 29 '25 07:07 daun

That's a good point. I since did add that method (a custom version) but I probably missed that step somewhere.

SuryaWebfox avatar Jul 29 '25 22:07 SuryaWebfox

Just to clarify… is this resolved now that you’ve added the method to your User model?

duncanmcclean avatar Jul 30 '25 07:07 duncanmcclean

Yes, sorry

SuryaWebfox avatar Jul 31 '25 21:07 SuryaWebfox