Skip to content

Repository files navigation

InitPHP Auth

A small PHP authentication & authorization library with pluggable storage adapters (session, signed cookie, or custom) and a tiny case-insensitive permission set.

Latest Stable VersionTotal DownloadsCILicensePHP Version Require


Features

  • Pluggable storage — pick SessionAdapter, CookieAdapter, or roll your own by implementing AdapterInterface.
  • Signed cookies — JSON payload sealed with constant-time HMAC-SHA256; tampered values are dropped before decoding ever runs.
  • Strict cookie defaultsSecure, SameSite=Lax, HttpOnly, and refusal of the unsafe SameSite=None + Secure=false combination.
  • Testable — inject a CookieWriterInterface to capture every setcookie() call in unit tests instead of touching response headers.
  • Tiny permission setPermission does case-insensitive membership checks and ships magic accessors ($perm->is_admin).
  • Honest contracts — typed properties, return types, @throws on every implementation-defined exception, PHPStan level 8 clean.

Requirements

  • PHP 8.0 or later (tested on 8.0 – 8.4)
  • ext-json, ext-hash (both bundled with default PHP builds)
  • initphp/parameterbag^2.0

Installation

composer require initphp/auth

Quick start

Session-backed auth

useInitPHP\Auth\Segment;
session_start();
$auth = Segment::session('auth');
$auth->set('user_id', 42)->set('role', 'editor');
if ($auth->has('user_id')) {
$user = loadUser($auth->get('user_id'));
}
$auth->destroy(); // unsets $_SESSION['auth']

Signed-cookie auth

useInitPHP\Auth\Segment;
$auth = Segment::cookie('auth', [
// 32+ byte secret. Generate with bin2hex(random_bytes(32)) and// load it from configuration — never hard-code it in source.'salt' => $_ENV['AUTH_COOKIE_SECRET'],
'path' => '/',
'domain' => 'example.com',
]);
$auth->set('user_id', 42);
echo$auth->get('user_id'); // 42$auth->destroy(); // emits a deletion cookie with matching path/domain

Permissions

useInitPHP\Auth\Permission;
// Comparison is case-insensitive: 'Editor', 'EDITOR', and 'editor'// are the same permission. The constructor normalizes its input the// same way push() and remove() do.$perm = newPermission(['Editor', 'post_list', 'post_edit']);
if ($perm->is('editor')) {
$perm->push('user'); // returns 1$perm->remove('post_edit'); // returns 1
}
$perm->is('admin', 'editor'); // true if any of the names is presentisset($perm->is_admin); // magic accessor for templates

Public API

Segment

MethodPurpose
Segment::session(string $name, array $options = []): selfBuild a segment backed by $_SESSION.
Segment::cookie(string $name, array $options): selfBuild a segment backed by a signed cookie (salt required).
Segment::custom(string $name, class-string $adapterClass, array $options = []): selfBuild a segment backed by your own adapter.
Segment::create(string $name, int|string $adapter, array $options = []): selfLegacy v1 factory; kept for BC.
adapter(): AdapterInterfaceEscape hatch for adapter-specific methods.
get/set/has/remove/collective/destroyForwarded to the underlying adapter.

AdapterInterface

MethodPurpose
get(string $key, mixed $default = null): mixedLook up a value or fall back to $default.
set(string $key, mixed $value): staticAssign / replace a value.
collective(array $data): staticAtomic bulk write. Cookie adapters emit one Set-Cookie instead of N.
has(string $key): boolExistence check (a stored null still counts as present).
remove(string ...$keys): staticDrop one or more keys (missing keys are a no-op).
destroy(): boolTear down the backing store. Subsequent calls raise RuntimeException.

Permission

MethodPurpose
is(string ...$names): boolTrue when any of the names is present. Case-insensitive.
push(string ...$names): intAdds names, returns the count actually inserted.
remove(string ...$names): intRemoves names, returns the count actually removed; the list is reindexed.
getPermissions(): list<string>Snapshot of the current permission list.

Magic accessors: $perm->is_admin (call), isset($perm->is_admin), unset($perm->is_admin).

CookieAdapter options

KeyTypeDefaultNotes
saltstring— requiredAt least 32 bytes. Use bin2hex(random_bytes(32)).
expiresint|nullnow + 86 400 sUnix timestamp. null resets to the default.
pathstring'/'RFC 6265 path scope.
domainstring''Empty disables the Domain attribute.
securebooltrueWhen false, modern browsers reject SameSite=None.
httponlybooltrueBlocks JS access via document.cookie.
samesite'Lax'|'Strict'|'None''Lax''None' is rejected unless secure=true.

Cookie wire format

base64url(json_encode($data)) . "." . hash_hmac('sha256', $json, $salt)

The signature is verified with hash_equals()before the JSON is decoded, so a forged or modified cookie never reaches the parser.

Exceptions

ExceptionRaised when
InvalidArgumentExceptionMissing/short/non-string salt, SameSite=None without Secure, unknown adapter constant, missing adapter class, class that does not extend AbstractAdapter.
RuntimeExceptionSessionAdapter constructed with no active session, or any read/write on an adapter whose destroy() has been called.
BadMethodCallExceptionPermission::__call() invoked with a name that does not start with is_.

Development

composer install
composer test# PHPUnit
composer analyse # PHPStan (level 8)
composer cs:check # PHP-CS-Fixer dry-run
composer cs:fix # PHP-CS-Fixer apply

CI runs the matrix across PHP 8.0, 8.1, 8.2, 8.3, and 8.4.

Documentation

Upgrading from v1

v2 ships intentional behaviour changes — most notably a new cookie format (old cookies become unreadable and are rolled), case-folding moved into the Permission constructor, a stricter cookie default profile, NullAdapter::has() returning false instead of true, and a clean adapter interface that no longer enforces a constructor signature. See docs/upgrading-from-v1.md.

Contributing & Security

Credits

License

Released under the MIT License.

About

Lightweight PHP 8 auth library: session, signed-cookie, and custom storage adapters plus a case-insensitive permission set.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages