Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

marcelok's avatar

Deploy a Laravel API and ReactJs frontend in an Apache Server

Hello everyone.

I'm trying to deploy a Laravel API with React in an Apache server.

My main issue is that some devices get an error message when they try to log in to the website. This happens in some mobile phones, but using the same credentials on other mobile phones works perfectly.

The message received is "ERROR: unauthenticated".

This is what I have.

REACT environment

react/src/login.js

...
axios.defaults.baseURL = process.env.REACT_APP_API || "http://localhost:8000";
axios.defaults.headers.common["Accept"] = "application/json";
axios.defaults.withCredentials = true;
...

The REACT_APP_API variable is defined in react/.env

REACT_APP_API="https://api.domain.com.au"

This file in react/public/.htaccess

Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]

package.json file

...
"homepage": "https://domain.com.au",
...

I run the npm run build command on my local machine and I upload the build folder in /var/www/frontend/build/

This is the virtual host for the react part /etc/apache2/sites-enabled/frontend-le-ssl.conf

<IfModule mod_ssl.c>
<VirtualHost *:443>
        ServerAdmin [email protected]
        ServerName domain.com.au
        ServerAlias www.domain.com.au
        DocumentRoot /var/www/frontend/build

        <Directory /var/www/frontend/build/>
            Options +FollowSymLinks
            AllowOverride All
            Require all granted
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        <IfModule mod_dir.c>
            DirectoryIndex index.php index.pl index.cgi index.html index.xhtml index.htm
        </IfModule>


Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/domain.com.au-0001/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/domain.com.au-0001/privkey.pem
</VirtualHost>
</IfModule>

This is what I have in the login post

axios.get("/sanctum/csrf-cookie").then((responseCrsf) => {
            axios.post("/login", input)
                .then((response) => {
                    axios.get('/api/user')
                        .then(({ data }) => {
                            const { perfil_id } = data;
                            setDisabled(true);
                            setTimeout(() => {
                                if (perfil_id === 3) {                                    
                                    window.history.go(-1)                                    

                                } else {                                    
                                    window.location.replace('/admin/products');
                                }
                            }, 1000);
                        })
                        .catch((error) => {
                            setError({ error: true, message: error.response.data.message });
                        })
                        .finally(() => setDisabled(false));                    
                })
                .catch((errorLogin) => {
                    setDisabled(false);
                    setError({ error: true, message: errorLogin.response.data.message });
                })
        });

Laravel production environment

The app is installed under /var/www/api

.env file

...
APP_URL=https://api.domain.com
SANCTUM_STATEFUL_DOMAINS=domain.com.au
SESSION_DOMAIN=.domain.com.au
...

/etc/apache2/sites-enabled/api-le-ssl.conf

<IfModule mod_ssl.c>
<VirtualHost *:443>
        ServerAdmin [email protected]
        ServerName api.domain.com.au
        DocumentRoot /var/www/api/public

        <Directory /var/www/api/public/>
            Options Indexes FollowSymLinks
            AllowOverride All
            Require all granted
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        <IfModule mod_dir.c>
            DirectoryIndex index.php index.pl index.cgi index.html index.xhtml index.htm
        </IfModule>


Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/api.domain.com.au-0001/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/api.domain.com.au-0001/privkey.pem
</VirtualHost>
</IfModule>

Any idea about the error? It took me many hours to get this setup but I have doubts if is the correct way, feel free to recommend me improvements.

Cheers.

0 likes
1 reply
LaryAI's avatar
Level 58

The "ERROR: unauthenticated" message could be caused by a few different issues, but one possibility is that the CSRF token is not being sent or received correctly. Here are a few things to try:

  1. Make sure that the CSRF cookie is being set correctly. In Laravel, you can do this by calling the csrf-cookie route before making any POST requests. In your login code, you are already doing this with axios.get("/sanctum/csrf-cookie"), so that should be fine.

  2. Make sure that the CSRF token is being sent with the login request. In your login code, you are not explicitly sending the CSRF token, but Axios should automatically include it in the request headers because you have set axios.defaults.withCredentials = true. However, you can check the request headers in your browser's developer tools to make sure that the CSRF token is being sent.

  3. Make sure that the CSRF token is being received correctly by the server. In Laravel, the CSRF token is checked automatically for all POST requests. If the token is not present or does not match, Laravel will return a 419 error. You can check the server logs to see if any 419 errors are being generated.

If none of these suggestions solve the problem, you may need to do some more debugging to figure out what is going wrong. For example, you could try logging the request and response data in your login code to see if there are any obvious issues. You could also try reproducing the problem on a different device or browser to see if it is specific to certain environments.

Please or to participate in this conversation.