Skip to content

Access Requests

Access Gate protects a named area, accepts public registration requests, grants access to users or email addresses, and can issue browser tokens for guest access.

  1. A public route or SubmitAccessGatePublicAction passes an area key and email address to CreateRegistrationAction.
  2. The action validates built-in fields and any registered RegistrationField implementations.
  3. Existing approved or claimed registrations for the same email can receive a new claim token instead of creating duplicates.
  4. Areas using first_n_auto_approve can approve the next pending registration automatically.
  5. Approved registrations receive a claim token. Claiming the token creates or reuses a grant and can set the browser token cookie.

ResolveAccessGateAccessAction is the read side. It checks area status, schedule, site scope, authenticated grants, email grants, and browser tokens.

RoutePurpose
GET /access/request/{area}Shows the public request form.
POST /access/request/{area}Stores a registration request.
GET /access/claim/{token}Claims an emailed token.
POST /access/logout/{area}Revokes the current browser token for an area.
GET /access/status/{area}Optional status endpoint when access-gate.status_endpoint_enabled is true.

The route prefix comes from access-gate.route_prefix.

Request methods decide how a visitor asks for access. They implement AccessRequestMethod and are stored in AccessRequestMethodRegistry.

The example translation namespace is the host app’s namespace. Use the package namespace that owns your request method.

use Capell\AccessGate\Contracts\AccessRequestMethod;
use Capell\AccessGate\Models\Area;
final class EmailAccessRequestMethod implements AccessRequestMethod
{
public function key(): string
{
return 'email';
}
public function label(): string
{
return __('host-app::access_gate.provider_login');
}
public function description(): ?string
{
return null;
}
public function isEnabled(Area $area): bool
{
return true;
}
public function isPrimary(Area $area): bool
{
return true;
}
public function url(Area $area, ?string $requestedUrl = null): string
{
return route('capell-access-gate.request', [
'area' => $area,
'requested_url' => $requestedUrl,
]);
}
}

Register it from a service provider:

use Capell\AccessGate\Support\AccessRequestMethodRegistry;
$this->app->afterResolving(
AccessRequestMethodRegistry::class,
static function (AccessRequestMethodRegistry $registry): void {
$registry->register(EmailAccessRequestMethod::class);
},
);

Custom fields implement RegistrationField. The return value is stored in field_values.

Use the package namespace that owns the field label; the value is shown on the public request form.

use Capell\AccessGate\Contracts\RegistrationField;
use Capell\AccessGate\Data\RegistrationFieldValue;
use Illuminate\Support\Facades\Validator;
final class CompanyRegistrationField implements RegistrationField
{
public function key(): string
{
return 'company';
}
public function label(): string
{
return __('host-app::access_gate.company');
}
public function validate(array $input): RegistrationFieldValue
{
$validated = Validator::make($input, [
'company' => ['required', 'string', 'max:120'],
])->validate();
return new RegistrationFieldValue('company', $validated['company']);
}
}

Register it with RegistrationFieldRegistry:

use Capell\AccessGate\Support\RegistrationFieldRegistry;
$this->app->afterResolving(
RegistrationFieldRegistry::class,
static function (RegistrationFieldRegistry $registry): void {
$registry->register(CompanyRegistrationField::class);
},
);

Access Gate can receive requests through Public Actions by using SubmitAccessGatePublicAction. The payload must include:

{
"area": "capell-preview",
"email": "[email protected]",
"requested_url": "https://example.test/preview"
}

The handler strips area and user_id, merges submission metadata, and calls CreateRegistrationAction.

KeyPurpose
access-gate.connectionOptional database connection.
access-gate.route_prefixPublic route prefix.
access-gate.status_endpoint_enabledEnables the public status route.
access-gate.claim_token_ttl_minutesClaim token lifetime.
access-gate.cookies.browser_token.*Browser token cookie name, lifetime, domain, secure flag, and SameSite policy.
access-gate.middleware.defaultMiddleware used by public routes.
access-gate.middleware.page_cache_aliasesMiddleware aliases stripped when gated pages must not be cached as public HTML.
access-gate.registration.methodsBuilt-in request method configuration.
access-gate.registration.identity_methodsOptional identity method configuration.
access-gate.registration.fieldsOptional registration field configuration.
access-gate.install.default_area.*Defaults used by the setup/install commands.
capell:access-gate-install
capell:access-gate-setup
capell:access-gate-doctor

Use capell:access-gate-doctor when a gated route behaves like a public cached page, or when claim/browser tokens fail unexpectedly.

Do not let a denied or personalized gated response be written as anonymous HTML. Keep the frontend cache middleware aliases in access-gate.middleware.page_cache_aliases current when the host app changes cache middleware names.