ShadowUserDenied
Thrown by a {@see ResolvesShadowUser} when a federated identity
authenticated successfully at the auth-server but must not enter
THIS app — e.g. local provisioning is out-of-band
(bridge.create_missing=false) and no local user matches.
The bridge controller turns this into a friendly login-page redirect rather than a 500.
Methods
reason()
function reason(): stringProvisioning is off (bridge.create_missing=false) and no local user matched. / public const REASON_NO_LOCAL_ACCOUNT = ‘no_local_account’; /* The matched local user is soft-deleted and bridge.on_trashed=deny. */ public const REASON_DEACTIVATED = ‘deactivated’;
public function __construct( string $message = 'No local account is linked to this identity.', private readonly string $reason = self::REASON_NO_LOCAL_ACCOUNT,) { parent::__construct($message, 403);}
/**Stable machine-readable reason so a host app can localize the message or route different denials to different screens (e.g. deactivated → support, no-account → contact-admin). Read it in the bridge controller’s ShadowUserDenied catch.