If you look at Devise's implementation of sessions_controller#create, you'll notice that they yield if you pass a block.
So, just subclass their sessions controllers and pass a block when you call super. To do that, first tell Devise in routes.rb that you'd like to use your own sessions controller:
devise_for :users, controllers: { sessions: 'users/sessions' }
And then create a SessionsController class and pass a block when you call super in your create method. It would look something like this:
# app/controllers/users/sessions_controller.rb
class Users::SessionsController < Devise::SessionsController
  layout "application"
  
  # POST /login
  def create
    super do |user|
      if user.persisted?
        user.update(foo: :bar)
      end
    end
  end
end
Most of the Devise controller methods accept a block, so you could do this for registration, forgot password, etc as well.