'test-fastapi-agent-secret-0123456789ABCDEF']); config(['services.fastapi_agent.jwt_algorithm' => 'HS256']); }); function fastApiAgentToken(string $openid): string { return JWT::encode([ 'sub' => $openid, 'iat' => time(), 'exp' => time() + 3600, ], 'test-fastapi-agent-secret-0123456789ABCDEF', 'HS256'); } test('a FastAPI JWT booking is stored against the verified openid, ignoring a spoofed body value', function () { config(['booking.back_seat_enabled' => true]); $route = EvRoute::factory()->create(['is_active' => true]); $timeSlot = DepartureTimeSlot::factory()->create(); $route->timeSlots()->attach($timeSlot->id, ['is_active' => true]); RoutePricing::factory()->create([ 'ev_route_id' => $route->id, 'vehicle_option' => VehicleOption::BackSeat, 'price' => '15000.00', ]); $token = fastApiAgentToken('real-customer-openid'); $this->withHeader('Authorization', "Bearer {$token}") ->withHeader('Device-Type', 'android') // the agent's own channel always wins, ignored here. ->postJson('/api/v1/bookings', [ 'ev_route_id' => $route->id, 'departure_time_slot_id' => $timeSlot->id, 'travel_date' => now()->addDay()->toDateString(), 'selections' => [['vehicle_option' => 'back_seat', 'passenger_count' => 1]], 'passenger_name' => 'Jane Doe', 'passenger_phone' => '+959123456789', 'pickup_address' => '123 Pickup St', 'dropoff_address' => '456 Dropoff Ave', 'openid' => 'spoofed-openid', ]) ->assertCreated(); $booking = Booking::sole(); expect($booking->openid)->toBe('real-customer-openid') ->and($booking->user_id)->toBeNull() ->and($booking->created_by_channel)->toBe(BookingChannel::Agent); }); test('a FastAPI JWT can list and show only its own openid\'s bookings', function () { $mine = Booking::factory()->create(['openid' => 'agent-openid-mine']); Booking::factory()->create(['openid' => 'agent-openid-someone-else']); $token = fastApiAgentToken('agent-openid-mine'); $this->withHeader('Authorization', "Bearer {$token}") ->getJson('/api/v1/bookings') ->assertSuccessful() ->assertJsonCount(1, 'data') ->assertJsonPath('data.0.id', $mine->id); $this->withHeader('Authorization', "Bearer {$token}") ->getJson("/api/v1/bookings/{$mine->booking_ref}") ->assertSuccessful() ->assertJsonPath('data.id', $mine->id); }); test('a FastAPI JWT gets a 404 for a booking belonging to a different openid', function () { $someoneElses = Booking::factory()->create(['openid' => 'agent-openid-someone-else']); $token = fastApiAgentToken('agent-openid-mine'); $this->withHeader('Authorization', "Bearer {$token}") ->getJson("/api/v1/bookings/{$someoneElses->booking_ref}") ->assertNotFound(); });