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

LancyBark's avatar

I get 302 response instead of 200 when capturing screenshot and user not keep logged in on the chrome extension

Hello, I have one strange issue. I get 302 response instead of 200 when capturing screenshot on chrome extension. Also, user can't keep logged in, despite having JWT token and as a result he must login repeatdly. I'm using Laravel as back-end with api auth. P.S. I do everything same with Java Springboot as a back-end it works like a charm. login.js

const url = 'http://local.requestmapper.com/api/ext/user/';


var form = document.getElementById('login_form');
document.getElementById("login_form").addEventListener("submit", login);

getUser();

form.addEventListener('submit', function (event) {
   

    var form = document.getElementById('login_form');

        var formData = new FormData();
        for (var i = 0; i < form.length; ++i) {
            formData.append(form[i].name, form[i].value)
        }

    fetch(url + 'login', {
        method: 'post',
        credentials: 'same-origin',
        mode: 'no-cors',
        cache: 'default',
        body: formData,
    })
        .then((response) => response.json())
        .then( (data) => {
            var token = data.token;
            console.log(token);
            localStorage.setItem('token', token);
            window.location.href = 'user.html';
        })
            .catch((error) => {
                console.log('Error:', error);
             })

    event.preventDefault();
})


function getUser() {

    var token = localStorage.getItem('token');

    fetch(url + 'check', {
        method: 'get',
        credentials: 'same-origin',
        cache: 'default',
        headers: { 'Authorization': 'Bearer  ' + token},
        mode: 'cors',
    })
        .then(response => {
            console.log(response.status)
            if (response.ok) {
                window.href.location = 'user.html';
            }
            return response.json();
        })
        .catch((error) => {
            console.log(error);
        })

}

app.js

const url = 'http://local.requestmapper.com/api/ext/user/';

document.getElementById('logout').addEventListener("click", logout);
document.getElementById('takess').addEventListener("click", takess);


getUser();

async function logout() {

    var token = localStorage.getItem('token');
  
    await fetch(url + 'logout', {
        method: 'post',
        credentials: 'same-origin',
        headers: {
            'Authorization': 'Bearer  ' + token,
        },
        mode: 'cors',
    })
        .then(data => data.json())
        .then( data =>{
            console.log(data);
            localStorage.removeItem('token');
            window.location.href = 'popup.html'
        })
        .catch((error) => {
            console.log(error);
        });
    event.preventDefault();
}

function takess() {

    //var token = localStorage.getItem('token');

    chrome.tabs.captureVisibleTab(null, {}, function (canvas) {
        upload(canvas);
        /*fetch(url + 'upload', {
            method: 'post',
            credentials: 'same-origin',
            headers: {
                'Authorization': 'Bearer  ' + token,
                'Content-Type':  'form-data',
            },
            mode: 'cors',
            body: JSON.stringify({ 'image': canvas }),
        })
            .then(response => console.log(response))
            .catch(error => console.log(error))*/
    });
    event.preventDefault();
}


function upload(canvas) {
    var token = localStorage.getItem('token');

    fetch(url + 'upload', {
        method: 'post',
        credentials: 'same-origin',
        headers: {
            'Authorization': 'Bearer  ' + token,
            'Content-Type': 'form-data',
        },
        mode: 'cors',
        body: JSON.stringify({ 'image': canvas }),
    })
        .then(response => console.log(response))
        .catch(error => console.log(error))
}

function getUser() {

    var token = localStorage.getItem('token');
  
    fetch(url + 'check', {
        method: 'get',
        credentials: 'same-origin',
        headers: {
            'Authorization': 'Bearer  ' + token,
        },
        mode: 'cors',
    })
        .then(response => {           
            response.json();
            console.log(response.json());
            if (!response.ok) {
                window.href.location = 'popup.html';
            }
        })
        .catch((error) => {
            console.log(error);
        })
}

ExtensionController.php

