Grzegorz Adam Kowalski
Grzegorz Adam Kowalski

Reputation: 5565

Laravel: Access denied for user 'forge'@'localhost' (but no such user is used in the app)

I've a Laravel application that works well but for some strange reason there is a lot of strange messages in log files:

[2019-10-04 10:24:21] production.ERROR: SQLSTATE[HY000] [1045] Access denied for user 'forge'@'localhost' (using password: NO) {"exception":"[object] (Doctrine\DBAL\Driver\PDOException(code: 1045): SQLSTATE[HY000] [1045] Access d enied for user 'forge'@'localhost' (using password: NO) at /var/www/html/pzw_prod/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:31, PDOException(code: 1045): SQLSTATE[HY000] [1045] Access denied for user 'forge'@'l ocalhost' (using password: NO) at /var/www/html/pzw_prod/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:27)

The thing is, I'm not connecting to database with user named forge. My .env uses completely different logins. And, I repeat, everything works fine: communication with database works as expected. Data is being successfully read and written.

So... why this message in log files?

UPDATE:

config('database')

$ php artisan tinker
Psy Shell v0.9.9 (PHP 7.2.22 — cli) by Justin Hileman
>>> config('database')
=> [
     "default" => "mysql",
     "connections" => [
       "sqlite" => [
         "driver" => "sqlite",
         "url" => null,
         "database" => /* CENSORED */,
         "prefix" => "",
         "foreign_key_constraints" => true,
       ],
       "mysql" => [
         "driver" => "mysql",
         "url" => null,
         "host" => "127.0.0.1",
         "port" => "3306",
         "database" => /* CENSORED */,
         "username" => "prod_pzw",
         "password" => /* CENSORED */,
         "unix_socket" => "",
         "charset" => "utf8",
         "collation" => "utf8_unicode_ci",
         "prefix" => "",
         "prefix_indexes" => true,
         "strict" => true,
         "engine" => null,
         "options" => [],
       ],
       "pgsql" => [
         "driver" => "pgsql",
         "url" => null,
         "host" => "127.0.0.1",
         "port" => "3306",
         "database" => /* CENSORED */,
         "username" => "prod_pzw",
         "password" => /* CENSORED */,
         "charset" => "utf8",
         "prefix" => "",
         "prefix_indexes" => true,
         "schema" => "public",
         "sslmode" => "prefer",
       ],
       "sqlsrv" => [
         "driver" => "sqlsrv",
         "url" => null,
         "host" => "127.0.0.1",
         "port" => "3306",
         "database" => /* CENSORED */,
         "username" => "prod_pzw",
         "password" => /* CENSORED */,
         "charset" => "utf8",
         "prefix" => "",
         "prefix_indexes" => true,
       ],
     ],
     "migrations" => "migrations",
     "redis" => [
       "client" => "predis",
       "options" => [
         "cluster" => "predis",
         "prefix" => /* CENSORED */,
       ],
       "default" => [
         "url" => null,
         "host" => "127.0.0.1",
         "password" => null,
         "port" => "6379",
         "database" => 0,
       ],
       "cache" => [
         "url" => null,
         "host" => "127.0.0.1",
         "password" => null,
         "port" => "6379",
         "database" => 1,
       ],
     ],
   ]

UPDATE 2:

It seems that 'forge' is some kind of default login. It seems that sometimes Laravel is not using values from .env. How can I debug this?

$ cat config/database.php | grep -B 5 forge
        'mysql' => [
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
--
        'pgsql' => [
            'driver' => 'pgsql',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '5432'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
--
        'sqlsrv' => [
            'driver' => 'sqlsrv',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST', 'localhost'),
            'port' => env('DB_PORT', '1433'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),

Upvotes: 6

Views: 15598

Answers (5)

Arnaud Bouchot
Arnaud Bouchot

Reputation: 1993

none of the above did it for me but it has helped me figuring out that only my APP_ENV env variable was not loaded.

In my case above issue has occurred when running a fresh migration after upgrading Laravel from v6 > v8. One of the oAuth migrations (create_oauth_auth_codes_table) is somehow failing to access APP_ENV and defaults to a "forge" mysql user which like @Grzegorz said is defined nowhere appart from within the oauth lib.

For security reasons I am quite reluctant to hard code default credentials in config/database.php and it being clear text in my git repo.

I have replicated the MySQL details env vars without the environment appended in .env like this

before:

DB_HOST_TESTING=127.0.0.1;unix_socket=/tmp/mysql.sock
DB_DATABASE_TESTING=api
DB_USERNAME_TESTING=ubuntu
DB_PASSWORD_TESTING=***************

after

DB_HOST_TESTING=127.0.0.1;unix_socket=/tmp/mysql.sock
DB_DATABASE_TESTING=api
DB_USERNAME_TESTING=ubuntu
DB_PASSWORD_TESTING=***************

# duplicate details without env appended
DB_HOST=127.0.0.1;unix_socket=/tmp/mysql.sock
DB_DATABASE=api
DB_USERNAME=ubuntu
DB_PASSWORD=***************

I don't like having to do this either but I hope it will help someone.

Upvotes: 0

MimisK
MimisK

Reputation: 47

This problem still exists until now.

For me the solution was: php artisan config:clear & php artisan config:cache

Upvotes: 0

secusaurus
secusaurus

Reputation: 9

Another solution for others out there: In my case, the .env file was not readable for the php user. So changing the .env file to public read-only fixed it (chmod 664).

Upvotes: 0

VIKAS KATARIYA
VIKAS KATARIYA

Reputation: 6005

I had this exact same problem for the past few days and I think I solved it:

The settings in .env are not always used for some reason or other and occasionally Laravel will just use the default settings in config/app.php and config/database.php.

config/app.php:

// Change the 'SomeRandomString' to the generated key from your .env
'key' => env('APP_KEY', 'SomeRandomString'),
 
'cipher' => 'AES-256-CBC',

config/database.php

'mysql' => [
    'driver'    => 'mysql',
    'host'      => env('DB_HOST', 'localhost'),
    'database'  => env('DB_DATABASE', 'forge'),
    'username'  => env('DB_USERNAME', 'forge'),
    'password'  => env('DB_PASSWORD', ''),
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => '',
    'strict'    => false,
],

Change localhost, database, username, password to your actual settings from the .env.

This example is for MySQL if you use another database engine, change to those variables instead.

There might be a better solution (more secure?) but this is what so far kept the error from showing up.

Upvotes: 16

Warz
Warz

Reputation: 333

In a multithreaded webserver two instances of PHP will share the same environment variables. That's a problem, because process A may shut down and set its ENV variables to null while process B is running, then when process B is asking for a ENV variable it will return null, that's why env('DB_DATABASE', 'forge') will sometimes result in forge, and other times the correct ENV.

More info here, here and here

One solution is to stop running a threaded web server (even if you compile with thread safety PHP might run functions that are not thread safe.)

But a quick and simple fix to your issue is by running:

php artisan config:cache

That will cache your ENV and config which avoids the issue (laravel will not be calling getenv/putenv when configs are cached). The downside is you have to run this command anytime you make a change in your environment variables or configs.

Another solution I found is to place this line in your bootstrap/app.php file:

\Illuminate\Support\Env::disablePutenv();

Upvotes: 4

Related Questions