zetacomponents/authentication-database-tiein
Database-backed authentication filter for Zeta Components' Authentication framework. It validates user credentials against SQL tables via PDO, using configurable queries and group lookups to plug into the authentication filter chain.
What this actually is. zetacomponents/authentication-database-tiein is a bridge package from the Zeta Components suite (formerly eZ Components). It contains essentially one class — a filter that lets zetacomponents/authentication validate credentials against a row in a database table using zetacomponents/database as the connection layer. It is not a framework, not a guard, and not a hashing library. It is one ezcAuthenticationFilter implementation with a run($credentials) method returning a status.
Minimum viable setup (three packages, not one):
composer require zetacomponents/authentication \
zetacomponents/database \
zetacomponents/authentication-database-tiein
The libraries are PHP 5-era and are not PSR-4. You will almost always need Zeta's own classmap autoloader in addition to Composer's:
require 'vendor/autoload.php';
require 'vendor/zetacomponents/base/src/autoload.php'; // ezc* class map
Where to look first, in this order:
src/ in this repo — one filter class plus its options class. Read both fully; they are short.tests/ — Zeta test files are the de-facto documentation and show the exact constructor signature and option property names for the version you installed.zetacomponents/authentication's src/authentication.php and src/filters/ — this is where ezcAuthentication, ezcAuthenticationPasswordCredentials, and the status object live.zetacomponents/database's ezcDbFactory — DSN format (mysql://user:pass@host/db, sqlite:///path/to.db, pgsql://...).First use case — a login check:
$db = ezcDbFactory::create('mysql://app:[email protected]/legacy_app');
$options = new ezcAuthenticationDatabaseFilterOptions();
$options->table = 'users';
$options->columns = array(
'id' => 'email', // column compared against the username credential
'password' => 'password', // column compared against the password credential
);
$credentials = new ezcAuthenticationPasswordCredentials($email, $password);
$auth = new ezcAuthentication($credentials);
$auth->addFilter(new ezcAuthenticationDatabaseFilter($db, $options));
$result = $auth->run();
if ($result->isValid()) {
// credentials matched a row
}
Verify the exact constructor arity and option property names against your installed version's
src/— the tiein changed shape across releases, and there is no maintained documentation site left to rely on.
1. Legacy-table bridge (the only real reason to install this). You have an old application with a users table and want to authenticate against it as-is. The filter performs a direct string comparison between the supplied password credential and the column value. It does not hash. So if the legacy table stores md5($password) or sha1($password), you hash the incoming plaintext before constructing the credentials:
$credentials = new ezcAuthenticationPasswordCredentials($email, md5($password));
This is the single most important fact about the package: it is a comparison primitive, not a password verification layer.
2. Wrap it in a Laravel guard so the rest of the app doesn't know it exists. The leverage comes from making this a one-time adapter, not a pervasive dependency:
// AuthServiceProvider::boot()
Auth::viaRequest('legacy-db', function ($request) {
$result = app(LegacyDbAuthenticator::class)
->attempt($request->input('email'), $request->input('password'));
return $result->isValid() ? LegacyUser::findByEmail($request->input('email')) : null;
});
Or, preferably, a UserProvider returning an Authenticatable — that keeps Auth::user(), @auth, auth middleware, policies, and session handling working normally while all Zeta code is confined to one class. Bind the ezcDbHandler and the filter as singletons in the container so you don't open a new connection per request.
3. Lazy rehash-on-login migration. The highest-value workflow: use the tiein to prove the legacy password, then immediately upgrade.
if ($result->isValid()) {
if (! Hash::needsRehash($user->password)) {
// already migrated
} elseif ($this->verifyLegacy($email, $password)) {
$user->forceFill([
'password' => Hash::make($password),
'hash_algo' => 'bcrypt',
])->save();
}
}
Run this in a console command or a queued job to bulk-verify and flip users, then delete the Composer dependency entirely. The package's useful lifespan in a modern codebase is measured in weeks.
4. Composing multiple checks. ezcAuthentication takes multiple filters; adding several applies AND semantics. For OR semantics use ezcAuthenticationFilterGroup. This is occasionally useful for "legacy table OR new table" cutover periods, but a Laravel UserProvider with two connection lookups is cleaner and easier to test.
5. Connection strategy. Reuse Laravel's PDO where you can, or at minimum reuse one ezcDbHandler instance. The Database component is a thin wrapper over PDO; creating a handler per authentication attempt will exhaust connections under load. Keep a dedicated read-replica DSN for legacy lookups, and set PDO timeouts on the underlying connection so a slow legacy table doesn't stall your login path.
6. Exception translation. Wrap run() in a try/catch and translate Zeta exceptions into your app's auth exceptions. A DB outage and a wrong password must not look identical to your logging, alerting, or rate limiter.
Abandonment is the headline. Two stars, zero dependents, no commits in roughly a decade, and no namespace. There is no community, no Stack Overflow coverage, and no security response process. Treat it as vendored legacy code you own, not as a dependency. Read every line of src/ before shipping — it is short enough to do so.
PHP 8 compatibility is not guaranteed. Zeta Components target PHP 5.2–5.6 idioms. Expect deprecation noise at best and fatal errors at worst on 8.x (dynamic property creation, ezcBase file-map autoloading assumptions). If you cannot run PHP 7.4 for this slice, isolate the auth check behind an HTTP call to a small legacy-PHP sidecar rather than fighting the runtime.
Composer autoloading will bite you. The ezc* classes are not PSR-4. If you see Class "ezcAuthenticationDatabaseFilter" not found, you skipped the autoload.php require, or your classmap entry points at the wrong directory. Do not "fix" this by adding a custom autoloader for a name you guessed.
Passwords are compared, never hashed. Covered above, but it is the mistake people make twice: once by passing plaintext to a table of MD5s, and once by passing an MD5 to a table of plaintexts during a partial migration. Assert the algorithm per row if the table is mixed.
Table and column names are interpolated into SQL. They are configuration, not user input. Never derive $options->table or $options->columns from a request parameter, a tenant name, or a header.
Timing and enumeration. The filter does not implement constant-time comparison, and it does not unify "no such user" with "wrong password." Whatever the status object reports per filter, normalize it at your boundary: always return the same generic error, and put rate limiting in Laravel (RateLimiter), not in this package.
Debugging. $result->isValid() is a boolean; the status object also exposes per-filter results, which is how you tell "row not found" from "password mismatch" while developing. Zeta also respects ezcBase working-directory settings for any file-based config — if behaviour differs between CLI and web, check which directory ezcBase thinks it is in.
Extension points, in preference order. (a) Do not extend — wrap the whole thing in one Laravel service class and swap the implementation later. (b) Implement ezcAuthenticationFilter yourself if you need a different query shape (e.g. soft-deleted rows, tenant scoping). (c) ezcAuthenticationSession exists for "remember me" using raw PHP sessions — do not use it; let Laravel's session and Auth::login($user, $remember) handle that.
License metadata says NOASSERTION. GitHub could not identify the license file. Zeta Components was historically Apache-2.0, but verify the LICENSE/COPYING file in the repo and in zetacomponents/base before this goes anywhere near a legal review or a distributed product.
The honest recommendation. For greenfield Laravel work, this package has no place: a custom UserProvider over a second DB connection plus Hash::check() does the same job with zero abandoned code. Its legitimate use is a bounded migration window — verify legacy credentials, rehash to bcrypt/argon2, then remove zetacomponents/authentication, zetacomponents/database, and this tiein from composer.json in the same pull request that deletes the last call site.
How can I help you explore Laravel packages today?