Home>Solution Center>Where should a web application store passwords, API keys, and database credentials?

Secrets management

Where should a web application store passwords, API keys, and database credentials?

User passwords and application secrets are both sensitive, but they are not the same security problem.

A user password normally should not be recoverable at all, so applications store a secure hash. A database password or API key must sometimes be presented to another system, so the application needs a protected way to retrieve its real value. A PHPRunner application can use environment-specific configuration or a secrets service without exposing those values to the browser.

User passwords

Goal: verify that the user knows the password without storing the original password.

Typical approach: salted password hashing using an appropriate password-hashing algorithm.

Application secrets

Goal: allow the application to authenticate to a database, API, encryption service, or other system.

Typical approach: protected configuration, environment-managed secrets, or a dedicated secrets manager.

Quick answer: Hash user passwords; do not try to recover them. Treat database passwords, API keys, client secrets, and encryption keys as application secrets that need controlled retrieval, limited access, rotation, and protection from source-code exposure.

Why hashing does not solve the API-key problem

A hash is useful when you only need to compare a submitted secret with a stored verifier.

At login, the user supplies the password again, so the application can verify it without knowing the original stored password. A database connection is different: the application itself must authenticate to the database, so it needs the actual credential or another usable token.

That is why a one-way password hash and a secrets vault solve two different problems.

Move secrets out of ordinary source code

Hard-coded credentials are easy to copy, commit, email, and forget.

1

Separate configuration

Keep environment-specific credentials outside normal application logic.

2

Limit access

Give the application identity access only to the secrets and systems it actually needs.

3

Use a secrets manager when appropriate

Services such as Azure Key Vault can centralize storage and access control for production credentials.

4

Plan rotation

Know how a password or API key can be changed without manually editing many copies of the application.

The secret store does not remove least-privilege requirements

A perfectly protected administrator password is still an administrator password.

Use database accounts and API credentials with only the permissions the application needs. Separate unrelated applications so a credential leak in one system does not automatically expose another.

Also avoid placing secrets in client-side JavaScript, URLs, logs, error messages, or other places that can be exposed to users or monitoring systems.

Where PHPRunner fits

The goal is to keep the architecture understandable while reducing repetitive application work.

PHPRunner applications can use protected configuration and custom connection logic; your existing Azure Key Vault tutorial demonstrates retrieving a database secret at runtime rather than hard-coding it in the connection.

NeedPHPRunner approach
User passwordsUse password hashing and application authentication features rather than storing plain-text passwords.
Database credentialsUse appropriately privileged database accounts and environment-specific connection configuration.
External secretsRetrieve API or database credentials from a secrets manager when the hosting environment and risk justify it.
Custom connection logicUse server-side connection or custom code to obtain the secret without exposing it to the browser.

Final recommendation

First classify the secret, then choose the protection model.

If the application only needs to verify a user knows a password, store a secure password hash. If the application must present a credential to another system, manage that value as an application secret.

Separating those two cases avoids the common mistake of treating every sensitive string as if it could be protected in the same way.