Fix onboarding return after bank auth errors (#361)

## Summary
- Keep non-onboarded users on the accounts step after bank authorization
errors
- Add feature and browser coverage for the callback error path

## Tests
- vendor/bin/pint --dirty --format agent
- php artisan test --compact tests/Browser/OnboardingFlowTest.php
--filter='returns to the accounts step'
- php artisan test --compact
tests/Feature/OpenBanking/AuthorizationControllerTest.php
--filter='callback with error'
This commit is contained in:
Víctor Falcón 2026-05-06 14:50:02 +01:00 committed by GitHub
parent 6cd465bb78
commit 0f1ce81b4e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 58 additions and 5 deletions

View File

@ -103,7 +103,8 @@ class AuthorizationController extends Controller
public function callback(Request $request, BankingProviderInterface $provider): RedirectResponse
{
$user = auth()->user();
$errorRedirect = $user->isOnboarded() ? 'settings.connections.index' : 'onboarding';
$errorRedirectRoute = $user->isOnboarded() ? 'settings.connections.index' : 'onboarding';
$errorRedirectParams = $user->isOnboarded() ? [] : ['step' => 'create-account'];
if ($request->has('error')) {
Log::warning('EnableBanking authorization error', [
@ -117,14 +118,14 @@ class AuthorizationController extends Controller
->first()
?->delete();
return redirect()->route($errorRedirect)
return redirect()->route($errorRedirectRoute, $errorRedirectParams)
->with('error', $request->query('error_description', 'Authorization was denied or cancelled.'));
}
$code = $request->query('code');
if (! $code) {
return redirect()->route($errorRedirect)
return redirect()->route($errorRedirectRoute, $errorRedirectParams)
->with('error', 'No authorization code received.');
}
@ -133,7 +134,7 @@ class AuthorizationController extends Controller
} catch (\Throwable $e) {
Log::error('EnableBanking session creation failed', ['error' => $e->getMessage()]);
return redirect()->route($errorRedirect)
return redirect()->route($errorRedirectRoute, $errorRedirectParams)
->with('error', 'Failed to connect to your bank. Please try again.');
}
@ -143,7 +144,7 @@ class AuthorizationController extends Controller
->first();
if (! $connection) {
return redirect()->route($errorRedirect)
return redirect()->route($errorRedirectRoute, $errorRedirectParams)
->with('error', 'No pending connection found.');
}

View File

@ -2,6 +2,7 @@
use App\Models\Account;
use App\Models\Bank;
use App\Models\BankingConnection;
use App\Models\User;
// =============================================================================
@ -168,6 +169,40 @@ it('allows continuing with existing accounts', function () {
->assertNoJavascriptErrors();
});
it('returns to the accounts step when bank authorization fails during onboarding', function () {
$user = User::factory()->create([
'onboarded_at' => null,
]);
$bank = Bank::factory()->create(['name' => 'Connected Bank']);
Account::factory()->create([
'user_id' => $user->id,
'bank_id' => $bank->id,
'type' => 'checking',
'currency_code' => 'EUR',
]);
$connection = BankingConnection::factory()->pending()->create([
'user_id' => $user->id,
'aspsp_name' => 'Failing Bank',
'aspsp_country' => 'ES',
]);
$this->actingAs($user);
$page = visit('/open-banking/callback?error=access_denied&error_description=Authentication+failed');
$page->wait(1)
->assertPathIs('/onboarding')
->assertQueryStringHas('step', 'create-account')
->assertSee('Your Accounts')
->assertSee('Connected Bank')
->assertDontSee('Welcome to')
->assertNoJavascriptErrors();
$connection->refresh();
expect($connection->trashed())->toBeTrue();
});
// =============================================================================
// More Accounts Flow Tests
// =============================================================================

View File

@ -146,6 +146,23 @@ test('callback with error redirects with error message and deletes pending conne
expect($connection->trashed())->toBeTrue();
});
test('callback with error during onboarding redirects to the accounts step', function () {
$user = User::factory()->notOnboarded()->create();
Account::factory()->create(['user_id' => $user->id]);
$connection = BankingConnection::factory()->pending()->create([
'user_id' => $user->id,
]);
$response = $this->actingAs($user)
->get('/open-banking/callback?error=access_denied&error_description=User+denied+access');
$response->assertRedirect(route('onboarding', ['step' => 'create-account']));
$response->assertSessionHas('error', 'User denied access');
$connection->refresh();
expect($connection->trashed())->toBeTrue();
});
test('callback without code redirects with error', function () {
$user = User::factory()->onboarded()->create();
$response = $this->actingAs($user)->get('/open-banking/callback');