4

Helloy everbody,

I have symfony and doctrine on the Server and Angularjs on the Client. I want to make a Login Endpoint. The Login is working and i get a PHPSESSID Cookie.

After the Login i perfom a subsequent request. At this requests i get an InsufficientAuthenticationException:

Full authentication is required to access this resource. (500 Internal Server Error)

Header of subsequent Request:

Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0
Accept: application/json, text/plain, */*
Accept-Language: de,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://localhost/frontend/admin/
Cookie: PHPSESSID=cllc3om5ascumuluofchu36aoc
DNT: 1
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache

security.yml:

security:
    encoders:
        App\Entity\User:
          algorithm: bcrypt
          cost: 20

    providers:
        database_users:
            entity: { class: App\Entity\User, property: username }
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            anonymous: ~
            json_login:
                check_path: login

            logout:
                path: logout
                target: http://localhost/frontend/

    access_control:
        - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/logout, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/, roles: ROLE_USER  }

The Logs:

[2018-08-27 22:59:22] security.INFO: User has been authenticated successfully. {"username":"alex"} []
[2018-08-27 22:59:38] php.INFO: User Deprecated: Doctrine\Common\ClassLoader is deprecated. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Doctrine\\Common\\ClassLoader is deprecated. at D:\\xampp\\htdocs\\symfony\\vendor\\doctrine\\common\\lib\\Doctrine\\Common\\ClassLoader.php:7)"} []
[2018-08-27 22:59:38] doctrine.DEBUG: SELECT t0.id AS id_1, t0.username AS username_2, t0.password AS password_3, t0.is_active AS is_active_4, t0.role AS role_5, t0.customer_id AS customer_id_6 FROM app_users t0 WHERE t0.id = ? [1] []
[2018-08-27 22:59:38] security.DEBUG: Token was deauthenticated after trying to refresh it. {"username":"alex","provider":"Symfony\\Bridge\\Doctrine\\Security\\User\\EntityUserProvider"} []
[2018-08-27 22:59:38] security.INFO: Populated the TokenStorage with an anonymous Token. [] []
[2018-08-27 22:59:38] security.DEBUG: Access denied, the user is not fully authenticated; redirecting to authentication entry point. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException(code: 403):

I don't know where my mistake is or how i can debug this problem.

EDIT: Login in PHP:

    /**
     * @Route("/login", name="login")
     * @param Request $request
     * @return Response
     */
    public function login(Request $request)
    {
        $securityContext = $this->container->get('security.authorization_checker');
//        $tokenStorage = $this->container->get('security.token_storage');
//        $token = $tokenStorage->getToken();
//        var_dump($token);  => user has not Token!
        if ($securityContext->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
            return new Response('http://localhost/frontend/admin/');
        } else {
            return new Response('', 500);
        }
    }

In JS:

<script type="text/javascript">
    $( "#loginForm" ).submit(function( event ) {
        event.preventDefault();
        let $form = $(this);
        let username = $form.find( "input[name='username']" ).val();
        let password = $form.find( "input[name='password']" ).val();
        let data = "{";
        data += '"username": "'+username+'", ';
        data += '"password": "'+password+'" ';
        data += "}";

        $.ajax({
            method: 'post',
            url:'http://localhost/symfony/public/login',
            type:"POST",
            data:data,
            contentType:"application/json; charset=utf-8"
            //dataType:"json"
        }).done(function(response) {
            $(location).attr('href', response)
        }).fail(function() {
        });
    });
</script>

EDIT 2: User Entity:

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\EquatableInterface;

/**
 * @ORM\Table(name="app_users")
 * @ORM\Entity()
 */
class User implements UserInterface, \Serializable, EquatableInterface
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=25, unique=true)
     */
    private $username;

    /**
     * @ORM\Column(type="string", length=64)
     */
    private $password;

    /**
     * @ORM\Column(name="is_active", type="boolean")
     */
    private $isActive;


    public function __construct()
    {
        $this->isActive = true;
    }

    public function getUsername()
    {
        return $this->username;
    }

    public function getSalt()
    {
        return null;
    }

    public function getPassword()
    {
        return $this->password;
    }

    public function getRoles()
    {
        return array('ROLE_USER');
    }

    public function eraseCredentials()
    {
        $this->password = null;
    }


    /** @see \Serializable::serialize() */
    public function serialize()
    {
        return serialize(array(
            $this->id,
            $this->username,
            $this->password
            // see section on salt below
            // $this->salt,
        ));
    }

    /** @see \Serializable::unserialize() */
    public function unserialize($serialized)
    {
        list (
            $this->id,
            $this->username,
            $this->password
            ) = unserialize($serialized, array('allowed_classes' => false));
    }

    public function isEqualTo(UserInterface $user)
    {
        if ($this->password !== $user->getPassword()) {
            return false;
        }

        if ($this->username !== $user->getUsername()) {
            return false;
        }

        return true;
    }
}

Greetings,

Alex

2 Answers2

0

The token getting deauthenticated when refreshing speaks to a problem with your User class, if it's a recent (4+) Symfony does your user implement EquatableInterface and have an equals method? Something like....

class User implements EquatableInterface
{
    public function isEqualTo(UserInterface $user)
    {
        if ($this->password !== $user->getPassword()) {
            return false;
        }

        if ($this->salt !== $user->getSalt()) {
            return false;
        }

        if ($this->username !== $user->getUsername()) {
            return false;
        }

        return true;
    }
}

Maybe you could add the source for your User class to your question?

(ref Token was deauthenticated after trying to refresh it)

Phil Rennie
  • 376
  • 1
  • 6
0

I solved the Problem by truncating the eraseCredentials method. I probably misunderstood the purpose of this method.

Thanks for your help!