<?php

namespace App\Http\Controllers;


use App\Http\Requests\ImageRequest;
use App\Http\Requests\LoginRequest;
use App\Http\Requests\TestRequest;
use App\User;

use Illuminate\Support\Facades\Auth;
use Tymon\JWTAuth\Facades\JWTAuth;

class ExtensionController extends Controller
{

    public function login(LoginRequest $request)
    {
        $credentials = $request->only('email', 'password');

        if ($token =  JWTAuth::attempt($credentials)) {

            return response()->json(['status' => 'success', 'token' => $token], 200)->header('Authorization', $token);
        }
        return response()->json(['error' => 'Login failed'], 401);

    }


    public function uploadImage(ImageRequest $request)
    {

        $imagedata = str_replace(['data:image/jpeg;base64','data:image/png;base64'], '', $request->input('image'));

        $imagedata = str_replace('', '+', $imagedata);

        $imagedata = base64_decode($imagedata);

        $source = imagecreatefromstring($imagedata);

        $rotate = imagerotate($source, 0, 0);

        $imagename = storage_path('app/screenshots/') . time() . '.jpg';

        imagejpeg($rotate, $imagename, 100);

        return response()->json(['status' => 'success'], 200);
    }

    public function check(){
        if(Auth::guard('api')->check())
            return response()->json(['status' => 'User logged in'], 200);
    }

    public function refresh()
    {
        if($token = $this->guard('api')->refresh()){
            return response()
                ->json(['status' => 'success'], 200)
                ->header('Authorization', $token);
        }
        return response()->json(['error' => 'Token refresh error'], 401);
    }

    public function logout()
    {
        $this->guard('api')->logout();
        return response()->json([
           'status' => 'success',
            'msg' => 'Logged out successfully'
        ], 200);
    }

    private function guard()
    {
        return Auth::guard();
    }
}
0 likes
9 replies
LancyBark's avatar
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class ImageRequest extends FormRequest
{
 
    public function authorize()
    {
        return true;
    }
    public function rules()
    {
        return [
            'image' => 'required'
        ];
    }
}
`
rodrigo.pedra's avatar

generally a 302 from a POST request is either a manual redirect (which is not the case) or a validation redirect.

That is why I asked for the ImageRequest but it seems fine.

Try adding a \info('log') to the very beginning of the controller's uploadImage method.

If that message gets printed in your project's log files, it can be an exception being thrown inside the method.

If the message is not written into the logs, that means the controller method doesn't get hit, so it might be something else related to CORS, or other middleware.

Try adding the route path associated to the uploadImage method to your app's VerifyCsrfToken middleware's $except array.

LancyBark's avatar

Yeah, I thought about CORS thing, but without cors, I am not able to do any requests from extension, I'm allowed to do requests from extension in cors config file. CSRF I'm allowed all api routes exception by default.

rodrigo.pedra's avatar

Just crossed my mind that maybe the input is so big it is greater than your php.ini's post_max_size configuration?

I see that you are not doing a traditional image upload so upload_max_filesize might not interfere, but if the decoded image ends being greater then your post_max_size configuration, PHP will fail on handling the request.

Might not be it as I expect it to fail with a status code different than a 302, but I think that is worth checking it up.

LancyBark's avatar

My upload image size is smaller than 1MB, it depends where you want capture screenshot. My host is running on docker VM. If I upload huge size image, I should get 500 error.

rodrigo.pedra's avatar

I don't use docker, so I don't know if might be some related config.

Can you try running your app outside of a docker container so you can assert if the problem is with you app or with your docker container?

Or try running in a different docker container? Or using Laravel Homestead?

LancyBark's avatar

I use laradock, prebuilt thing for PHP projects. Trying on localhost same issue.

LancyBark's avatar

uploading with axios works like a charm. Still, it doesn't keep user logged in normally and I must repeatdl login.

Please or to participate in this conversation.