Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Credentials Laravel Package

graham-campbell/credentials

A Laravel package by Graham Campbell for managing application credentials. It offers a simple, configurable way to store and retrieve sensitive values such as API keys, tokens, and passwords, helping keep them organized and out of your codebase. Integrates smoothly with Laravel's container and confi...

View on GitHub
Deep Wiki
Context7

Getting Started

Read the source before you read the README. This package's public descriptions disagree with each other — the marketing copy reads like a secrets vault, the Laravel-dev notes read like an auth driver, and the PM notes read like an OAuth/social-login package. Open composer.json, src/CredentialsServiceProvider.php, the published config, and the migration before you composer require. Your first hour of "getting started" is figuring out which of those three packages you actually installed.

Assuming the vault reading (which the description spells out most concretely), the minimal path is:

composer require graham-campbell/credentials

Then, because this predates Laravel's package auto-discovery:

  1. Add the service provider to config/app.php under providers:
    GrahamCampbell\Credentials\CredentialsServiceProvider::class,
    
  2. Optionally register the facade under aliases:
    'Credentials' => GrahamCampbell\Credentials\Facades\Credentials::class,
    
  3. Publish the config and the migration:
    php artisan vendor:publish --provider="GrahamCampbell\Credentials\CredentialsServiceProvider"
    
  4. Run php artisan migrate and confirm the credentials table exists with the expected columns (key/name, value, and the polymorphic owner columns if the trait is part of the picture).
  5. Add the trait to any model that owns credentials:
    use GrahamCampbell\Credentials\Traits\HasCredentials;
    
    class User extends Model
    {
        use HasCredentials;
    }
    

First use case to validate end-to-end: store one trivial secret on a user, read it back, then read it back from a fresh request. That second read is the one that fails when APP_KEY is wrong, the cache is holding a stale value, or the package silently stores plaintext. Prove the round-trip works before you store anything you care about.

If the source turns out to be the auth-driver reading instead, the getting-started path is different — you'll be editing config/auth.php to set a guard driver and a provider, and your first test is "can an unauthenticated request be rejected and an authenticated one accepted." Confirm which world you're in before writing any application code.

Implementation Patterns

Treat the trait as the primary API, and the facade as a convenience. Day to day, almost everything goes through the model:

// Set / rotate a credential
$user->setCredential('github_token', $plaintext);

// Read it back
$token = $user->getCredential('github_token');

// Read with a fallback — this matters more than it looks
$token = $user->getCredential('github_token') ?? config('services.github.token');

That fallback pattern is worth adopting everywhere. It lets you ship with an .env-based value for local development and switch to per-user stored values in staging/production without a code branch.

Wrap the trait in a small application-level service. The trait gives you magic methods that are hard to mock, hard to type-hint, and hard to reason about in a large codebase. Even a thin wrapper pays for itself:

class CredentialStore
{
    public function __construct(private HasCredentials $owner) {}

    public function get(string $key, ?string $default = null): ?string
    {
        return $this->owner->getCredential($key) ?? $default;
    }

    public function put(string $key, string $value): void
    {
        $this->owner->setCredential($key, $value);
    }
}

Now every call site depends on CredentialStore, not on the package. When the package is forked, vendored, or replaced with a first-party implementation, you change one class.

Store the shape you'll need later. The most common real-world pattern is many credentials per user — a GitHub token, a Google refresh token, a personal API token. Model them as a set of named keys on the owning model rather than one big JSON blob. A JSON blob means you can't rotate one secret without touching the others, and you lose the ability to reason about key names in the database.

Use it in jobs and commands the way you'd use any repository. Because the trait hangs off an Eloquent model, this works inside a queued job exactly as it does in a controller — as long as you load the model:

public function handle(): void
{
    $user  = User::findOrFail($this->userId);
    $token = $user->getCredential('provider_token');

    Http::withToken($token)->post(...);
}

Do rotation as an explicit, tested flow. Set the new value, use it once to confirm it works, then leave the old one recoverable or overwrite it — but pick one and write it down. The most common bug here is a half-completed rotation that leaves the account authenticated against a stale token that hasn't yet been revoked by the provider.

Test against the trait, not against the encrypted storage. In tests, RefreshDatabase + a real user model is the fastest path. Assert on what getCredential returns; don't reach into the database to assert on ciphertext, because the ciphertext is a Laravel implementation detail you don't own.

Gotchas and Tips

Laravel 5 only, no auto-discovery. If you're on Laravel 8+ this package won't install cleanly, and if you force it you inherit a dependency that will block every future framework upgrade. Verify composer.json's illuminate/* constraints against your actual framework version before you start. Plan the exit path the day you adopt.

APP_KEY is the whole security model. Credentials are encrypted with Laravel's crypter, which means anyone with a database dump and your APP_KEY can read every secret in the table. That's fine for a conventional app, but treat APP_KEY with the same care as a root password, and know that php artisan key:generate on an existing install makes every stored credential undecryptable. Rotate keys with a deliberate re-encrypt job, never blindly.

Decryption failures are silent until they aren't. A bad key or a truncated value typically surfaces as a DecryptException deep inside a getter — or worse, returns null and your fallback quietly kicks in. Add a test that deliberately corrupts a value and asserts your application's behaviour, so you find out how it fails before production does.

The facade is a trap for testability. Credentials::get(...) reads nicely but is a static call into the container. Prefer the trait, or the wrapper service, and keep the facade for tinker and one-off scripts. Anywhere you're tempted to inject the facade, inject your CredentialStore instead.

Cache invalidation is a real failure mode. If the package uses the cache for lookups (the description suggests cache-backed retrieval), then rotation can leave a stale secret being served somewhere. After any write, flush the relevant cache key explicitly, and know which cache store the package is using — if it's array in one environment and redis in another, your rotation bugs won't show up in local dev.

Watch the polymorphic columns. If credentials attach to models via a morph relation, credentialable_type must match the exact class name Eloquent stores, which means renaming or moving a model class orphans its credentials. Treat model class names in that column as part of your data contract.

Extension points are the reason to read the source. The service provider, a manager/factory class, and the config file are the three places worth understanding. If you're going to fork (and given the zero-adopter base, you probably should), those are the files you actually own. Everything else is glue.

Don't debug a broken trait by editing vendor code. vendor/graham-campbell/credentials will be overwritten on the next composer update. If you need a fix, fork it, point the repo's composer.json at your fork with a pinned version, and apply the patch there.

Budget a security review, not just a spike. A working demo takes an afternoon. The review — who can read the table, what APP_KEY handling looks like, whether values are hashed or encrypted, whether there's any audit trail — takes a week and is the part that determines whether you can put this anywhere near real credentials. Do the review before, not after, the first production secret is written.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core