modera/mjr-security-integration-bundle
Modera MJR Security Integration Bundle wires security into Modera MJR-based PHP applications, packaging the configuration and services needed to connect authentication and access control with the rest of your stack. A niche integration for projects already using Modera components.
This is a Symfony bundle, not a Laravel package — before anything else, correct that framing. It exists solely to wire MJR (Modera's JSON-RPC bundle) into Symfony's Security component so RPC endpoints participate in firewalls, voters, and access control. There is no Laravel equivalent to "install and go."
Since you cannot composer require this into a Laravel app, the first move is deciding what you're actually after:
Auth guards/providers, middleware, Gate/Policy, and Sanctum or Passport for API tokens. This package offers nothing you can execute in Laravel 10/11/12 on PHP 8.1+; its last release is 2016-07-18, targeting Symfony 2.x/3.x and PHP 5.6/7.0-era APIs.DependencyInjection/*Extension.php, Resources/config/services.yml) — shows how the security stack is wired to the RPC dispatcher.(principal, resource, policy) evaluation happens before the handler is invoked.First meaningful use case for a Laravel team: treat the repo as specification input for your own middleware. The question it answers — "where do we centralize authentication and authorization so RPC/business handlers stay clean?" — is one you should answer natively rather than import.
You will not be using this package directly. You will be transliterating its design idioms into Laravel. Here is what is worth borrowing, mapped to the Laravel equivalent:
The bundle's core idea: wrap the RPC dispatcher so every call is authenticated and authorized before the handler runs. Handlers never see auth concerns.
Laravel translation:
// app/Http/Middleware/AuthorizeRpcCall.php
public function handle($request, Closure $next)
{
$user = $request->user();
abort_unless($user, 401);
$action = $request->input('method'); // RPC method name
$params = $request->input('params', []);
Gate::authorize('rpc.'.$action, $params);
return $next($request);
}
Register it in bootstrap/app.php (Laravel 11+) or app/Http/Kernel.php under the route group serving your RPC endpoint.
The bundle lets you map each MJR method to a permission/role. In Laravel, model this explicitly in a Gate::before or a dedicated policy:
// app/Providers/AuthServiceProvider.php
Gate::define('rpc.user.create', fn (User $u, array $p) => $u->can('users.create'));
Gate::define('rpc.order.cancel', fn (User $u, array $p) => $u->can('orders.cancel', $p['order_id']));
Keep the mapping in a single file or config (config/rpc-permissions.php) so it reads like the bundle's YAML mapping — one source of truth, greppable.
The bundle exposes Symfony compiler passes so app code can register new guards/voters without forking. The Laravel analogue is tagged bindings + a registrar class:
// Tag your RPC authorizers
$this->app->tag([OrderPolicy::class, UserPolicy::class], 'rpc.authorizers');
// In an RpcAuthorizationRegistry
foreach ($this->app->tagged('rpc.authorizers') as $auth) {
$this->register($auth);
}
This gives you the same "extend without touching core" property the bundle had.
The bundle's YAML (config.yml) controls which RPC firewalls apply to which paths. Mirror that with config/rpc.php and a thin middleware that reads config('rpc.firewalls.*'). Resist putting these rules inside controllers — the whole point of the original was to keep them at the seam.
If JSON-RPC is the real requirement, do not resurrect MJR. Use a maintained Laravel JSON-RPC package (e.g., sajya/server or friendsofphp/laravel-json-rpc in the community) and wrap it with the middleware above. The pattern transfers; the code doesn't.
composer.json. Even as a dev- dependency, it will force Symfony 2/3 and PHP 7.0-era constraints into your solver and can block unrelated upgrades. If you need to read the source, git clone it outside the project.Laravel\Gate, Laravel\Sanctum, and the auth middleware — not here.TokenStorage vs Laravel's Auth::guard()->user() behave differently around stateless/stateful requests. If you're doing API + web in one app, plan for two guards.DependencyInjection/ — the extension class is where the service graph and config parameters are defined. Every behavior the bundle offers is reachable from there.DependencyInjection/Compiler/ — that's where the "extend without forking" hooks live. Port the concept (tagged services) rather than the specific voting mechanism.Resources/config/services.yml is the wiring diagram. Read it top-to-bottom; it tells you which MJR services get decorated and by whom.security.yml firewalls.*.listeners. If you're auditing a legacy Symfony app, that's the config to inspect first to confirm the integration is actually active (a silently disabled firewall is the failure mode that produces no errors, just unauthorized access).rpc.order.cancel, not Rpc.Order.Cancel) or you'll produce silent policy misses.config/rpc.php, you must implement merging yourself or use array_replace_recursive in a service provider.composer.lock requiring an active maintainer and a release within N months for auth* / security* packages). This bundle is the exact calibration example.Bottom line for a Laravel developer: this is a read-only 2016 Symfony artifact with zero dependents and zero stars. Do not install it, do not wrap it, do not hope it "mostly works." Extract the pattern (transport-boundary authorization, config-driven method-to-permission mapping, tagged extension points) and implement it natively with Gate/Policy, middleware, and a maintained JSON-RPC package if you need one. The metrics on this package are not a hurdle to overcome — they're the answer.
How can I help you explore Laravel packages today?