Download the PHP package returnearly/laravel-cloudflare-zero-trust without Composer

On this page you can find all versions of the php package returnearly/laravel-cloudflare-zero-trust. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package laravel-cloudflare-zero-trust

Cloudflare Zero Trust for Laravel

Latest Version on Packagist GitHub Tests Action Status PHPStan Total Downloads

Security-first Cloudflare Access (Zero Trust) authentication for Laravel.

When you put an application behind Cloudflare Access, Cloudflare authenticates every request at the edge — via your identity provider for humans, or via service tokens for machines — and forwards a signed JWT to your origin in the Cf-Access-Jwt-Assertion header. This package verifies that JWT cryptographically and turns it into a first-class Laravel authentication primitive:

How it works

The package never trusts unverified input: principal classification happens only after cryptographic verification, and CF-Access-Client-Id / CF-Access-Client-Secret headers are never treated as origin credentials (Cloudflare validates those at the edge and mints a signed JWT for your origin).

Requirements

Installation

Publish the config file:

Quick start

1. Find your team domain (Cloudflare Zero Trust dashboard → Settings → Custom Pages) and the Application Audience (AUD) tag for each Access application (Access → Applications → your app → Overview).

2. Define your accounts and applications in config/cloudflare-zero-trust.php:

3. Protect your routes:

4. Use the verified identity:

That's it. Invalid, expired, or missing tokens are rejected before your route runs.

Configuration

Accounts and applications

Each account corresponds to one Cloudflare Zero Trust team (one team domain, one JWKS endpoint). Each application under it corresponds to a Cloudflare Access application with one or more AUD tags. Application names must be unique across all accounts, because middleware and guards refer to applications by name alone.

Configuration is validated eagerly — a missing audience, an unknown principal kind, or a non-HTTPS team domain throws InvalidConfiguration rather than silently misbehaving.

Package options

All top-level options with their environment variables and defaults:

Config key Env variable Default Purpose
enabled CLOUDFLARE_ZERO_TRUST_ENABLED true Master switch. When false, middleware passes requests through unvalidated and the guard returns no user.
header — Cf-Access-Jwt-Assertion Header containing the Access JWT. The CF_Authorization cookie is intentionally not read.
guard CLOUDFLARE_ZERO_TRUST_GUARD cloudflare Default guard name, for your own reference in config/auth.php.
clock_leeway CLOUDFLARE_ZERO_TRUST_CLOCK_LEEWAY 30 Seconds of clock skew tolerated when checking exp/nbf/iat.
jwks.cache_store CLOUDFLARE_ZERO_TRUST_CACHE_STORE default store Cache store for JWKS keys and identity payloads. Must support atomic locks.
jwks.cache_ttl CLOUDFLARE_ZERO_TRUST_JWKS_CACHE_TTL 3600 Seconds to cache the JWKS key set.
jwks.connect_timeout CLOUDFLARE_ZERO_TRUST_JWKS_CONNECT_TIMEOUT 2 JWKS HTTP connect timeout (seconds).
jwks.timeout CLOUDFLARE_ZERO_TRUST_JWKS_TIMEOUT 5 JWKS HTTP request timeout (seconds).
jwks.refresh_rate_limit CLOUDFLARE_ZERO_TRUST_JWKS_REFRESH_RATE_LIMIT 10 Max unknown-kid triggered refreshes per window.
jwks.refresh_rate_window CLOUDFLARE_ZERO_TRUST_JWKS_REFRESH_RATE_WINDOW 60 Rate-limit window (seconds).
identity.enabled CLOUDFLARE_ZERO_TRUST_IDENTITY_ENABLED true Global switch for identity enrichment.
identity.connect_timeout CLOUDFLARE_ZERO_TRUST_IDENTITY_CONNECT_TIMEOUT 2 Identity HTTP connect timeout (seconds).
identity.timeout CLOUDFLARE_ZERO_TRUST_IDENTITY_TIMEOUT 5 Identity HTTP request timeout (seconds).

Protecting routes with middleware

The cloudflare-access middleware takes the application name as its parameter:

To protect Laravel Horizon, reference the middleware in config/horizon.php:

What a rejected request gets

The middleware fails closed and never leaks why a token was rejected to the client (the detail goes into events instead):

Status When Body
401 Missing, malformed, expired, or otherwise invalid token Unauthenticated.
403 Token is valid but the principal kind is not allowed for this application Forbidden.
500 The middleware references an unknown application name Cloudflare Access is misconfigured.
503 The Cloudflare JWKS endpoint is unreachable and no cached keys exist Service Unavailable.

Requests that expect JSON receive {"message": "..."}; everything else gets a plain-text body.

Working with the verified principal

Once a request has been verified (by the middleware or the guard), the Access support class exposes the verified identity anywhere in your app:

All helpers return null/false on requests that were not verified, so they are safe to call unconditionally. State lives on the request instance (not the container), so it cannot bleed between requests under Octane; every helper also accepts an optional Request argument if you need to inspect a specific request.

