Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

oscaribarra25's avatar

Laravel 10 - Conditionally redirects and messages during authentication using external API

Hi everyone,

I am building a site in Laravel 10 for which the customer asked that it should integrate with existing authentication API on their end.

The authentication flow is as follows:

  1. When user enters his credentials the authentication process should send this to the API for validation.
  2. API endpoint validates credentials if correct it checks: a. If the user needs to change his temporary password it returns an specific return code, else b. If the user already has a valid PIN it returns a different return code, else c. A new PIN is generated (valid for 3 hours), send this PIN to user email and return a different return code.
  3. When non successful API response is received (error sending pin, invalid credentials, user not authorized to use this application) the site should remain in login view (showing a different message depending on the return code received) to allow the user to retry.
  4. When successfull API response is received: a. If the user needs to change his temporary password the site should need to redirect to a change password view, else b. The site should redirect to PIN validation view (similar to two factor authentication) with a message indicating if the PIN was sent or if he already had a PIN.
  5. The user enters the PIN which is sent to the API for validation. If the API response for this new request is successful then and just then the user is authenticated and the site should redirect to home if not no redirection should happen and the corresponding message has to be shown.

There also exist a forgot password flow as follows:

  1. User clicks on forgot password link.
  2. Site redirects to forgot password view.
  3. User enters his email and click send.
  4. API endpoint is called. The API generates a temporary password for the user matching the email and then sends this temporary password to the user via email.
  5. When non successful API reponse is received the corresponding message should show and the site should remain in the same view.
  6. When successful API response is received the site should redirect to login view showing a message.
  7. The user logs is an explained in steps 1, 2.a, 3, 4.a.
  8. The user changes his password and the following API calls are made a. Store new password b. Login attempt (mostly to get a new PIN if needed).
  9. The site redirects to PIN validation view.
  10. Then the user login as explained in previous flow.

I already:

  • Implemented Fortify::authenticateUsing in boot method in JetstreamServiceProvider with the API calls but not sure how to conditionally redirect to PIN validation view or to change password view. Also not sure how to send the return code to PIN validation view to know which message to how there. This is because as I read this closure returns the authenticated user.
  • Created the necessary migrations to add a users.username field and to drop the users.password field (I don't need it anymore). I am keeping the users table to allow defining user-role-ability based authorization.
  • Modified the auth\login view to ask for username rather than email. And also the config\fortify to ask for the users.username field as the username instead of the users.email field.
  • Created a custom PasswordResetLinkController with the API calls and avoiding to send laravel's email (the API is taking care of this).
  • Created a custom Password class to add some password policy rules like password max length (laravel only has option to validate min length), and lowercase required
  • Modified UpdateUserPassword fortify action to include the necessary API calls but not sure how to send a flash message saying the password was changed successfully.
  • Modified the profile.update-password-form view to show the user the password policies the password must match.

I am missing:

  • Conditional redirects and conditional messages after login view submit.
  • How to keep the user non authenticated until after the PIN is validated.

I have being reviewing Fortify::authenticateThrough and also Fortify actions RedirectIfTwoFactorAuthenticatable, AttemptToAuthenticate and PrepareAuthenticatedSession but not sure how to proceed.

Any help will be greatly appreciated.

0 likes
2 replies
oscaribarra25's avatar

Thanks @snapey I ended creating custom AuthenticatedSessionController, custom NewPasswordController, custom PasswordResetLinkController and custom TwoFactorAuthenticatedSessionController (and created all the Web routes) for it to work as expected.

At the end, Custom AuthenticatedSessionController store method receives the credentials call the API and depending on the response:

  1. sets username and custom message in session and then redirects to 'two-factor.login',
  2. sets username in session and then redirects to 'password.reset'
  3. stay in login and show the corresponding error message.

Custom AuthenticatedSessionController destroy method just do Auth::logout(), invalidate session, do session token regeneration and redirect to 'login'.

Custom NewPasswordController store method receives the current and new password and call the API to validate current password, validate password policies compliance, if everything is ok call the API to store new password if successful call the API again to simulate a login (to get a new PIN) and finally redirects to 'two-factor.login'.

Custom PasswordResetLinkController store method just get the email call the API to send new temporary password to user if successful redirect to 'login'

Custom TwoFactorAuthenticatedSessionController store method is managing two actions:

  1. If user clicks on resend PIN submit button it call the API to resend PIN (actually is a new PIN not the same one)
  2. If user attempt to validate PIN it call the API to validate PIN if successful then it gets the user in my local DB, perform an Auth::login, regenerate session and redirect to 'home.index'.

I also made all the necessary changes in views and removed the added code to JetStreamServiceProvider, ResetUserPassword, UpdateUserPassword, PasswordValidationRules leaving them as originally was. Also i switched off unnecessary features in fortify and jetstream config files.

It is working now.

Please or to participate in this conversation.