UserPrincipal (SSO users)

A user token must carry type=app, a non-empty sub, and a valid email — otherwise it is rejected.

ServicePrincipal (service tokens)

A service token must carry type=app, an empty sub, and a non-empty common_name.

Both principal types implement Laravel's Authenticatable contract, so they also work with the auth guard below. kind() returns a PrincipalKind enum (PrincipalKind::User or PrincipalKind::Service).

Using the auth guard

Register a guard with the cloudflare driver in config/auth.php:

Then authenticate the standard Laravel way:

The guard and the middleware share one verification per request: whichever runs first stores the verified token on the request, and the other reuses it. The guard works standalone, but the package middleware gives you richer rejection behavior (403 vs 401, failure events), so stacking both is a good default:

Resolving Access users onto your own user model

By default the guard returns the package's stateless principals. To map SSO users onto your application's User model, implement ApplicationUserResolver:

A closure works too, if you configure the guard at runtime. Resolution rules:

Service tokens

Machine-to-machine clients authenticate to Cloudflare with CF-Access-Client-Id / CF-Access-Client-Secret headers. Cloudflare validates those at the edge and forwards a signed JWT like any other request — this package only ever validates the resulting Cf-Access-Jwt-Assertion and never treats the client ID/secret pair as origin credentials.

Service tokens are opt-in per application. The default principal set is users only, so add PrincipalKind::Service where machines should be allowed:

An application without PrincipalKind::Service rejects service-token JWTs with 403 even when they are cryptographically valid. Which service tokens can mint a JWT for an application's audience is governed by your Cloudflare Access policy — manage that allowlist in the Cloudflare dashboard, not at the origin.

Identity enrichment

The Access JWT deliberately carries a minimal claim set. When you need more — IdP groups, device posture, geo — the package fetches the full identity from your team domain's /cdn-cgi/access/get-identity endpoint:

Behavior to be aware of:

Events

Every authentication outcome dispatches an event you can hook for logging, metrics, or alerting. No event ever contains the raw JWT.

Event When Notable payload
AccessAuthenticated Middleware verified a token account, application, principalKind (enum), key ID
AccessAuthenticationFailed Middleware rejected a request reasonCode, account, application, safe context
IdentityEnriched Identity fetched from Cloudflare account, application, subject
JwksRefreshed JWKS key set fetched and cached account, issuer, keyCount
JwksRefreshFailed JWKS fetch failed account, issuer, reason

reasonCode values include missing_token, malformed_token, invalid_algorithm, unknown_kid, invalid_signature_or_claims, invalid_issuer, invalid_audience, invalid_type, missing_sub, invalid_email, disallowed_principal, and jwks_unavailable — enough granularity to alert on tampering separately from misconfiguration.

JWKS caching and key rotation

Cloudflare rotates your team's signing keys periodically. The package handles this without manual intervention:

Local development

Validation is on by default everywhere. There is deliberately no environment-name bypass — an app that skips auth because APP_ENV=local is one typo away from skipping it in production. To work without Cloudflare in front of you, disable the package explicitly:

When disabled, the middleware passes requests through and the guard returns no user.

To disable a single application while keeping others enforced, set that application's enabled flag (via a per-app env var in config):

Alternatively, run cloudflared locally and keep validation on — this exercises the real code path.

Testing your application

For feature tests that don't exercise authentication, disable the package in phpunit.xml:

To test the authentication path itself, fake the JWKS endpoint and mint your own RS256 tokens with firebase/php-jwt (already installed as a dependency of this package). Generate an RSA key pair in your test, serve its public JWK from the faked certs URL, and sign tokens with the private key:

For a service-token request, replace sub/email with 'sub' => '' and 'common_name' => 'my-client-id.access'. See this package's own test suite for a complete key-pair fixture you can adapt.

Security model

What the package guarantees:

What the package cannot do for you:

[!IMPORTANT] Your origin must not be directly reachable from the internet. A valid Access JWT is a bearer credential: anyone who obtains one can replay it against an exposed origin until it expires, bypassing Cloudflare's checks entirely. Put your origin behind Cloudflare Tunnel, mTLS, or equivalent network controls so the only path to your app is through Cloudflare.

See SECURITY.md for the full deployment threat model and the vulnerability disclosure policy.

Development

Contributing

See CONTRIBUTING.md.

Credits

License

The MIT License (MIT). See LICENSE.md for details.


All versions of laravel-cloudflare-zero-trust with dependencies

PHP Build Version
Package Version
Requires php Version ^8.3
firebase/php-jwt Version ^6.11|^7.0
illuminate/auth Version ^12.0|^13.0
illuminate/cache Version ^12.0|^13.0
illuminate/contracts Version ^12.0|^13.0
illuminate/http Version ^12.0|^13.0
illuminate/support Version ^12.0|^13.0
returnearly/actions-pattern Version ^2.0
spatie/laravel-package-tools Version ^1.16
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package returnearly/laravel-cloudflare-zero-trust contains the following files

Loading the files please wait ...